changeset 55368:0d49e7c0b4fa

Merge
author prr
date Tue, 07 May 2019 11:52:28 -0700
parents 72d194129803 61049e91eae5
children c2e4aef5edf2
files test/jdk/ProblemList.txt
diffstat 272 files changed, 7162 insertions(+), 1912 deletions(-) [+]
line wrap: on
line diff
--- a/make/InitSupport.gmk	Fri May 03 17:06:42 2019 -0700
+++ b/make/InitSupport.gmk	Tue May 07 11:52:28 2019 -0700
@@ -387,7 +387,7 @@
 	fi
         # Re-run configure with the same arguments (and possibly some additional),
         # must be done after patching.
-	( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" \
+	( cd $(CONFIGURE_START_DIR) && PATH="$(ORIGINAL_PATH)" \
 	    $(BASH) $(topdir)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF))
   endef
 
--- a/make/autoconf/flags-cflags.m4	Fri May 03 17:06:42 2019 -0700
+++ b/make/autoconf/flags-cflags.m4	Tue May 07 11:52:28 2019 -0700
@@ -219,7 +219,7 @@
           -Wunused-function -Wundef -Wunused-value -Woverloaded-virtual"
       WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2 $WARNINGS_ENABLE_ADDITIONAL"
 
-      DISABLED_WARNINGS="unused-parameter unused"
+      DISABLED_WARNINGS="unknown-warning-option unused-parameter unused"
 
       if test "x$OPENJDK_TARGET_OS" = xmacosx; then
         # missing-method-return-type triggers in JavaNativeFoundation framework
--- a/make/hotspot/lib/CompileGtest.gmk	Fri May 03 17:06:42 2019 -0700
+++ b/make/hotspot/lib/CompileGtest.gmk	Tue May 07 11:52:28 2019 -0700
@@ -76,7 +76,8 @@
     DISABLED_WARNINGS_gcc := $(DISABLED_WARNINGS_gcc) \
         undef, \
     DISABLED_WARNINGS_clang := $(DISABLED_WARNINGS_clang) \
-        undef switch format-nonliteral tautological-undefined-compare, \
+        undef switch format-nonliteral tautological-undefined-compare \
+        self-assign-overloaded, \
     DISABLED_WARNINGS_solstudio := $(DISABLED_WARNINGS_solstudio) \
         identexpected, \
     DISABLED_WARNINGS_microsoft := $(DISABLED_WARNINGS_microsoft) \
--- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java	Fri May 03 17:06:42 2019 -0700
+++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -346,17 +346,26 @@
                     if (sb.indexOf("root") == -1) {
                         sb.append("root");
                     }
-                    Bundle b = new Bundle(id, sb.toString(), null, null);
-                    // Insert the bundle for root at the top so that it will get
-                    // processed first.
-                    if ("root".equals(id)) {
-                        retList.add(0, b);
-                    } else {
-                        retList.add(b);
-                    }
+                    retList.add(new Bundle(id, sb.toString(), null, null));
                 }
             }
         }
+
+        // Sort the bundles based on id. This will make sure all the parent bundles are
+        // processed first, e.g., for en_GB bundle, en_001, and "root" comes before
+        // en_GB. In order for "root" to come at the beginning, "root" is replaced with
+        // empty string on comparison.
+        retList.sort((o1, o2) -> {
+            String id1 = o1.getID();
+            String id2 = o2.getID();
+            if(id1.equals("root")) {
+                id1 = "";
+            }
+            if(id2.equals("root")) {
+                id2 = "";
+            }
+            return id1.compareTo(id2);
+        });
         return retList;
     }
 
--- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetC1_x86.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetC1_x86.cpp	Tue May 07 11:52:28 2019 -0700
@@ -46,12 +46,14 @@
   // Apply storeval barrier to newval.
   ShenandoahBarrierSet::assembler()->storeval_barrier(masm->masm(), newval, tmp1);
 
+#ifdef _LP64
   if (UseCompressedOops) {
     __ encode_heap_oop(cmpval);
     __ mov(rscratch1, newval);
     __ encode_heap_oop(rscratch1);
     newval = rscratch1;
   }
+#endif
 
   ShenandoahBarrierSet::assembler()->cmpxchg_oop(masm->masm(), result, Address(addr, 0), cmpval, newval, false, tmp1, tmp2);
 }
--- a/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/os_cpu/aix_ppc/orderAccess_aix_ppc.hpp	Tue May 07 11:52:28 2019 -0700
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2019 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,9 +65,7 @@
 #define inlasm_eieio()    __asm__ __volatile__ ("eieio"  : : : "memory");
 #define inlasm_isync()    __asm__ __volatile__ ("isync"  : : : "memory");
 // Use twi-isync for load_acquire (faster than lwsync).
-// ATTENTION: seems like xlC 10.1 has problems with this inline assembler macro (VerifyMethodHandles found "bad vminfo in AMH.conv"):
-// #define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory");
-#define inlasm_acquire_reg(X) inlasm_lwsync();
+#define inlasm_acquire_reg(X) __asm__ __volatile__ ("twi 0,%0,0\n isync\n" : : "r" (X) : "memory");
 
 inline void OrderAccess::loadload()   { inlasm_lwsync(); }
 inline void OrderAccess::storestore() { inlasm_lwsync(); }
--- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
+ * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -302,7 +302,6 @@
   address stub = NULL;
   address pc   = NULL;
 
-  //%note os_trap_1
   if (info != NULL && uc != NULL && thread != NULL) {
     pc = (address) os::Linux::ucontext_get_pc(uc);
 
@@ -311,17 +310,17 @@
       // si_addr may not be valid due to a bug in the linux-ppc64 kernel (see
       // comment below). Use get_stack_bang_address instead of si_addr.
       // If SIGSEGV is caused due to a branch to an invalid address an
-      // "Instruction Storage" interruption is generated and 'pc' (NIP) already
+      // "Instruction Storage Interrupt" is generated and 'pc' (NIP) already
       // contains the invalid address. Otherwise, the SIGSEGV is caused due to
       // load/store instruction trying to load/store from/to an invalid address
-      // and causing a "Data Storage" interruption, so we inspect the intruction
+      // and causing a "Data Storage Interrupt", so we inspect the intruction
       // in order to extract the faulty data addresss.
       address addr;
       if ((ucontext_get_trap(uc) & 0x0F00 /* no IRQ reply bits */) == 0x0400) {
-        // Instruction interruption
+        // Instruction Storage Interrupt (ISI)
         addr = pc;
       } else {
-        // Data interruption (0x0300): extract faulty data address
+        // Data Storage Interrupt (DSI), i.e. 0x0300: extract faulty data address
         addr = ((NativeInstruction*)pc)->get_stack_bang_address(uc);
       }
 
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1988,8 +1988,9 @@
   }
 
   if (cha_monomorphic_target != NULL) {
+    assert(!target->can_be_statically_bound() || target == cha_monomorphic_target, "");
     assert(!cha_monomorphic_target->is_abstract(), "");
-    if (!target->is_final_method() && !target->is_private()) {
+    if (!cha_monomorphic_target->can_be_statically_bound(actual_recv)) {
       // If we inlined because CHA revealed only a single target method,
       // then we are dependent on that target method not getting overridden
       // by dynamic class loading.  Be sure to test the "static" receiver
--- a/src/hotspot/share/ci/ciMethod.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/ci/ciMethod.cpp	Tue May 07 11:52:28 2019 -0700
@@ -765,6 +765,14 @@
 }
 
 // ------------------------------------------------------------------
+// ciMethod::can_be_statically_bound
+//
+// Tries to determine whether a method can be statically bound in some context.
+bool ciMethod::can_be_statically_bound(ciInstanceKlass* context) const {
+  return (holder() == context) && can_be_statically_bound();
+}
+
+// ------------------------------------------------------------------
 // ciMethod::resolve_invoke
 //
 // Given a known receiver klass, find the target for the call.
--- a/src/hotspot/share/ci/ciMethod.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/ci/ciMethod.hpp	Tue May 07 11:52:28 2019 -0700
@@ -352,6 +352,8 @@
   bool is_unboxing_method() const;
   bool is_object_initializer() const;
 
+  bool can_be_statically_bound(ciInstanceKlass* context) const;
+
   // Replay data methods
   void dump_name_as_ascii(outputStream* st);
   void dump_replay_data(outputStream* st);
--- a/src/hotspot/share/code/dependencies.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/code/dependencies.cpp	Tue May 07 11:52:28 2019 -0700
@@ -108,6 +108,7 @@
 
 void Dependencies::assert_unique_concrete_method(ciKlass* ctxk, ciMethod* uniqm) {
   check_ctxk(ctxk);
+  check_unique_method(ctxk, uniqm);
   assert_common_2(unique_concrete_method, ctxk, uniqm);
 }
 
@@ -180,6 +181,7 @@
 
 void Dependencies::assert_unique_concrete_method(Klass* ctxk, Method* uniqm) {
   check_ctxk(ctxk);
+  check_unique_method(ctxk, uniqm);
   assert_common_2(unique_concrete_method, DepValue(_oop_recorder, ctxk), DepValue(_oop_recorder, uniqm));
 }
 
--- a/src/hotspot/share/code/dependencies.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/code/dependencies.hpp	Tue May 07 11:52:28 2019 -0700
@@ -27,6 +27,7 @@
 
 #include "ci/ciCallSite.hpp"
 #include "ci/ciKlass.hpp"
+#include "ci/ciMethod.hpp"
 #include "ci/ciMethodHandle.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/compressedStream.hpp"
@@ -341,6 +342,9 @@
     check_ctxk(ctxk);
     assert(!is_concrete_klass(ctxk->as_instance_klass()), "must be abstract");
   }
+  static void check_unique_method(ciKlass* ctxk, ciMethod* m) {
+    assert(!m->can_be_statically_bound(ctxk->as_instance_klass()), "redundant");
+  }
 
   void assert_common_1(DepType dept, ciBaseObject* x);
   void assert_common_2(DepType dept, ciBaseObject* x0, ciBaseObject* x1);
@@ -368,6 +372,11 @@
     check_ctxk(ctxk);
     assert(ctxk->is_abstract(), "must be abstract");
   }
+  static void check_unique_method(Klass* ctxk, Method* m) {
+    // Graal can register redundant dependencies
+    assert(UseJVMCICompiler || !m->can_be_statically_bound(InstanceKlass::cast(ctxk)), "redundant");
+  }
+
   void assert_common_1(DepType dept, DepValue x);
   void assert_common_2(DepType dept, DepValue x0, DepValue x1);
 
--- a/src/hotspot/share/compiler/compileBroker.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/compiler/compileBroker.cpp	Tue May 07 11:52:28 2019 -0700
@@ -70,7 +70,6 @@
 #if INCLUDE_JVMCI
 #include "jvmci/jvmciEnv.hpp"
 #include "jvmci/jvmciRuntime.hpp"
-#include "runtime/vframe.hpp"
 #endif
 #ifdef COMPILER2
 #include "opto/c2compiler.hpp"
@@ -1063,20 +1062,22 @@
     }
 
 #if INCLUDE_JVMCI
-    if (UseJVMCICompiler && blocking && !UseJVMCINativeLibrary) {
+    if (UseJVMCICompiler && blocking) {
       // Don't allow blocking compiles for requests triggered by JVMCI.
       if (thread->is_Compiler_thread()) {
         blocking = false;
       }
 
-      // Don't allow blocking compiles if inside a class initializer or while performing class loading
-      vframeStream vfst((JavaThread*) thread);
-      for (; !vfst.at_end(); vfst.next()) {
-        if (vfst.method()->is_static_initializer() ||
-            (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
-                vfst.method()->name() == vmSymbols::loadClass_name())) {
-          blocking = false;
-          break;
+      if (!UseJVMCINativeLibrary) {
+        // Don't allow blocking compiles if inside a class initializer or while performing class loading
+        vframeStream vfst((JavaThread*) thread);
+        for (; !vfst.at_end(); vfst.next()) {
+          if (vfst.method()->is_static_initializer() ||
+              (vfst.method()->method_holder()->is_subclass_of(SystemDictionary::ClassLoader_klass()) &&
+                  vfst.method()->name() == vmSymbols::loadClass_name())) {
+            blocking = false;
+            break;
+          }
         }
       }
 
@@ -2063,7 +2064,7 @@
       compilable = ciEnv::MethodCompilable_never;
     } else {
       JVMCICompileState compile_state(task, system_dictionary_modification_counter);
-      JVMCIEnv env(&compile_state, __FILE__, __LINE__);
+      JVMCIEnv env(thread, &compile_state, __FILE__, __LINE__);
       methodHandle method(thread, target_handle);
       env.runtime()->compile_method(&env, jvmci, method, osr_bci);
 
--- a/src/hotspot/share/compiler/compileBroker.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/compiler/compileBroker.hpp	Tue May 07 11:52:28 2019 -0700
@@ -229,7 +229,6 @@
   static JavaThread* make_thread(jobject thread_oop, CompileQueue* queue, AbstractCompiler* comp, TRAPS);
   static void init_compiler_sweeper_threads();
   static void possibly_add_compiler_threads();
-  static bool compilation_is_complete  (const methodHandle& method, int osr_bci, int comp_level);
   static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded);
   static void preload_classes          (const methodHandle& method, TRAPS);
 
@@ -285,6 +284,7 @@
     return NULL;
   }
 
+  static bool compilation_is_complete(const methodHandle& method, int osr_bci, int comp_level);
   static bool compilation_is_in_queue(const methodHandle& method);
   static void print_compile_queues(outputStream* st);
   static void print_directives(outputStream* st);
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1036,7 +1036,7 @@
 
 void G1CollectedHeap::verify_before_full_collection(bool explicit_gc) {
   assert(!GCCause::is_user_requested_gc(gc_cause()) || explicit_gc, "invariant");
-  assert(used() == recalculate_used(), "Should be equal");
+  assert_used_and_recalculate_used_equal(this);
   _verifier->verify_region_sets_optional();
   _verifier->verify_before_gc(G1HeapVerifier::G1VerifyFull);
   _verifier->check_bitmaps("Full GC Start");
@@ -1092,7 +1092,7 @@
   // the full GC has compacted objects and updated TAMS but not updated
   // the prev bitmap.
   if (G1VerifyBitmaps) {
-    GCTraceTime(Debug, gc)("Clear Prev Bitmap for Verification");
+    GCTraceTime(Debug, gc) tm("Clear Prev Bitmap for Verification");
     _cm->clear_prev_bitmap(workers());
   }
   // This call implicitly verifies that the next bitmap is clear after Full GC.
@@ -4539,9 +4539,7 @@
       _archive_allocator->clear_used();
     }
   }
-  assert(used() == recalculate_used(),
-         "inconsistent used(), value: " SIZE_FORMAT " recalculated: " SIZE_FORMAT,
-         used(), recalculate_used());
+  assert_used_and_recalculate_used_equal(this);
 }
 
 // Methods for the mutator alloc region
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue May 07 11:52:28 2019 -0700
@@ -354,6 +354,15 @@
     assert(Thread::current()->is_VM_thread(), "current thread is not VM thread"); \
   } while (0)
 
+#define assert_used_and_recalculate_used_equal(g1h)                           \
+  do {                                                                        \
+    size_t cur_used_bytes = g1h->used();                                      \
+    size_t recal_used_bytes = g1h->recalculate_used();                        \
+    assert(cur_used_bytes == recal_used_bytes, "Used(" SIZE_FORMAT ") is not" \
+           " same as recalculated used(" SIZE_FORMAT ").",                    \
+           cur_used_bytes, recal_used_bytes);                                 \
+  } while (0)
+
   const char* young_gc_name() const;
 
   // The young region list.
--- a/src/hotspot/share/gc/g1/g1FullCollector.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1FullCollector.cpp	Tue May 07 11:52:28 2019 -0700
@@ -289,6 +289,6 @@
   // fail. At the end of the GC, the original mark word values
   // (including hash values) are restored to the appropriate
   // objects.
-  GCTraceTime(Info, gc, verify)("Verifying During GC (full)");
+  GCTraceTime(Info, gc, verify) tm("Verifying During GC (full)");
   _heap->verify(VerifyOption_G1UseFullMarking);
 }
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp	Tue May 07 11:52:28 2019 -0700
@@ -65,7 +65,6 @@
   _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>(max_gc_threads, "CM RefProcessor Roots (ms):");
   _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray<double>(max_gc_threads, "Wait For Strong CLD (ms):");
   _gc_par_phases[WeakCLDRoots] = new WorkerDataArray<double>(max_gc_threads, "Weak CLD Roots (ms):");
-  _gc_par_phases[SATBFiltering] = new WorkerDataArray<double>(max_gc_threads, "SATB Filtering (ms):");
 
   _gc_par_phases[UpdateRS] = new WorkerDataArray<double>(max_gc_threads, "Update RS (ms):");
   if (G1HotCardCache::default_use_cache()) {
@@ -406,7 +405,7 @@
 
   trace_phase(_gc_par_phases[GCWorkerStart], false);
   debug_phase(_gc_par_phases[ExtRootScan]);
-  for (int i = ExtRootScanSubPhasesStart; i <= ExtRootScanSubPhasesEnd; i++) {
+  for (int i = ExtRootScanSubPhasesFirst; i <= ExtRootScanSubPhasesLast; i++) {
     trace_phase(_gc_par_phases[i]);
   }
   if (G1HotCardCache::default_use_cache()) {
@@ -531,7 +530,6 @@
       "CMRefRoots",
       "WaitForStrongCLD",
       "WeakCLDRoots",
-      "SATBFiltering",
       "UpdateRS",
       "ScanHCC",
       "ScanRS",
--- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.hpp	Tue May 07 11:52:28 2019 -0700
@@ -60,7 +60,6 @@
     CMRefRoots,
     WaitForStrongCLD,
     WeakCLDRoots,
-    SATBFiltering,
     UpdateRS,
     ScanHCC,
     ScanRS,
@@ -82,8 +81,8 @@
     GCParPhasesSentinel
   };
 
-  static const GCParPhases ExtRootScanSubPhasesStart = ThreadRoots;
-  static const GCParPhases ExtRootScanSubPhasesEnd = SATBFiltering;
+  static const GCParPhases ExtRootScanSubPhasesFirst = ThreadRoots;
+  static const GCParPhases ExtRootScanSubPhasesLast = WeakCLDRoots;
 
   enum GCScanRSWorkItems {
     ScanRSScannedCards,
--- a/src/hotspot/share/gc/g1/g1Policy.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1Policy.cpp	Tue May 07 11:52:28 2019 -0700
@@ -487,10 +487,7 @@
   assert(max_survivor_regions() + _g1h->num_used_regions() <= _g1h->max_regions(),
          "Maximum survivor regions %u plus used regions %u exceeds max regions %u",
          max_survivor_regions(), _g1h->num_used_regions(), _g1h->max_regions());
-
-  assert(_g1h->used() == _g1h->recalculate_used(),
-         "sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT,
-         _g1h->used(), _g1h->recalculate_used());
+  assert_used_and_recalculate_used_equal(_g1h);
 
   phase_times()->record_cur_collection_start_sec(start_time_sec);
   _pending_cards = _g1h->pending_card_num();
@@ -581,8 +578,8 @@
 void G1Policy::record_collection_pause_end(double pause_time_ms, size_t cards_scanned, size_t heap_used_bytes_before_gc) {
   double end_time_sec = os::elapsedTime();
 
+  assert_used_and_recalculate_used_equal(_g1h);
   size_t cur_used_bytes = _g1h->used();
-  assert(cur_used_bytes == _g1h->recalculate_used(), "It should!");
   bool this_pause_included_initial_mark = false;
   bool this_pause_was_young_only = collector_state()->in_young_only_phase();
 
--- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Tue May 07 11:52:28 2019 -0700
@@ -122,16 +122,6 @@
     assert(closures->second_pass_weak_clds() == NULL, "Should be null if not tracing metadata.");
   }
 
-  // During conc marking we have to filter the per-thread SATB buffers
-  // to make sure we remove any oops into the CSet (which will show up
-  // as implicitly live).
-  {
-    G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SATBFiltering, worker_i);
-    if (_process_strong_tasks.try_claim_task(G1RP_PS_filter_satb_buffers) && _g1h->collector_state()->mark_or_rebuild_in_progress()) {
-      G1BarrierSet::satb_mark_queue_set().filter_thread_buffers();
-    }
-  }
-
   _process_strong_tasks.all_tasks_completed(n_workers());
 }
 
--- a/src/hotspot/share/gc/g1/g1RootProcessor.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.hpp	Tue May 07 11:52:28 2019 -0700
@@ -65,7 +65,6 @@
     G1RP_PS_CodeCache_oops_do,
     AOT_ONLY(G1RP_PS_aot_oops_do COMMA)
     JVMCI_ONLY(G1RP_PS_JVMCI_oops_do COMMA)
-    G1RP_PS_filter_satb_buffers,
     G1RP_PS_refProcessor_oops_do,
     // Leave this one last.
     G1RP_PS_NumElements
--- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp	Tue May 07 11:52:28 2019 -0700
@@ -189,18 +189,6 @@
   Threads::threads_do(&closure);
 }
 
-void SATBMarkQueueSet::filter_thread_buffers() {
-  class FilterThreadBufferClosure : public ThreadClosure {
-    SATBMarkQueueSet* _qset;
-  public:
-    FilterThreadBufferClosure(SATBMarkQueueSet* qset) : _qset(qset) {}
-    virtual void do_thread(Thread* t) {
-      _qset->satb_queue_for_thread(t).filter();
-    }
-  } closure(this);
-  Threads::threads_do(&closure);
-}
-
 bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) {
   BufferNode* nd = get_completed_buffer();
   if (nd != NULL) {
--- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp	Tue May 07 11:52:28 2019 -0700
@@ -125,9 +125,6 @@
   size_t buffer_enqueue_threshold() const { return _buffer_enqueue_threshold; }
   virtual void filter(SATBMarkQueue* queue) = 0;
 
-  // Filter all the currently-active SATB buffers.
-  void filter_thread_buffers();
-
   // If there exists some completed buffer, pop and process it, and
   // return true.  Otherwise return false.  Processing a buffer
   // consists of applying the closure to the active range of the
--- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1333,8 +1333,8 @@
         }
       }
     }
-    if (ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) {
-      CallNode* call = ctrl->in(0)->as_CallJava();
+    if ((ctrl->is_Proj() && ctrl->in(0)->is_CallJava()) || ctrl->is_CallJava()) {
+      CallNode* call = ctrl->is_Proj() ? ctrl->in(0)->as_CallJava() : ctrl->as_CallJava();
       CallProjections projs;
       call->extract_projections(&projs, false, false);
 
@@ -1362,7 +1362,7 @@
         if (idx < n->outcnt()) {
           Node* u = n->raw_out(idx);
           Node* c = phase->ctrl_or_self(u);
-          if (c == ctrl) {
+          if (phase->is_dominator(call, c) && phase->is_dominator(c, projs.fallthrough_proj)) {
             stack.set_index(idx+1);
             assert(!u->is_CFG(), "");
             stack.push(u, 0);
@@ -1404,14 +1404,11 @@
             }
           }
         } else {
-          // assert(n_clone->outcnt() > 0, "");
-          // assert(n->outcnt() > 0, "");
           stack.pop();
           clones.pop();
         }
       } while (stack.size() > 0);
       assert(stack.size() == 0 && clones.size() == 0, "");
-      ctrl = projs.fallthrough_catchproj;
     }
   }
 
@@ -1950,6 +1947,9 @@
               head->verify_strip_mined(0);
             }
             move_heap_stable_test_out_of_loop(iff, phase);
+
+            AutoNodeBudget node_budget(phase);
+
             if (loop->policy_unswitching(phase)) {
               if (head->is_strip_mined()) {
                 OuterStripMinedLoopNode* outer = head->as_CountedLoop()->outer_loop();
--- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp	Tue May 07 11:52:28 2019 -0700
@@ -45,10 +45,13 @@
   FLAG_SET_DEFAULT(ShenandoahGCHeuristics,           "passive");
 
   FLAG_SET_DEFAULT(ShenandoahSATBBarrier,            false);
+  FLAG_SET_DEFAULT(ShenandoahLoadRefBarrier,         false);
   FLAG_SET_DEFAULT(ShenandoahKeepAliveBarrier,       false);
   FLAG_SET_DEFAULT(ShenandoahStoreValEnqueueBarrier, false);
   FLAG_SET_DEFAULT(ShenandoahCASBarrier,             false);
   FLAG_SET_DEFAULT(ShenandoahCloneBarrier,           false);
+
+  FLAG_SET_DEFAULT(ShenandoahVerifyOptoBarriers,     false);
 #endif
 
 #ifdef _LP64
@@ -106,6 +109,7 @@
   // C2 barrier verification is only reliable when all default barriers are enabled
   if (ShenandoahVerifyOptoBarriers &&
           (!FLAG_IS_DEFAULT(ShenandoahSATBBarrier)            ||
+           !FLAG_IS_DEFAULT(ShenandoahLoadRefBarrier)         ||
            !FLAG_IS_DEFAULT(ShenandoahKeepAliveBarrier)       ||
            !FLAG_IS_DEFAULT(ShenandoahStoreValEnqueueBarrier) ||
            !FLAG_IS_DEFAULT(ShenandoahCASBarrier)             ||
--- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp	Tue May 07 11:52:28 2019 -0700
@@ -89,7 +89,6 @@
 
   AlwaysTrueClosure always_true;
   WeakProcessor::weak_oops_do(&always_true, oops);
-  JvmtiExport::weak_oops_do(&always_true, oops);
 
   if (ShenandoahStringDedup::is_enabled()) {
     ShenandoahStringDedup::oops_do_slow(oops);
--- a/src/hotspot/share/gc/z/zGranuleMap.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/z/zGranuleMap.hpp	Tue May 07 11:52:28 2019 -0700
@@ -35,10 +35,10 @@
   friend class ZGranuleMapIterator<T>;
 
 private:
-  T* const _map;
+  const size_t _size;
+  T* const     _map;
 
   size_t index_for_addr(uintptr_t addr) const;
-  size_t size() const;
 
 public:
   ZGranuleMap();
--- a/src/hotspot/share/gc/z/zGranuleMap.inline.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/gc/z/zGranuleMap.inline.hpp	Tue May 07 11:52:28 2019 -0700
@@ -31,11 +31,12 @@
 
 template <typename T>
 inline ZGranuleMap<T>::ZGranuleMap() :
-    _map(MmapArrayAllocator<T>::allocate(size(), mtGC)) {}
+    _size(ZAddressOffsetMax >> ZGranuleSizeShift),
+    _map(MmapArrayAllocator<T>::allocate(_size, mtGC)) {}
 
 template <typename T>
 inline ZGranuleMap<T>::~ZGranuleMap() {
-  MmapArrayAllocator<T>::free(_map, size());
+  MmapArrayAllocator<T>::free(_map, _size);
 }
 
 template <typename T>
@@ -43,17 +44,12 @@
   assert(!ZAddress::is_null(addr), "Invalid address");
 
   const size_t index = ZAddress::offset(addr) >> ZGranuleSizeShift;
-  assert(index < size(), "Invalid index");
+  assert(index < _size, "Invalid index");
 
   return index;
 }
 
 template <typename T>
-inline size_t ZGranuleMap<T>::size() const {
-  return ZAddressOffsetMax >> ZGranuleSizeShift;
-}
-
-template <typename T>
 inline T ZGranuleMap<T>::get(uintptr_t addr) const {
   const size_t index = index_for_addr(addr);
   return _map[index];
@@ -83,7 +79,7 @@
 
 template <typename T>
 inline bool ZGranuleMapIterator<T>::next(T* value) {
-  if (_next < _map->size()) {
+  if (_next < _map->_size) {
     *value = _map->_map[_next++];
     return true;
   }
@@ -94,7 +90,7 @@
 
 template <typename T>
 inline bool ZGranuleMapIterator<T>::next(T** value) {
-  if (_next < _map->size()) {
+  if (_next < _map->_size) {
     *value = _map->_map + _next++;
     return true;
   }
--- a/src/hotspot/share/interpreter/abstractInterpreter.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp	Tue May 07 11:52:28 2019 -0700
@@ -28,6 +28,7 @@
 #include "compiler/disassembler.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
 #include "interpreter/bytecodeInterpreter.hpp"
+#include "interpreter/bytecodeStream.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/interp_masm.hpp"
@@ -36,6 +37,8 @@
 #include "memory/metaspaceShared.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/arrayOop.hpp"
+#include "oops/constantPool.hpp"
+#include "oops/cpCache.inline.hpp"
 #include "oops/methodData.hpp"
 #include "oops/method.hpp"
 #include "oops/oop.inline.hpp"
@@ -240,9 +243,36 @@
 // Return true if the interpreter can prove that the given bytecode has
 // not yet been executed (in Java semantics, not in actual operation).
 bool AbstractInterpreter::is_not_reached(const methodHandle& method, int bci) {
-  Bytecodes::Code code = method()->code_at(bci);
+  BytecodeStream s(method, bci);
+  Bytecodes::Code code = s.next();
 
-  if (!Bytecodes::must_rewrite(code)) {
+  if (Bytecodes::is_invoke(code)) {
+    assert(!Bytecodes::must_rewrite(code), "invokes aren't rewritten");
+    ConstantPool* cpool = method()->constants();
+
+    Bytecode invoke_bc(s.bytecode());
+
+    switch (code) {
+      case Bytecodes::_invokedynamic: {
+        assert(invoke_bc.has_index_u4(code), "sanity");
+        int method_index = invoke_bc.get_index_u4(code);
+        return cpool->invokedynamic_cp_cache_entry_at(method_index)->is_f1_null();
+      }
+      case Bytecodes::_invokevirtual:   // fall-through
+      case Bytecodes::_invokeinterface: // fall-through
+      case Bytecodes::_invokespecial:   // fall-through
+      case Bytecodes::_invokestatic: {
+        if (cpool->has_preresolution()) {
+          return false; // might have been reached
+        }
+        assert(!invoke_bc.has_index_u4(code), "sanity");
+        int method_index = invoke_bc.get_index_u2_cpcache(code);
+        Method* resolved_method = ConstantPool::method_at_if_loaded(cpool, method_index);
+        return (resolved_method == NULL);
+      }
+      default: ShouldNotReachHere();
+    }
+  } else if (!Bytecodes::must_rewrite(code)) {
     // might have been reached
     return false;
   }
--- a/src/hotspot/share/interpreter/bytecodeStream.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/interpreter/bytecodeStream.hpp	Tue May 07 11:52:28 2019 -0700
@@ -170,6 +170,10 @@
   // Construction
   BytecodeStream(const methodHandle& method) : BaseBytecodeStream(method) { }
 
+  BytecodeStream(const methodHandle& method, int bci) : BaseBytecodeStream(method) {
+    set_start(bci);
+  }
+
   // Iteration
   Bytecodes::Code next() {
     Bytecodes::Code raw_code, code;
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Tue May 07 11:52:28 2019 -0700
@@ -62,12 +62,17 @@
   return *this;
 }
 
-void JNIHandleMark::push_jni_handle_block() {
-  JavaThread* thread = JavaThread::current();
+static void requireInHotSpot(const char* caller, JVMCI_TRAPS) {
+  if (!JVMCIENV->is_hotspot()) {
+    JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot call %s from JVMCI shared library", caller));
+  }
+}
+
+void JNIHandleMark::push_jni_handle_block(JavaThread* thread) {
   if (thread != NULL) {
     // Allocate a new block for JNI handles.
     // Inlined code from jni_PushLocalFrame()
-    JNIHandleBlock* java_handles = ((JavaThread*)thread)->active_handles();
+    JNIHandleBlock* java_handles = thread->active_handles();
     JNIHandleBlock* compile_handles = JNIHandleBlock::allocate_block(thread);
     assert(compile_handles != NULL && java_handles != NULL, "should not be NULL");
     compile_handles->set_pop_frame_link(java_handles);
@@ -75,8 +80,7 @@
   }
 }
 
-void JNIHandleMark::pop_jni_handle_block() {
-  JavaThread* thread = JavaThread::current();
+void JNIHandleMark::pop_jni_handle_block(JavaThread* thread) {
   if (thread != NULL) {
     // Release our JNI handle block
     JNIHandleBlock* compile_handles = thread->active_handles();
@@ -111,25 +115,88 @@
   return Handle(Thread::current(), arg);
 }
 
-// Entry to native method implementation that transitions current thread to '_thread_in_vm'.
+// Bring the JVMCI compiler thread into the VM state.
+#define JVMCI_VM_ENTRY_MARK                   \
+  ThreadInVMfromNative __tiv(thread);         \
+  ResetNoHandleMark rnhm;                     \
+  HandleMarkCleaner __hm(thread);             \
+  Thread* THREAD = thread;                    \
+  debug_only(VMNativeEntryWrapper __vew;)
+
+// Native method block that transitions current thread to '_thread_in_vm'.
+#define C2V_BLOCK(result_type, name, signature)      \
+  TRACE_CALL(result_type, jvmci_ ## name signature)  \
+  JVMCI_VM_ENTRY_MARK;                               \
+  ResourceMark rm;                                   \
+  JNI_JVMCIENV(thread, env);
+
+static Thread* get_current_thread() {
+  return Thread::current_or_null_safe();
+}
+
+// Entry to native method implementation that transitions
+// current thread to '_thread_in_vm'.
 #define C2V_VMENTRY(result_type, name, signature)        \
   JNIEXPORT result_type JNICALL c2v_ ## name signature { \
+  Thread* base_thread = get_current_thread();            \
+  if (base_thread == NULL) {                             \
+    env->ThrowNew(JNIJVMCI::InternalError::clazz(),      \
+        err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \
+    return;                                              \
+  }                                                      \
+  assert(base_thread->is_Java_thread(), "just checking");\
+  JavaThread* thread = (JavaThread*) base_thread;        \
   JVMCITraceMark jtm("CompilerToVM::" #name);            \
-  TRACE_CALL(result_type, jvmci_ ## name signature)      \
-  JVMCI_VM_ENTRY_MARK;                                   \
-  ResourceMark rm;                                       \
-  JNI_JVMCIENV(env);
+  C2V_BLOCK(result_type, name, signature)
+
+#define C2V_VMENTRY_(result_type, name, signature, result) \
+  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
+  Thread* base_thread = get_current_thread();            \
+  if (base_thread == NULL) {                             \
+    env->ThrowNew(JNIJVMCI::InternalError::clazz(),      \
+        err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \
+    return result;                                       \
+  }                                                      \
+  assert(base_thread->is_Java_thread(), "just checking");\
+  JavaThread* thread = (JavaThread*) base_thread;        \
+  JVMCITraceMark jtm("CompilerToVM::" #name);            \
+  C2V_BLOCK(result_type, name, signature)
+
+#define C2V_VMENTRY_NULL(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, NULL)
+#define C2V_VMENTRY_0(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, 0)
+
+// Entry to native method implementation that does not transition
+// current thread to '_thread_in_vm'.
+#define C2V_VMENTRY_PREFIX(result_type, name, signature) \
+  JNIEXPORT result_type JNICALL c2v_ ## name signature { \
+  Thread* base_thread = get_current_thread();
 
 #define C2V_END }
 
+#define JNI_THROW(caller, name, msg) do {                                         \
+    jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg);               \
+    if (__throw_res != JNI_OK) {                                                  \
+      tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \
+    }                                                                             \
+    return;                                                                       \
+  } while (0);
+
+#define JNI_THROW_(caller, name, msg, result) do {                                \
+    jint __throw_res = env->ThrowNew(JNIJVMCI::name::clazz(), msg);               \
+    if (__throw_res != JNI_OK) {                                                  \
+      tty->print_cr("Throwing " #name " in " caller " returned %d", __throw_res); \
+    }                                                                             \
+    return result;                                                                \
+  } while (0)
+
 jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS);
 
-C2V_VMENTRY(jobjectArray, readConfiguration, (JNIEnv* env))
+C2V_VMENTRY_NULL(jobjectArray, readConfiguration, (JNIEnv* env))
   jobjectArray config = readConfiguration0(env, JVMCI_CHECK_NULL);
   return config;
 }
 
-C2V_VMENTRY(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name_handle))
+C2V_VMENTRY_NULL(jobject, getFlagValue, (JNIEnv* env, jobject c2vm, jobject name_handle))
 #define RETURN_BOXED_LONG(value) jvalue p; p.j = (jlong) (value); JVMCIObject box = JVMCIENV->create_box(T_LONG, &p, JVMCI_CHECK_NULL); return box.as_jobject();
 #define RETURN_BOXED_DOUBLE(value) jvalue p; p.d = (jdouble) (value); JVMCIObject box = JVMCIENV->create_box(T_DOUBLE, &p, JVMCI_CHECK_NULL); return box.as_jobject();
   JVMCIObject name = JVMCIENV->wrap(name_handle);
@@ -170,10 +237,8 @@
 #undef RETURN_BOXED_DOUBLE
 C2V_END
 
-C2V_VMENTRY(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong oop_address))
-  if (env != JavaThread::current()->jni_environment()) {
-    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
-  }
+C2V_VMENTRY_NULL(jobject, getObjectAtAddress, (JNIEnv* env, jobject c2vm, jlong oop_address))
+  requireInHotSpot("getObjectAtAddress", JVMCI_CHECK_NULL);
   if (oop_address == 0) {
     JVMCI_THROW_MSG_NULL(InternalError, "Handle must be non-zero");
   }
@@ -184,7 +249,7 @@
   return JNIHandles::make_local(obj);
 C2V_END
 
-C2V_VMENTRY(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
 
   int code_size = method->code_size();
@@ -262,12 +327,12 @@
   return JVMCIENV->get_jbyteArray(result);
 C2V_END
 
-C2V_VMENTRY(jint, getExceptionTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jint, getExceptionTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return method->exception_table_length();
 C2V_END
 
-C2V_VMENTRY(jlong, getExceptionTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jlong, getExceptionTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   if (method->exception_table_length() == 0) {
     return 0L;
@@ -275,11 +340,8 @@
   return (jlong) (address) method->exception_table_start();
 C2V_END
 
-C2V_VMENTRY(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject executable_handle))
-  if (env != JavaThread::current()->jni_environment()) {
-    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
-  }
-
+C2V_VMENTRY_NULL(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject executable_handle))
+  requireInHotSpot("asResolvedJavaMethod", JVMCI_CHECK_NULL);
   oop executable = JNIHandles::resolve(executable_handle);
   oop mirror = NULL;
   int slot = 0;
@@ -298,7 +360,7 @@
   return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset))
+C2V_VMENTRY_NULL(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset))
   methodHandle method;
   JVMCIObject base_object = JVMCIENV->wrap(base);
   if (base_object.is_null()) {
@@ -321,7 +383,7 @@
   return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getConstantPool, (JNIEnv* env, jobject, jobject object_handle))
+C2V_VMENTRY_NULL(jobject, getConstantPool, (JNIEnv* env, jobject, jobject object_handle))
   constantPoolHandle cp;
   JVMCIObject object = JVMCIENV->wrap(object_handle);
   if (object.is_null()) {
@@ -341,7 +403,7 @@
   return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed))
+C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed))
   JVMCIKlassHandle klass(THREAD);
   JVMCIObject base_object = JVMCIENV->wrap(base);
   jlong base_address = 0;
@@ -384,7 +446,7 @@
   return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
+C2V_VMENTRY_NULL(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   Klass* holder = JVMCIENV->asKlass(jvmci_type);
   if (holder->is_interface()) {
@@ -400,7 +462,7 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, getImplementor, (JNIEnv* env, jobject, jobject jvmci_type))
+C2V_VMENTRY_NULL(jobject, getImplementor, (JNIEnv* env, jobject, jobject jvmci_type))
   Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_interface()) {
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@@ -417,12 +479,12 @@
   return JVMCIENV->get_jobject(implementor);
 C2V_END
 
-C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return method->is_ignored_by_security_stack_walk();
 C2V_END
 
-C2V_VMENTRY(jboolean, isCompilable,(JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jboolean, isCompilable,(JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   constantPoolHandle cp = method->constMethod()->constants();
   assert(!cp.is_null(), "npe");
@@ -430,17 +492,17 @@
   return !method->is_not_compilable(CompLevel_full_optimization) && !cp->has_dynamic_constant();
 C2V_END
 
-C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jboolean, hasNeverInlineDirective,(JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return !Inline || CompilerOracle::should_not_inline(method) || method->dont_inline();
 C2V_END
 
-C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   return CompilerOracle::should_inline(method) || method->force_inline();
 C2V_END
 
-C2V_VMENTRY(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jclass accessing_class, jboolean resolve))
+C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, jclass accessing_class, jboolean resolve))
   JVMCIObject name = JVMCIENV->wrap(jname);
   const char* str = JVMCIENV->as_utf8_string(name);
   TempNewSymbol class_name = SymbolTable::new_symbol(str, CHECK_NULL);
@@ -465,6 +527,9 @@
 
   if (resolve) {
     resolved_klass = SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK_0);
+    if (resolved_klass == NULL) {
+      JVMCI_THROW_MSG_NULL(ClassNotFoundException, str);
+    }
   } else {
     if (class_name->char_at(0) == 'L' &&
       class_name->char_at(class_name->utf8_length()-1) == ';') {
@@ -483,7 +548,6 @@
         TempNewSymbol strippedsym = SymbolTable::new_symbol(class_name->as_utf8()+1+fd.dimension(),
                                                             class_name->utf8_length()-2-fd.dimension(),
                                                             CHECK_0);
-        // naked oop "k" is OK here -- we assign back into it
         resolved_klass = SystemDictionary::find(strippedsym,
                                                              class_loader,
                                                              protection_domain,
@@ -502,10 +566,8 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror))
-  if (env != JavaThread::current()->jni_environment()) {
-    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
-  }
+C2V_VMENTRY_NULL(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror))
+  requireInHotSpot("lookupClass", JVMCI_CHECK_NULL);
   if (mirror == NULL) {
     return NULL;
   }
@@ -518,52 +580,56 @@
   return JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jobject, resolveConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_NULL(jobject, resolveConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop result = cp->resolve_constant_at(index, CHECK_NULL);
   return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result));
 C2V_END
 
-C2V_VMENTRY(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_NULL(jobject, resolvePossiblyCachedConstantInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop result = cp->resolve_possibly_cached_constant_at(index, CHECK_NULL);
   return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(result));
 C2V_END
 
-C2V_VMENTRY(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_0(jint, lookupNameAndTypeRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->name_and_type_ref_index_at(index);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupNameInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
+C2V_VMENTRY_NULL(jobject, lookupNameInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   JVMCIObject sym = JVMCIENV->create_string(cp->name_ref_at(which), JVMCI_CHECK_NULL);
   return JVMCIENV->get_jobject(sym);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupSignatureInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
+C2V_VMENTRY_NULL(jobject, lookupSignatureInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint which))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   JVMCIObject sym = JVMCIENV->create_string(cp->signature_ref_at(which), JVMCI_CHECK_NULL);
   return JVMCIENV->get_jobject(sym);
 C2V_END
 
-C2V_VMENTRY(jint, lookupKlassRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_0(jint, lookupKlassRefIndexInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->klass_ref_index_at(index);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveTypeInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_NULL(jobject, resolveTypeInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* klass = cp->klass_at(index, CHECK_NULL);
   JVMCIKlassHandle resolved_klass(THREAD, klass);
   if (resolved_klass->is_instance_klass()) {
-    InstanceKlass::cast(resolved_klass())->link_class_or_fail(THREAD);
+    InstanceKlass::cast(resolved_klass())->link_class(CHECK_NULL);
+    if (!InstanceKlass::cast(resolved_klass())->is_linked()) {
+      // link_class() should not return here if there is an issue.
+      JVMCI_THROW_MSG_NULL(InternalError, err_msg("Class %s must be linked", resolved_klass()->external_name()));
+    }
   }
   JVMCIObject klassObject = JVMCIENV->get_jvmci_type(resolved_klass, JVMCI_CHECK_NULL);
   return JVMCIENV->get_jobject(klassObject);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupKlassInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+C2V_VMENTRY_NULL(jobject, lookupKlassInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Klass* loading_klass = cp->pool_holder();
   bool is_accessible = false;
@@ -591,13 +657,13 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_NULL(jobject, lookupAppendixInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   oop appendix_oop = ConstantPool::appendix_at_if_loaded(cp, index);
   return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(appendix_oop));
 C2V_END
 
-C2V_VMENTRY(jobject, lookupMethodInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
+C2V_VMENTRY_NULL(jobject, lookupMethodInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jbyte opcode))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   InstanceKlass* pool_holder = cp->pool_holder();
   Bytecodes::Code bc = (Bytecodes::Code) (((int) opcode) & 0xFF);
@@ -606,12 +672,12 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_0(jint, constantPoolRemapInstructionOperandFromCache, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   return cp->remap_instruction_operand_from_cache(index);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveFieldInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle))
+C2V_VMENTRY_NULL(jobject, resolveFieldInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index, jobject jvmci_method, jbyte opcode, jintArray info_handle))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   Bytecodes::Code code = (Bytecodes::Code)(((int) opcode) & 0xFF);
   fieldDescriptor fd;
@@ -629,7 +695,7 @@
   return JVMCIENV->get_jobject(field_holder);
 C2V_END
 
-C2V_VMENTRY(jint, getVtableIndexForInterfaceMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
+C2V_VMENTRY_0(jint, getVtableIndexForInterfaceMethod, (JNIEnv* env, jobject, jobject jvmci_type, jobject jvmci_method))
   Klass* klass = JVMCIENV->asKlass(jvmci_type);
   Method* method = JVMCIENV->asMethod(jvmci_method);
   if (klass->is_interface()) {
@@ -647,7 +713,7 @@
   return LinkResolver::vtable_index_of_interface_method(klass, method);
 C2V_END
 
-C2V_VMENTRY(jobject, resolveMethod, (JNIEnv* env, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
+C2V_VMENTRY_NULL(jobject, resolveMethod, (JNIEnv* env, jobject, jobject receiver_jvmci_type, jobject jvmci_method, jobject caller_jvmci_type))
   Klass* recv_klass = JVMCIENV->asKlass(receiver_jvmci_type);
   Klass* caller_klass = JVMCIENV->asKlass(caller_jvmci_type);
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
@@ -694,13 +760,13 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, jobject jvmci_type))
+C2V_VMENTRY_0(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, jobject jvmci_type))
   Klass* klass = JVMCIENV->asKlass(jvmci_type);
   assert(klass != NULL, "method must not be called for primitive types");
   return Dependencies::find_finalizable_subclass(klass) != NULL;
 C2V_END
 
-C2V_VMENTRY(jobject, getClassInitializer, (JNIEnv* env, jobject, jobject jvmci_type))
+C2V_VMENTRY_NULL(jobject, getClassInitializer, (JNIEnv* env, jobject, jobject jvmci_type))
   Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_instance_klass()) {
     return NULL;
@@ -710,7 +776,7 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jlong, getMaxCallTargetOffset, (JNIEnv* env, jobject, jlong addr))
+C2V_VMENTRY_0(jlong, getMaxCallTargetOffset, (JNIEnv* env, jobject, jlong addr))
   address target_addr = (address) addr;
   if (target_addr != 0x0) {
     int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int));
@@ -727,10 +793,10 @@
   method->set_dont_inline(true);
 C2V_END
 
-C2V_VMENTRY(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject compiled_code,
+C2V_VMENTRY_0(jint, installCode, (JNIEnv *env, jobject, jobject target, jobject compiled_code,
             jobject installed_code, jlong failed_speculations_address, jbyteArray speculations_obj))
   HandleMark hm;
-  JNIHandleMark jni_hm;
+  JNIHandleMark jni_hm(thread);
 
   JVMCIObject target_handle = JVMCIENV->wrap(target);
   JVMCIObject compiled_code_handle = JVMCIENV->wrap(compiled_code);
@@ -788,7 +854,7 @@
   return result;
 C2V_END
 
-C2V_VMENTRY(jint, getMetadata, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject metadata))
+C2V_VMENTRY_0(jint, getMetadata, (JNIEnv *env, jobject, jobject target, jobject compiled_code, jobject metadata))
 #if INCLUDE_AOT
   HandleMark hm;
   assert(JVMCIENV->is_hotspot(), "AOT code is executed only in HotSpot mode");
@@ -869,7 +935,7 @@
   stats->_osr.reset();
 C2V_END
 
-C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv* env, jobject, jobject installedCode))
+C2V_VMENTRY_NULL(jobject, disassembleCodeBlob, (JNIEnv* env, jobject, jobject installedCode))
   HandleMark hm;
 
   if (installedCode == NULL) {
@@ -906,7 +972,7 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, getStackTraceElement, (JNIEnv* env, jobject, jobject jvmci_method, int bci))
+C2V_VMENTRY_NULL(jobject, getStackTraceElement, (JNIEnv* env, jobject, jobject jvmci_method, int bci))
   HandleMark hm;
 
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
@@ -914,12 +980,10 @@
   return JVMCIENV->get_jobject(element);
 C2V_END
 
-C2V_VMENTRY(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject args, jobject hs_nmethod))
-  if (env != JavaThread::current()->jni_environment()) {
-    // The incoming arguments array would have to contain JavaConstants instead of regular objects
-    // and the return value would have to be wrapped as a JavaConstant.
-    JVMCI_THROW_MSG_NULL(InternalError, "Wrapping of arguments is currently unsupported");
-  }
+C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject args, jobject hs_nmethod))
+  // The incoming arguments array would have to contain JavaConstants instead of regular objects
+  // and the return value would have to be wrapped as a JavaConstant.
+  requireInHotSpot("executeHotSpotNmethod", JVMCI_CHECK_NULL);
 
   HandleMark hm;
 
@@ -965,7 +1029,7 @@
   }
 C2V_END
 
-C2V_VMENTRY(jlongArray, getLineNumberTable, (JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_NULL(jlongArray, getLineNumberTable, (JNIEnv* env, jobject, jobject jvmci_method))
   Method* method = JVMCIENV->asMethod(jvmci_method);
   if (!method->has_linenumber_table()) {
     return NULL;
@@ -992,7 +1056,7 @@
   return (jlongArray) JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jlong, getLocalVariableTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jlong, getLocalVariableTableStart, (JNIEnv* env, jobject, jobject jvmci_method))
   Method* method = JVMCIENV->asMethod(jvmci_method);
   if (!method->has_localvariable_table()) {
     return 0;
@@ -1000,7 +1064,7 @@
   return (jlong) (address) method->localvariable_table_start();
 C2V_END
 
-C2V_VMENTRY(jint, getLocalVariableTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jint, getLocalVariableTableLength, (JNIEnv* env, jobject, jobject jvmci_method))
   Method* method = JVMCIENV->asMethod(jvmci_method);
   return method->localvariable_table_length();
 C2V_END
@@ -1034,18 +1098,23 @@
   JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, JVMCI_CHECK);
 C2V_END
 
-C2V_VMENTRY(jobject, readUncompressedOop, (JNIEnv* env, jobject, jlong addr))
+C2V_VMENTRY_NULL(jobject, readUncompressedOop, (JNIEnv* env, jobject, jlong addr))
   oop ret = RawAccess<>::oop_load((oop*)(address)addr);
   return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(ret));
  C2V_END
 
-C2V_VMENTRY(jlongArray, collectCounters, (JNIEnv* env, jobject))
+C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject))
+  // Returns a zero length array if counters aren't enabled
   JVMCIPrimitiveArray array = JVMCIENV->new_longArray(JVMCICounterSize, JVMCI_CHECK_NULL);
-  JavaThread::collect_counters(JVMCIENV, array);
+  if (JVMCICounterSize > 0) {
+    jlong* temp_array = NEW_RESOURCE_ARRAY(jlong, JVMCICounterSize);
+    JavaThread::collect_counters(temp_array, JVMCICounterSize);
+    JVMCIENV->copy_longs_from(temp_array, array, 0, JVMCICounterSize);
+  }
   return (jlongArray) JVMCIENV->get_jobject(array);
 C2V_END
 
-C2V_VMENTRY(int, allocateCompileId, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci))
+C2V_VMENTRY_0(int, allocateCompileId, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci))
   HandleMark hm;
   if (jvmci_method == NULL) {
     JVMCI_THROW_0(NullPointerException);
@@ -1058,17 +1127,17 @@
 C2V_END
 
 
-C2V_VMENTRY(jboolean, isMature, (JNIEnv* env, jobject, jlong metaspace_method_data))
+C2V_VMENTRY_0(jboolean, isMature, (JNIEnv* env, jobject, jlong metaspace_method_data))
   MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data);
   return mdo != NULL && mdo->is_mature();
 C2V_END
 
-C2V_VMENTRY(jboolean, hasCompiledCodeForOSR, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci, int comp_level))
+C2V_VMENTRY_0(jboolean, hasCompiledCodeForOSR, (JNIEnv* env, jobject, jobject jvmci_method, int entry_bci, int comp_level))
   Method* method = JVMCIENV->asMethod(jvmci_method);
   return method->lookup_osr_nmethod_for(entry_bci, comp_level, true) != NULL;
 C2V_END
 
-C2V_VMENTRY(jobject, getSymbol, (JNIEnv* env, jobject, jlong symbol))
+C2V_VMENTRY_NULL(jobject, getSymbol, (JNIEnv* env, jobject, jlong symbol))
   JVMCIObject sym = JVMCIENV->create_string((Symbol*)(address)symbol, JVMCI_CHECK_NULL);
   return JVMCIENV->get_jobject(sym);
 C2V_END
@@ -1099,16 +1168,14 @@
   JavaCalls::call(result, method, args, CHECK);
 }
 
-C2V_VMENTRY(jobject, iterateFrames, (JNIEnv* env, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle))
+C2V_VMENTRY_NULL(jobject, iterateFrames, (JNIEnv* env, jobject compilerToVM, jobjectArray initial_methods, jobjectArray match_methods, jint initialSkip, jobject visitor_handle))
 
   if (!thread->has_last_Java_frame()) {
     return NULL;
   }
   Handle visitor(THREAD, JNIHandles::resolve_non_null(visitor_handle));
 
-  if (env != JavaThread::current()->jni_environment()) {
-    JVMCI_THROW_MSG_NULL(InternalError, "getNextStackFrame is only supported for HotSpot stack walking");
-  }
+  requireInHotSpot("iterateFrames", JVMCI_CHECK_NULL);
 
   HotSpotJVMCI::HotSpotStackFrameReference::klass()->initialize(CHECK_NULL);
   Handle frame_reference = HotSpotJVMCI::HotSpotStackFrameReference::klass()->allocate_instance_handle(CHECK_NULL);
@@ -1280,7 +1347,7 @@
   }
 C2V_END
 
-C2V_VMENTRY(jint, isResolvedInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
+C2V_VMENTRY_0(jint, isResolvedInvokeHandleInPool, (JNIEnv* env, jobject, jobject jvmci_constant_pool, jint index))
   constantPoolHandle cp = JVMCIENV->asConstantPool(jvmci_constant_pool);
   ConstantPoolCacheEntry* cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
   if (cp_cache_entry->is_resolved(Bytecodes::_invokehandle)) {
@@ -1321,7 +1388,7 @@
 C2V_END
 
 
-C2V_VMENTRY(jobject, getSignaturePolymorphicHolders, (JNIEnv* env, jobject))
+C2V_VMENTRY_NULL(jobject, getSignaturePolymorphicHolders, (JNIEnv* env, jobject))
   JVMCIObjectArray holders = JVMCIENV->new_String_array(2, JVMCI_CHECK_NULL);
   JVMCIObject mh = JVMCIENV->create_string("Ljava/lang/invoke/MethodHandle;", JVMCI_CHECK_NULL);
   JVMCIObject vh = JVMCIENV->create_string("Ljava/lang/invoke/VarHandle;", JVMCI_CHECK_NULL);
@@ -1330,7 +1397,7 @@
   return JVMCIENV->get_jobject(holders);
 C2V_END
 
-C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv* env, jobject))
+C2V_VMENTRY_0(jboolean, shouldDebugNonSafepoints, (JNIEnv* env, jobject))
   //see compute_recording_non_safepoints in debugInfroRec.cpp
   if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
     return true;
@@ -1345,9 +1412,7 @@
     JVMCI_THROW_MSG(NullPointerException, "stack frame is null");
   }
 
-  if (env != JavaThread::current()->jni_environment()) {
-    JVMCI_THROW_MSG(InternalError, "getNextStackFrame is only supported for HotSpot stack walking");
-  }
+  requireInHotSpot("materializeVirtualObjects", JVMCI_CHECK);
 
   JVMCIENV->HotSpotStackFrameReference_initialize(JVMCI_CHECK);
 
@@ -1462,20 +1527,76 @@
   HotSpotJVMCI::HotSpotStackFrameReference::set_objectsMaterialized(JVMCIENV, hs_frame, JNI_TRUE);
 C2V_END
 
-C2V_VMENTRY(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length))
+// Creates a scope where the current thread is attached and detached
+// from HotSpot if it wasn't already attached when entering the scope.
+extern "C" void jio_printf(const char *fmt, ...);
+class AttachDetach : public StackObj {
+ public:
+  bool _attached;
+  AttachDetach(JNIEnv* env, Thread* current_thread) {
+    if (current_thread == NULL) {
+      extern struct JavaVM_ main_vm;
+      JNIEnv* hotspotEnv;
+      jint res = main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL);
+      _attached = res == JNI_OK;
+      static volatile int report_attach_error = 0;
+      if (res != JNI_OK && report_attach_error == 0 && Atomic::cmpxchg(1, &report_attach_error, 0) == 0) {
+        // Only report an attach error once
+        jio_printf("Warning: attaching current thread to VM failed with %d (future attach errors are suppressed)\n", res);
+      }
+    } else {
+      _attached = false;
+    }
+  }
+  ~AttachDetach() {
+    if (_attached && get_current_thread() != NULL) {
+      extern struct JavaVM_ main_vm;
+      jint res = main_vm.DetachCurrentThread();
+      static volatile int report_detach_error = 0;
+      if (res != JNI_OK && report_detach_error == 0 && Atomic::cmpxchg(1, &report_detach_error, 0) == 0) {
+        // Only report an attach error once
+        jio_printf("Warning: detaching current thread from VM failed with %d (future attach errors are suppressed)\n", res);
+      }
+    }
+  }
+};
+
+C2V_VMENTRY_PREFIX(jint, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length, bool flush, bool can_throw))
+  AttachDetach ad(env, base_thread);
+  bool use_tty = true;
+  if (base_thread == NULL) {
+    if (!ad._attached) {
+      // Can only use tty if the current thread is attached
+      return 0;
+    }
+    base_thread = get_current_thread();
+  }
+  JVMCITraceMark jtm("writeDebugOutput");
+  assert(base_thread->is_Java_thread(), "just checking");
+  JavaThread* thread = (JavaThread*) base_thread;
+  C2V_BLOCK(void, writeDebugOutput, (JNIEnv* env, jobject, jbyteArray bytes, jint offset, jint length))
   if (bytes == NULL) {
-    JVMCI_THROW(NullPointerException);
+    if (can_throw) {
+      JVMCI_THROW_0(NullPointerException);
+    }
+    return -1;
   }
   JVMCIPrimitiveArray array = JVMCIENV->wrap(bytes);
 
   // Check if offset and length are non negative.
   if (offset < 0 || length < 0) {
-    JVMCI_THROW(ArrayIndexOutOfBoundsException);
+    if (can_throw) {
+      JVMCI_THROW_0(ArrayIndexOutOfBoundsException);
+    }
+    return -2;
   }
   // Check if the range is valid.
   int array_length = JVMCIENV->get_length(array);
   if ((((unsigned int) length + (unsigned int) offset) > (unsigned int) array_length)) {
-    JVMCI_THROW(ArrayIndexOutOfBoundsException);
+    if (can_throw) {
+      JVMCI_THROW_0(ArrayIndexOutOfBoundsException);
+    }
+    return -2;
   }
   jbyte buffer[O_BUFLEN];
   while (length > 0) {
@@ -1485,13 +1606,17 @@
     length -= O_BUFLEN;
     offset += O_BUFLEN;
   }
+  if (flush) {
+    tty->flush();
+  }
+  return 0;
 C2V_END
 
 C2V_VMENTRY(void, flushDebugOutput, (JNIEnv* env, jobject))
   tty->flush();
 C2V_END
 
-C2V_VMENTRY(int, methodDataProfileDataSize, (JNIEnv* env, jobject, jlong metaspace_method_data, jint position))
+C2V_VMENTRY_0(int, methodDataProfileDataSize, (JNIEnv* env, jobject, jlong metaspace_method_data, jint position))
   MethodData* mdo = JVMCIENV->asMethodData(metaspace_method_data);
   ProfileData* profile_data = mdo->data_at(position);
   if (mdo->is_valid(profile_data)) {
@@ -1509,7 +1634,7 @@
   JVMCI_THROW_MSG_0(IllegalArgumentException, err_msg("Invalid profile data position %d", position));
 C2V_END
 
-C2V_VMENTRY(jlong, getFingerprint, (JNIEnv* env, jobject, jlong metaspace_klass))
+C2V_VMENTRY_0(jlong, getFingerprint, (JNIEnv* env, jobject, jlong metaspace_klass))
 #if INCLUDE_AOT
   Klass *k = (Klass*) (address) metaspace_klass;
   if (k->is_instance_klass()) {
@@ -1522,7 +1647,7 @@
 #endif
 C2V_END
 
-C2V_VMENTRY(jobject, getHostClass, (JNIEnv* env, jobject, jobject jvmci_type))
+C2V_VMENTRY_NULL(jobject, getHostClass, (JNIEnv* env, jobject, jobject jvmci_type))
   InstanceKlass* k = InstanceKlass::cast(JVMCIENV->asKlass(jvmci_type));
   InstanceKlass* host = k->unsafe_anonymous_host();
   JVMCIKlassHandle handle(THREAD, host);
@@ -1530,7 +1655,7 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobject, getInterfaces, (JNIEnv* env, jobject, jobject jvmci_type))
+C2V_VMENTRY_NULL(jobject, getInterfaces, (JNIEnv* env, jobject, jobject jvmci_type))
   if (jvmci_type == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1557,7 +1682,7 @@
   return JVMCIENV->get_jobject(interfaces);
 C2V_END
 
-C2V_VMENTRY(jobject, getComponentType, (JNIEnv* env, jobject, jobject jvmci_type))
+C2V_VMENTRY_NULL(jobject, getComponentType, (JNIEnv* env, jobject, jobject jvmci_type))
   if (jvmci_type == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1597,7 +1722,7 @@
   }
 C2V_END
 
-C2V_VMENTRY(int, interpreterFrameSize, (JNIEnv* env, jobject, jobject bytecode_frame_handle))
+C2V_VMENTRY_0(int, interpreterFrameSize, (JNIEnv* env, jobject, jobject bytecode_frame_handle))
   if (bytecode_frame_handle == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1645,12 +1770,12 @@
   }
 C2V_END
 
-C2V_VMENTRY(int, getIdentityHashCode, (JNIEnv* env, jobject, jobject object))
+C2V_VMENTRY_0(int, getIdentityHashCode, (JNIEnv* env, jobject, jobject object))
   Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
   return obj->identity_hash();
 C2V_END
 
-C2V_VMENTRY(jboolean, isInternedString, (JNIEnv* env, jobject, jobject object))
+C2V_VMENTRY_0(jboolean, isInternedString, (JNIEnv* env, jobject, jobject object))
   Handle str = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0);
   if (!java_lang_String::is_instance(str())) {
     return false;
@@ -1661,7 +1786,7 @@
 C2V_END
 
 
-C2V_VMENTRY(jobject, unboxPrimitive, (JNIEnv* env, jobject, jobject object))
+C2V_VMENTRY_NULL(jobject, unboxPrimitive, (JNIEnv* env, jobject, jobject object))
   if (object == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1675,7 +1800,7 @@
   return JVMCIENV->get_jobject(boxResult);
 C2V_END
 
-C2V_VMENTRY(jobject, boxPrimitive, (JNIEnv* env, jobject, jobject object))
+C2V_VMENTRY_NULL(jobject, boxPrimitive, (JNIEnv* env, jobject, jobject object))
   if (object == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1719,7 +1844,7 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, jobject holder))
+C2V_VMENTRY_NULL(jobjectArray, getDeclaredConstructors, (JNIEnv* env, jobject, jobject holder))
   if (holder == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1748,7 +1873,7 @@
   return JVMCIENV->get_jobjectArray(methods);
 C2V_END
 
-C2V_VMENTRY(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, jobject holder))
+C2V_VMENTRY_NULL(jobjectArray, getDeclaredMethods, (JNIEnv* env, jobject, jobject holder))
   if (holder == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1777,7 +1902,7 @@
   return JVMCIENV->get_jobjectArray(methods);
 C2V_END
 
-C2V_VMENTRY(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject field, jboolean is_volatile))
+C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, jobject field, jboolean is_volatile))
   if (object == NULL || field == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1845,7 +1970,7 @@
   return JVMCIENV->get_jobject(result);
 C2V_END
 
-C2V_VMENTRY(jboolean, isInstance, (JNIEnv* env, jobject, jobject holder, jobject object))
+C2V_VMENTRY_0(jboolean, isInstance, (JNIEnv* env, jobject, jobject holder, jobject object))
   if (object == NULL || holder == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1854,7 +1979,7 @@
   return obj->is_a(klass);
 C2V_END
 
-C2V_VMENTRY(jboolean, isAssignableFrom, (JNIEnv* env, jobject, jobject holder, jobject otherHolder))
+C2V_VMENTRY_0(jboolean, isAssignableFrom, (JNIEnv* env, jobject, jobject holder, jobject otherHolder))
   if (holder == NULL || otherHolder == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1863,7 +1988,7 @@
   return otherKlass->is_subtype_of(klass);
 C2V_END
 
-C2V_VMENTRY(jboolean, isTrustedForIntrinsics, (JNIEnv* env, jobject, jobject holder))
+C2V_VMENTRY_0(jboolean, isTrustedForIntrinsics, (JNIEnv* env, jobject, jobject holder))
   if (holder == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1874,7 +1999,7 @@
   return false;
 C2V_END
 
-C2V_VMENTRY(jobject, asJavaType, (JNIEnv* env, jobject, jobject object))
+C2V_VMENTRY_NULL(jobject, asJavaType, (JNIEnv* env, jobject, jobject object))
   if (object == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1894,7 +2019,7 @@
 C2V_END
 
 
-C2V_VMENTRY(jobject, asString, (JNIEnv* env, jobject, jobject object))
+C2V_VMENTRY_NULL(jobject, asString, (JNIEnv* env, jobject, jobject object))
   if (object == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1905,14 +2030,14 @@
 C2V_END
 
 
-C2V_VMENTRY(jboolean, equals, (JNIEnv* env, jobject, jobject x, jlong xHandle, jobject y, jlong yHandle))
+C2V_VMENTRY_0(jboolean, equals, (JNIEnv* env, jobject, jobject x, jlong xHandle, jobject y, jlong yHandle))
   if (x == NULL || y == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
   return JVMCIENV->resolve_handle(xHandle) == JVMCIENV->resolve_handle(yHandle);
 C2V_END
 
-C2V_VMENTRY(jobject, getJavaMirror, (JNIEnv* env, jobject, jobject object))
+C2V_VMENTRY_NULL(jobject, getJavaMirror, (JNIEnv* env, jobject, jobject object))
   if (object == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1931,7 +2056,7 @@
 C2V_END
 
 
-C2V_VMENTRY(jint, getArrayLength, (JNIEnv* env, jobject, jobject x))
+C2V_VMENTRY_0(jint, getArrayLength, (JNIEnv* env, jobject, jobject x))
   if (x == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1943,7 +2068,7 @@
  C2V_END
 
 
-C2V_VMENTRY(jobject, readArrayElement, (JNIEnv* env, jobject, jobject x, int index))
+C2V_VMENTRY_NULL(jobject, readArrayElement, (JNIEnv* env, jobject, jobject x, int index))
   if (x == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1983,7 +2108,7 @@
 C2V_END
 
 
-C2V_VMENTRY(jint, arrayBaseOffset, (JNIEnv* env, jobject, jobject kind))
+C2V_VMENTRY_0(jint, arrayBaseOffset, (JNIEnv* env, jobject, jobject kind))
   if (kind == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1991,7 +2116,7 @@
   return arrayOopDesc::header_size(type) * HeapWordSize;
 C2V_END
 
-C2V_VMENTRY(jint, arrayIndexScale, (JNIEnv* env, jobject, jobject kind))
+C2V_VMENTRY_0(jint, arrayIndexScale, (JNIEnv* env, jobject, jobject kind))
   if (kind == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -1999,7 +2124,7 @@
   return type2aelembytes(type);
 C2V_END
 
-C2V_VMENTRY(jbyte, getByte, (JNIEnv* env, jobject, jobject x, long displacement))
+C2V_VMENTRY_0(jbyte, getByte, (JNIEnv* env, jobject, jobject x, long displacement))
   if (x == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -2007,7 +2132,7 @@
   return xobj->byte_field(displacement);
 }
 
-C2V_VMENTRY(jshort, getShort, (JNIEnv* env, jobject, jobject x, long displacement))
+C2V_VMENTRY_0(jshort, getShort, (JNIEnv* env, jobject, jobject x, long displacement))
   if (x == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -2015,7 +2140,7 @@
   return xobj->short_field(displacement);
 }
 
-C2V_VMENTRY(jint, getInt, (JNIEnv* env, jobject, jobject x, long displacement))
+C2V_VMENTRY_0(jint, getInt, (JNIEnv* env, jobject, jobject x, long displacement))
   if (x == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -2023,7 +2148,7 @@
   return xobj->int_field(displacement);
 }
 
-C2V_VMENTRY(jlong, getLong, (JNIEnv* env, jobject, jobject x, long displacement))
+C2V_VMENTRY_0(jlong, getLong, (JNIEnv* env, jobject, jobject x, long displacement))
   if (x == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -2031,7 +2156,7 @@
   return xobj->long_field(displacement);
 }
 
-C2V_VMENTRY(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement))
+C2V_VMENTRY_NULL(jobject, getObject, (JNIEnv* env, jobject, jobject x, long displacement))
   if (x == NULL) {
     JVMCI_THROW_0(NullPointerException);
   }
@@ -2049,30 +2174,38 @@
   }
 }
 
-C2V_VMENTRY(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror))
+static void requireJVMCINativeLibrary(JVMCI_TRAPS) {
   if (!UseJVMCINativeLibrary) {
-    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)");
+    JVMCI_THROW_MSG(UnsupportedOperationException, "JVMCI shared library is not enabled (requires -XX:+UseJVMCINativeLibrary)");
   }
-  if (!JVMCIENV->is_hotspot()) {
-    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "Cannot call registerNativeMethods from JVMCI shared library");
+}
+
+static JavaVM* requireNativeLibraryJavaVM(const char* caller, JVMCI_TRAPS) {
+  JavaVM* javaVM = JVMCIEnv::get_shared_library_javavm();
+  if (javaVM == NULL) {
+    JVMCI_THROW_MSG_NULL(IllegalStateException, err_msg("Require JVMCI shared library to be initialized in %s", caller));
   }
+  return javaVM;
+}
+
+C2V_VMENTRY_NULL(jlongArray, registerNativeMethods, (JNIEnv* env, jobject, jclass mirror))
+  requireJVMCINativeLibrary(JVMCI_CHECK_NULL);
+  requireInHotSpot("registerNativeMethods", JVMCI_CHECK_NULL);
   void* shared_library = JVMCIEnv::get_shared_library_handle();
   if (shared_library == NULL) {
     // Ensure the JVMCI shared library runtime is initialized.
-    JVMCIEnv __peer_jvmci_env__(false, __FILE__, __LINE__);
+    JVMCIEnv __peer_jvmci_env__(thread, false, __FILE__, __LINE__);
     JVMCIEnv* peerEnv = &__peer_jvmci_env__;
     HandleMark hm;
     JVMCIRuntime* runtime = JVMCI::compiler_runtime();
     JVMCIObject receiver = runtime->get_HotSpotJVMCIRuntime(peerEnv);
     if (peerEnv->has_pending_exception()) {
       peerEnv->describe_pending_exception(true);
+    }
+    shared_library = JVMCIEnv::get_shared_library_handle();
+    if (shared_library == NULL) {
       JVMCI_THROW_MSG_0(InternalError, "Error initializing JVMCI runtime");
     }
-    shared_library = JVMCIEnv::get_shared_library_handle();
-  }
-
-  if (shared_library == NULL) {
-    JVMCI_THROW_MSG_0(UnsatisfiedLinkError, "JVMCI shared library is unavailable");
   }
 
   if (mirror == NULL) {
@@ -2110,15 +2243,18 @@
         st.print_raw(pure_name);
         st.print_raw(long_name);
         os::print_jni_name_suffix_on(&st, args_size);
-        jni_name = st.as_string();
-        entry = (address) os::dll_lookup(shared_library, jni_name);
+        char* jni_long_name = st.as_string();
+        entry = (address) os::dll_lookup(shared_library, jni_long_name);
+        if (entry == NULL) {
+          JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [neither %s nor %s exist in %s]",
+              method->name_and_sig_as_C_string(),
+              jni_name, jni_long_name, JVMCIEnv::get_shared_library_path()));
+        }
       }
-      if (entry == NULL) {
-        JVMCI_THROW_MSG_0(UnsatisfiedLinkError, method->name_and_sig_as_C_string());
-      }
+
       if (method->has_native_function() && entry != method->native_function()) {
-        JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("Cannot overwrite existing native implementation for %s",
-            method->name_and_sig_as_C_string()));
+        JVMCI_THROW_MSG_0(UnsatisfiedLinkError, err_msg("%s [cannot re-link from " PTR_FORMAT " to " PTR_FORMAT "]",
+            method->name_and_sig_as_C_string(), p2i(method->native_function()), p2i(entry)));
       }
       method->set_native_function(entry, Method::native_bind_event_is_interesting);
       if (PrintJNIResolving) {
@@ -2138,11 +2274,102 @@
   return (jlongArray) JVMCIENV->get_jobject(result);
 }
 
-C2V_VMENTRY(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle))
+C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm))
+  if (base_thread == NULL) {
+    // Called from unattached JVMCI shared library thread
+    return false;
+  }
+  JVMCITraceMark jtm("isCurrentThreadAttached");
+  assert(base_thread->is_Java_thread(), "just checking");
+  JavaThread* thread = (JavaThread*) base_thread;
+  if (thread->jni_environment() == env) {
+    C2V_BLOCK(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject))
+    requireJVMCINativeLibrary(JVMCI_CHECK_0);
+    JavaVM* javaVM = requireNativeLibraryJavaVM("isCurrentThreadAttached", JVMCI_CHECK_0);
+    JNIEnv* peerEnv;
+    return javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK;
+  }
+  return true;
+C2V_END
+
+C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jboolean as_daemon))
+  if (base_thread == NULL) {
+    // Called from unattached JVMCI shared library thread
+    extern struct JavaVM_ main_vm;
+    JNIEnv* hotspotEnv;
+    jint res = as_daemon ? main_vm.AttachCurrentThreadAsDaemon((void**)&hotspotEnv, NULL) :
+                           main_vm.AttachCurrentThread((void**)&hotspotEnv, NULL);
+    if (res != JNI_OK) {
+      JNI_THROW_("attachCurrentThread", InternalError, err_msg("Trying to attach thread returned %d", res), false);
+    }
+    return true;
+  }
+  JVMCITraceMark jtm("attachCurrentThread");
+  assert(base_thread->is_Java_thread(), "just checking");\
+  JavaThread* thread = (JavaThread*) base_thread;
+  if (thread->jni_environment() == env) {
+    // Called from HotSpot
+    C2V_BLOCK(jboolean, attachCurrentThread, (JNIEnv* env, jobject, jboolean))
+    requireJVMCINativeLibrary(JVMCI_CHECK_0);
+    JavaVM* javaVM = requireNativeLibraryJavaVM("attachCurrentThread", JVMCI_CHECK_0);
+    JavaVMAttachArgs attach_args;
+    attach_args.version = JNI_VERSION_1_2;
+    attach_args.name = thread->name();
+    attach_args.group = NULL;
+    JNIEnv* peerEnv;
+    if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) == JNI_OK) {
+      return false;
+    }
+    jint res = as_daemon ? javaVM->AttachCurrentThreadAsDaemon((void**)&peerEnv, &attach_args) :
+                           javaVM->AttachCurrentThread((void**)&peerEnv, &attach_args);
+    if (res == JNI_OK) {
+      guarantee(peerEnv != NULL, "must be");
+      return true;
+    }
+    JVMCI_THROW_MSG_0(InternalError, err_msg("Error %d while attaching %s", res, attach_args.name));
+  }
+  // Called from JVMCI shared library
+  return false;
+C2V_END
+
+C2V_VMENTRY_PREFIX(void, detachCurrentThread, (JNIEnv* env, jobject c2vm))
+  if (base_thread == NULL) {
+    // Called from unattached JVMCI shared library thread
+    JNI_THROW("detachCurrentThread", IllegalStateException, err_msg("Cannot detach non-attached thread"));
+  }
+  JVMCITraceMark jtm("detachCurrentThread");
+  assert(base_thread->is_Java_thread(), "just checking");\
+  JavaThread* thread = (JavaThread*) base_thread;
+  if (thread->jni_environment() == env) {
+    // Called from HotSpot
+    C2V_BLOCK(void, detachCurrentThread, (JNIEnv* env, jobject))
+    requireJVMCINativeLibrary(JVMCI_CHECK);
+    requireInHotSpot("detachCurrentThread", JVMCI_CHECK);
+    JavaVM* javaVM = requireNativeLibraryJavaVM("detachCurrentThread", JVMCI_CHECK);
+    JNIEnv* peerEnv;
+    if (javaVM->GetEnv((void**)&peerEnv, JNI_VERSION_1_2) != JNI_OK) {
+      JVMCI_THROW_MSG(IllegalStateException, err_msg("Cannot detach non-attached thread: %s", thread->name()));
+    }
+    jint res = javaVM->DetachCurrentThread();
+    if (res != JNI_OK) {
+      JVMCI_THROW_MSG(InternalError, err_msg("Error %d while attaching %s", res, thread->name()));
+    }
+  } else {
+    // Called from attached JVMCI shared library thread
+    extern struct JavaVM_ main_vm;
+    jint res = main_vm.DetachCurrentThread();
+    if (res != JNI_OK) {
+      JNI_THROW("detachCurrentThread", InternalError, err_msg("Cannot detach non-attached thread"));
+    }
+  }
+C2V_END
+
+C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle))
+  requireJVMCINativeLibrary(JVMCI_CHECK_0);
   if (obj_handle == NULL) {
     return 0L;
   }
-  JVMCIEnv __peer_jvmci_env__(!JVMCIENV->is_hotspot(), __FILE__, __LINE__);
+  JVMCIEnv __peer_jvmci_env__(thread, !JVMCIENV->is_hotspot(), __FILE__, __LINE__);
   JVMCIEnv* peerEnv = &__peer_jvmci_env__;
   JVMCIEnv* thisEnv = JVMCIENV;
 
@@ -2213,7 +2440,8 @@
   return (jlong) peerEnv->make_global(result).as_jobject();
 }
 
-C2V_VMENTRY(jobject, unhand, (JNIEnv* env, jobject, jlong obj_handle))
+C2V_VMENTRY_NULL(jobject, unhand, (JNIEnv* env, jobject, jlong obj_handle))
+  requireJVMCINativeLibrary(JVMCI_CHECK_NULL);
   if (obj_handle == 0L) {
     return NULL;
   }
@@ -2231,7 +2459,7 @@
   JVMCIENV->asNmethod(code);
 }
 
-C2V_VMENTRY(jbyteArray, getCode, (JNIEnv* env, jobject, jobject code_handle))
+C2V_VMENTRY_NULL(jbyteArray, getCode, (JNIEnv* env, jobject, jobject code_handle))
   JVMCIObject code = JVMCIENV->wrap(code_handle);
   CodeBlob* cb = JVMCIENV->asCodeBlob(code);
   if (cb == NULL) {
@@ -2243,10 +2471,8 @@
   return JVMCIENV->get_jbyteArray(result);
 }
 
-C2V_VMENTRY(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method))
-  if (env != JavaThread::current()->jni_environment()) {
-    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
-  }
+C2V_VMENTRY_NULL(jobject, asReflectionExecutable, (JNIEnv* env, jobject, jobject jvmci_method))
+  requireInHotSpot("asReflectionExecutable", JVMCI_CHECK_NULL);
   methodHandle m = JVMCIENV->asMethod(jvmci_method);
   oop executable;
   if (m->is_initializer()) {
@@ -2261,10 +2487,8 @@
   return JNIHandles::make_local(THREAD, executable);
 }
 
-C2V_VMENTRY(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index))
-  if (env != JavaThread::current()->jni_environment()) {
-    JVMCI_THROW_MSG_NULL(InternalError, "Only supported when running in HotSpot");
-  }
+C2V_VMENTRY_NULL(jobject, asReflectionField, (JNIEnv* env, jobject, jobject jvmci_type, jint index))
+  requireInHotSpot("asReflectionField", JVMCI_CHECK_NULL);
   Klass* klass = JVMCIENV->asKlass(jvmci_type);
   if (!klass->is_instance_klass()) {
     JVMCI_THROW_MSG_NULL(IllegalArgumentException,
@@ -2281,7 +2505,7 @@
   return JNIHandles::make_local(env, reflected);
 }
 
-C2V_VMENTRY(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current))
+C2V_VMENTRY_NULL(jobjectArray, getFailedSpeculations, (JNIEnv* env, jobject, jlong failed_speculations_address, jobjectArray current))
   FailedSpeculation* head = *((FailedSpeculation**)(address) failed_speculations_address);
   int result_length = 0;
   for (FailedSpeculation* fs = head; fs != NULL; fs = fs->next()) {
@@ -2313,7 +2537,7 @@
   return JVMCIENV->get_jobjectArray(result);
 }
 
-C2V_VMENTRY(jlong, getFailedSpeculationsAddress, (JNIEnv* env, jobject, jobject jvmci_method))
+C2V_VMENTRY_0(jlong, getFailedSpeculationsAddress, (JNIEnv* env, jobject, jobject jvmci_method))
   methodHandle method = JVMCIENV->asMethod(jvmci_method);
   MethodData* method_data = method->method_data();
   if (method_data == NULL) {
@@ -2328,7 +2552,7 @@
   FailedSpeculation::free_failed_speculations((FailedSpeculation**)(address) failed_speculations_address);
 }
 
-C2V_VMENTRY(bool, addFailedSpeculation, (JNIEnv* env, jobject, jlong failed_speculations_address, jbyteArray speculation_obj))
+C2V_VMENTRY_0(bool, addFailedSpeculation, (JNIEnv* env, jobject, jlong failed_speculations_address, jbyteArray speculation_obj))
   JVMCIPrimitiveArray speculation_handle = JVMCIENV->wrap(speculation_obj);
   int speculation_len = JVMCIENV->get_length(speculation_handle);
   char* speculation = NEW_RESOURCE_ARRAY(char, speculation_len);
@@ -2428,7 +2652,7 @@
   {CC "iterateFrames",                                CC "([" RESOLVED_METHOD "[" RESOLVED_METHOD "I" INSPECTED_FRAME_VISITOR ")" OBJECT,   FN_PTR(iterateFrames)},
   {CC "materializeVirtualObjects",                    CC "(" HS_STACK_FRAME_REF "Z)V",                                                      FN_PTR(materializeVirtualObjects)},
   {CC "shouldDebugNonSafepoints",                     CC "()Z",                                                                             FN_PTR(shouldDebugNonSafepoints)},
-  {CC "writeDebugOutput",                             CC "([BII)V",                                                                         FN_PTR(writeDebugOutput)},
+  {CC "writeDebugOutput",                             CC "([BIIZZ)I",                                                                       FN_PTR(writeDebugOutput)},
   {CC "flushDebugOutput",                             CC "()V",                                                                             FN_PTR(flushDebugOutput)},
   {CC "methodDataProfileDataSize",                    CC "(JI)I",                                                                           FN_PTR(methodDataProfileDataSize)},
   {CC "getFingerprint",                               CC "(J)J",                                                                            FN_PTR(getFingerprint)},
@@ -2466,6 +2690,9 @@
   {CC "getObject",                                    CC "(" OBJECTCONSTANT "J)" OBJECTCONSTANT,                                            FN_PTR(getObject)},
   {CC "deleteGlobalHandle",                           CC "(J)V",                                                                            FN_PTR(deleteGlobalHandle)},
   {CC "registerNativeMethods",                        CC "(" CLASS ")[J",                                                                   FN_PTR(registerNativeMethods)},
+  {CC "isCurrentThreadAttached",                      CC "()Z",                                                                             FN_PTR(isCurrentThreadAttached)},
+  {CC "attachCurrentThread",                          CC "(Z)Z",                                                                            FN_PTR(attachCurrentThread)},
+  {CC "detachCurrentThread",                          CC "()V",                                                                             FN_PTR(detachCurrentThread)},
   {CC "translate",                                    CC "(" OBJECT ")J",                                                                   FN_PTR(translate)},
   {CC "unhand",                                       CC "(J)" OBJECT,                                                                      FN_PTR(unhand)},
   {CC "updateHotSpotNmethod",                         CC "(" HS_NMETHOD ")V",                                                               FN_PTR(updateHotSpotNmethod)},
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Tue May 07 11:52:28 2019 -0700
@@ -160,13 +160,14 @@
 };
 
 class JNIHandleMark : public StackObj {
+  JavaThread* _thread;
   public:
-    JNIHandleMark() { push_jni_handle_block(); }
-    ~JNIHandleMark() { pop_jni_handle_block(); }
+    JNIHandleMark(JavaThread* thread) : _thread(thread) { push_jni_handle_block(thread); }
+    ~JNIHandleMark() { pop_jni_handle_block(_thread); }
 
   private:
-    static void push_jni_handle_block();
-    static void pop_jni_handle_block();
+    static void push_jni_handle_block(JavaThread* thread);
+    static void pop_jni_handle_block(JavaThread* thread);
 };
 
 #endif // SHARE_JVMCI_JVMCICOMPILERTOVM_HPP
--- a/src/hotspot/share/jvmci/jvmciEnv.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciEnv.cpp	Tue May 07 11:52:28 2019 -0700
@@ -129,11 +129,10 @@
   }
 }
 
-JNIEnv* JVMCIEnv::attach_shared_library() {
+JNIEnv* JVMCIEnv::init_shared_library(JavaThread* thread) {
   if (_shared_library_javavm == NULL) {
     MutexLocker locker(JVMCI_lock);
     if (_shared_library_javavm == NULL) {
-
       char path[JVM_MAXPATHLEN];
       char ebuf[1024];
       if (JVMCILibPath != NULL) {
@@ -179,85 +178,107 @@
       }
     }
   }
-  JNIEnv* env;
-  if (_shared_library_javavm->AttachCurrentThread((void**)&env, NULL) == JNI_OK) {
-    guarantee(env != NULL, "missing env");
-    return env;
-  }
-  fatal("Error attaching current thread to JVMCI shared library JNI interface");
   return NULL;
 }
 
-void JVMCIEnv::init_env_mode_runtime(JNIEnv* parent_env) {
+void JVMCIEnv::init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env) {
+  assert(thread != NULL, "npe");
   // By default there is only one runtime which is the compiler runtime.
   _runtime = JVMCI::compiler_runtime();
+  _env = NULL;
+  _pop_frame_on_close = false;
+  _detach_on_close = false;
   if (!UseJVMCINativeLibrary) {
     // In HotSpot mode, JNI isn't used at all.
     _is_hotspot = true;
-    _env = NULL;
     return;
   }
 
   if (parent_env != NULL) {
     // If the parent JNI environment is non-null then figure out whether it
     // is a HotSpot or shared library JNIEnv and set the state appropriately.
-    JavaThread* thread = JavaThread::current();
-    if (thread->jni_environment() == parent_env) {
+    _is_hotspot = thread->jni_environment() == parent_env;
+    if (_is_hotspot) {
       // Select the Java runtime
       _runtime = JVMCI::java_runtime();
-      _is_hotspot = true;
-      _env = NULL;
       return;
     }
+    _env = parent_env;
+    return;
+  }
+
+  // Running in JVMCI shared library mode so ensure the shared library
+  // is loaded and initialized and get a shared library JNIEnv
+  _is_hotspot = false;
+  _env = init_shared_library(thread);
+
+  if (_env != NULL) {
+    // Creating the JVMCI shared library VM also attaches the current thread
+    _detach_on_close = true;
+  } else {
+    _shared_library_javavm->GetEnv((void**)&parent_env, JNI_VERSION_1_2);
+    if (parent_env != NULL) {
+      // Even though there's a parent JNI env, there's no guarantee
+      // it was opened by a JVMCIEnv scope and thus may not have
+      // pushed a local JNI frame. As such, we use a new JNI local
+      // frame in this scope to ensure local JNI refs are collected
+      // in a timely manner after leaving this scope.
+      _env = parent_env;
+    } else {
+      ResourceMark rm; // Thread name is resource allocated
+      JavaVMAttachArgs attach_args;
+      attach_args.version = JNI_VERSION_1_2;
+      attach_args.name = thread->name();
+      attach_args.group = NULL;
+      if (_shared_library_javavm->AttachCurrentThread((void**)&_env, &attach_args) != JNI_OK) {
+        fatal("Error attaching current thread (%s) to JVMCI shared library JNI interface", attach_args.name);
+      }
+      _detach_on_close = true;
+    }
   }
 
-  // Running in JVMCI shared library mode so get a shared library JNIEnv
-  _is_hotspot = false;
-  _env = attach_shared_library();
-  assert(parent_env == NULL || _env == parent_env, "must be");
+  assert(_env != NULL, "missing env");
+  assert(_throw_to_caller == false, "must be");
 
-  if (parent_env == NULL) {
-    // There is no parent shared library JNI env so push
-    // a JNI local frame to release all local handles in
-    // this JVMCIEnv scope when it's closed.
-    assert(_throw_to_caller == false, "must be");
-    JNIAccessMark jni(this);
-    jint result = _env->PushLocalFrame(32);
-    if (result != JNI_OK) {
-      char message[256];
-      jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
-      JVMCIRuntime::exit_on_pending_exception(this, message);
-    }
+  JNIAccessMark jni(this);
+  jint result = _env->PushLocalFrame(32);
+  if (result != JNI_OK) {
+    char message[256];
+    jio_snprintf(message, 256, "Uncaught exception pushing local frame for JVMCIEnv scope entered at %s:%d", _file, _line);
+    JVMCIRuntime::exit_on_pending_exception(this, message);
   }
+  _pop_frame_on_close = true;
 }
 
-JVMCIEnv::JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line):
+JVMCIEnv::JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line):
     _throw_to_caller(false), _file(file), _line(line), _compile_state(compile_state) {
-  init_env_mode_runtime(NULL);
+  init_env_mode_runtime(thread, NULL);
 }
 
 JVMCIEnv::JVMCIEnv(JavaThread* thread, const char* file, int line):
     _throw_to_caller(false), _file(file), _line(line), _compile_state(NULL) {
-  init_env_mode_runtime(NULL);
+  init_env_mode_runtime(thread, NULL);
 }
 
-JVMCIEnv::JVMCIEnv(JNIEnv* parent_env, const char* file, int line):
+JVMCIEnv::JVMCIEnv(JavaThread* thread, JNIEnv* parent_env, const char* file, int line):
     _throw_to_caller(true), _file(file), _line(line), _compile_state(NULL) {
-  init_env_mode_runtime(parent_env);
+  init_env_mode_runtime(thread, parent_env);
   assert(_env == NULL || parent_env == _env, "mismatched JNIEnvironment");
 }
 
-void JVMCIEnv::init(bool is_hotspot, const char* file, int line) {
+void JVMCIEnv::init(JavaThread* thread, bool is_hotspot, const char* file, int line) {
   _compile_state = NULL;
   _throw_to_caller = false;
   _file = file;
   _line = line;
   if (is_hotspot) {
     _env = NULL;
+    _pop_frame_on_close = false;
+    _detach_on_close = false;
     _is_hotspot = true;
     _runtime = JVMCI::java_runtime();
   } else {
-    init_env_mode_runtime(NULL);
+    init_env_mode_runtime(thread, NULL);
   }
 }
 
@@ -324,7 +345,7 @@
       }
     }
   } else {
-    if (!is_hotspot()) {
+    if (_pop_frame_on_close) {
       // Pop the JNI local frame that was pushed when entering this JVMCIEnv scope.
       JNIAccessMark jni(this);
       jni()->PopLocalFrame(NULL);
@@ -335,6 +356,10 @@
       jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line);
       JVMCIRuntime::exit_on_pending_exception(this, message);
     }
+
+    if (_detach_on_close) {
+      get_shared_library_javavm()->DetachCurrentThread();
+    }
   }
 }
 
@@ -463,26 +488,38 @@
   }
 }
 
-void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes) {
-  if (size_in_bytes == 0) {
+void JVMCIEnv::copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length) {
+  if (length == 0) {
     return;
   }
   if (is_hotspot()) {
-    memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), size_in_bytes);
+    memcpy(dest, HotSpotJVMCI::resolve(src)->byte_at_addr(offset), length);
   } else {
     JNIAccessMark jni(this);
-    jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, size_in_bytes, dest);
+    jni()->GetByteArrayRegion(src.as_jbyteArray(), offset, length, dest);
   }
 }
-void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes) {
-  if (size_in_bytes == 0) {
+void JVMCIEnv::copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
+  if (length == 0) {
     return;
   }
   if (is_hotspot()) {
-    memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, size_in_bytes);
+    memcpy(HotSpotJVMCI::resolve(dest)->byte_at_addr(offset), src, length);
   } else {
     JNIAccessMark jni(this);
-    jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, size_in_bytes, src);
+    jni()->SetByteArrayRegion(dest.as_jbyteArray(), offset, length, src);
+  }
+}
+
+void JVMCIEnv::copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length) {
+  if (length == 0) {
+    return;
+  }
+  if (is_hotspot()) {
+    memcpy(HotSpotJVMCI::resolve(dest)->long_at_addr(offset), src, length * sizeof(jlong));
+  } else {
+    JNIAccessMark jni(this);
+    jni()->SetLongArrayRegion(dest.as_jlongArray(), offset, length, src);
   }
 }
 
@@ -612,6 +649,8 @@
 DO_THROW(IllegalArgumentException)
 DO_THROW(InvalidInstalledCodeException)
 DO_THROW(UnsatisfiedLinkError)
+DO_THROW(UnsupportedOperationException)
+DO_THROW(ClassNotFoundException)
 
 #undef DO_THROW
 
@@ -888,7 +927,7 @@
       return JVMCIObject();
     }
     jobject file_name = NULL;
-    if (file_name != NULL) {
+    if (file_name_sym != NULL) {
       file_name = jni()->NewStringUTF(file_name_sym->as_C_string());
       if (jni()->ExceptionCheck()) {
         return JVMCIObject();
@@ -1323,14 +1362,15 @@
     assert(HotSpotJVMCI::DirectHotSpotObjectConstantImpl::is_instance(this, constant), "wrong type");
     oop obj = HotSpotJVMCI::DirectHotSpotObjectConstantImpl::object(this, HotSpotJVMCI::resolve(constant));
     return Handle(THREAD, obj);
-  } else {
-    assert(isa_IndirectHotSpotObjectConstantImpl(constant), "wrong type");
+  } else if (isa_IndirectHotSpotObjectConstantImpl(constant)) {
     jlong object_handle = get_IndirectHotSpotObjectConstantImpl_objectHandle(constant);
     oop result = resolve_handle(object_handle);
     if (result == NULL) {
       JVMCI_THROW_MSG_(InternalError, "Constant was unexpectedly NULL", Handle());
     }
     return Handle(THREAD, result);
+  } else {
+    JVMCI_THROW_MSG_(IllegalArgumentException, "DirectHotSpotObjectConstantImpl shouldn't reach JVMCI in SVM mode", Handle());
   }
 }
 
--- a/src/hotspot/share/jvmci/jvmciEnv.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciEnv.hpp	Tue May 07 11:52:28 2019 -0700
@@ -36,15 +36,6 @@
 class JVMCICompiler;
 class JVMCIRuntime;
 
-// Bring the JVMCI compiler thread into the VM state.
-#define JVMCI_VM_ENTRY_MARK                       \
-  JavaThread* thread = JavaThread::current(); \
-  ThreadInVMfromNative __tiv(thread);       \
-  ResetNoHandleMark rnhm;                   \
-  HandleMarkCleaner __hm(thread);           \
-  Thread* THREAD = thread;                  \
-  debug_only(VMNativeEntryWrapper __vew;)
-
 #define JVMCI_EXCEPTION_CONTEXT \
   JavaThread* thread=JavaThread::current(); \
   Thread* THREAD = thread;
@@ -154,24 +145,25 @@
   static void*   _shared_library_handle; // result of os::dll_load
   static JavaVM* _shared_library_javavm; // result of calling JNI_CreateJavaVM in shared library
 
-  // Attaches the current thread to the JavaVM in the shared library,
-  // initializing the shared library VM first if necessary.
-  // Returns the JNI interface pointer of the current thread.
-  // The _shared_library_* fields are initialized by the first
-  // call to this method.
-  static JNIEnv* attach_shared_library();
+  // Initializes the shared library JavaVM if not already initialized.
+  // Returns the JNI interface pointer for the current thread
+  // if initialization was performed by this call, NULL if
+  // initialization was performed by a previous call.
+  static JNIEnv* init_shared_library(JavaThread* thread);
 
   // Initializes the _env, _mode and _runtime fields.
-  void init_env_mode_runtime(JNIEnv* parent_env);
+  void init_env_mode_runtime(JavaThread* thread, JNIEnv* parent_env);
 
-  void init(bool is_hotspot, const char* file, int line);
+  void init(JavaThread* thread, bool is_hotspot, const char* file, int line);
 
-  JNIEnv*                _env;     // JNI env for calling into shared library
-  JVMCIRuntime*          _runtime; // Access to a HotSpotJVMCIRuntime
-  bool             _is_hotspot;    // Which heap is the HotSpotJVMCIRuntime in
-  bool        _throw_to_caller;    // Propagate an exception raised in this env to the caller?
-  const char*            _file;    // The file and ...
-  int                    _line;    // ... line where this JNIEnv was created
+  JNIEnv*                 _env;  // JNI env for calling into shared library
+  bool     _pop_frame_on_close;  // Must pop frame on close?
+  bool        _detach_on_close;  // Must detach on close?
+  JVMCIRuntime*       _runtime;  // Access to a HotSpotJVMCIRuntime
+  bool             _is_hotspot;  // Which heap is the HotSpotJVMCIRuntime in
+  bool        _throw_to_caller;  // Propagate an exception raised in this env to the caller?
+  const char*            _file;  // The file and ...
+  int                    _line;  // ... line where this JNIEnv was created
 
   // Translates an exception on the HotSpot heap to an exception on
   // the shared library heap. The translation includes the stack and
@@ -185,12 +177,12 @@
   // scope closes so that it will be propagated back to Java.
   // The JVMCIEnv destructor translates the exception object for the
   // Java runtime if necessary.
-  JVMCIEnv(JNIEnv* env, const char* file, int line);
+  JVMCIEnv(JavaThread* thread, JNIEnv* env, const char* file, int line);
 
   // Opens a JVMCIEnv scope for a compilation scheduled by the CompileBroker.
   // An exception occurring within the scope must not be propagated back to
   // the CompileBroker.
-  JVMCIEnv(JVMCICompileState* compile_state, const char* file, int line);
+  JVMCIEnv(JavaThread* thread, JVMCICompileState* compile_state, const char* file, int line);
 
   // Opens a JNIEnv scope for a call from within the VM. An exception occurring
   // within the scope must not be propagated back to the caller.
@@ -198,20 +190,20 @@
 
   // Opens a JNIEnv scope for accessing `for_object`. An exception occurring
   // within the scope must not be propagated back to the caller.
-  JVMCIEnv(JVMCIObject for_object, const char* file, int line) {
+  JVMCIEnv(JavaThread* thread, JVMCIObject for_object, const char* file, int line) {
     // A JNI call to access an object in the shared library heap
     // can block or take a long time so do not allow such access
     // on the VM thread.
     assert(for_object.is_hotspot() || !Thread::current()->is_VM_thread(),
         "cannot open JVMCIEnv scope when in the VM thread for accessing a shared library heap object");
-    init(for_object.is_hotspot(), file, line);
+    init(thread, for_object.is_hotspot(), file, line);
   }
 
   // Opens a JNIEnv scope for the HotSpot runtime if `is_hotspot` is true
   // otherwise for the shared library runtime. An exception occurring
   // within the scope must not be propagated back to the caller.
-  JVMCIEnv(bool is_hotspot, const char* file, int line) {
-    init(is_hotspot, file, line);
+  JVMCIEnv(JavaThread* thread, bool is_hotspot, const char* file, int line) {
+    init(thread, is_hotspot, file, line);
   }
 
   ~JVMCIEnv();
@@ -247,8 +239,10 @@
   long get_long_at(JVMCIPrimitiveArray array, int index);
   void put_long_at(JVMCIPrimitiveArray array, int index, jlong value);
 
-  void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, int size_in_bytes);
-  void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, int size_in_bytes);
+  void copy_bytes_to(JVMCIPrimitiveArray src, jbyte* dest, int offset, jsize length);
+  void copy_bytes_from(jbyte* src, JVMCIPrimitiveArray dest, int offset, jsize length);
+
+  void copy_longs_from(jlong* src, JVMCIPrimitiveArray dest, int offset, jsize length);
 
   JVMCIObjectArray initialize_intrinsics(JVMCI_TRAPS);
 
@@ -323,6 +317,8 @@
   DO_THROW(IllegalArgumentException)
   DO_THROW(InvalidInstalledCodeException)
   DO_THROW(UnsatisfiedLinkError)
+  DO_THROW(UnsupportedOperationException)
+  DO_THROW(ClassNotFoundException)
 
 #undef DO_THROW
 
--- a/src/hotspot/share/jvmci/jvmciExceptions.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciExceptions.hpp	Tue May 07 11:52:28 2019 -0700
@@ -32,8 +32,8 @@
 #define JVMCIENV __jvmci_env__
 #define JVMCI_TRAPS  JVMCIEnv* JVMCIENV
 
-#define JNI_JVMCIENV(env)                                     \
-  JVMCIEnv __stack_jvmci_env__(env, __FILE__, __LINE__);      \
+#define JNI_JVMCIENV(thread, env)                                     \
+  JVMCIEnv __stack_jvmci_env__(thread, env, __FILE__, __LINE__);      \
   JVMCIEnv* JVMCIENV = &__stack_jvmci_env__
 
 #define THREAD_JVMCIENV(thread)                               \
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp	Tue May 07 11:52:28 2019 -0700
@@ -356,6 +356,43 @@
   jobject  JNICALL JVM_GetJVMCIRuntime(JNIEnv *env, jclass c);
 }
 
+// Dumps symbols for public <init>() and <init>(String) methods of
+// non-abstract Throwable subtypes known by the VM. This is to
+// support the use of reflection in jdk.vm.ci.hotspot.TranslatedException.create().
+class ThrowableInitDumper : public SymbolClosure {
+ private:
+  fileStream* _st;
+ public:
+  ThrowableInitDumper(fileStream* st)     { _st = st; }
+  void do_symbol(Symbol** p) {
+    Thread* THREAD = Thread::current();
+    Symbol* name = *p;
+    if (name == NULL) {
+      return;
+    }
+    Klass* k = SystemDictionary::resolve_or_null(name, CHECK_EXIT);
+    if (k != NULL && k->is_instance_klass()) {
+      InstanceKlass* iklass = InstanceKlass::cast(k);
+      if (iklass->is_subclass_of(SystemDictionary::Throwable_klass()) && iklass->is_public() && !iklass->is_abstract()) {
+        const char* class_name = NULL;
+        Array<Method*>* methods = iklass->methods();
+        for (int i = 0; i < methods->length(); i++) {
+          Method* m = methods->at(i);
+          if (m->name() == vmSymbols::object_initializer_name() &&
+              m->is_public() &&
+              (m->signature() == vmSymbols::void_method_signature() || m->signature() == vmSymbols::string_void_signature())) {
+            if (class_name == NULL) {
+              class_name = name->as_C_string();
+              _st->print_cr("class %s", class_name);
+            }
+            _st->print_cr("method %s %s %s", class_name, m->name()->as_C_string(), m->signature()->as_C_string());
+          }
+        }
+      }
+    }
+  }
+};
+
 #define IN_CLASS(fullClassName) current_class_name = vmSymbols::fullClassName()->as_C_string()
 /**
  * Initializes the JNI method and field ids used in JNIJVMCI.
@@ -441,6 +478,8 @@
     fileStream* st = JVMCIGlobals::get_jni_config_file();
 
     DUMP_ALL_NATIVE_METHODS(vmSymbols::jdk_vm_ci_hotspot_CompilerToVM());
+    ThrowableInitDumper dumper(st);
+    vmSymbols::symbols_do(&dumper);
 
     st->flush();
     tty->print_cr("Dumped JVMCI shared library JNI configuration to %s", JVMCILibDumpJNIConfig);
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Tue May 07 11:52:28 2019 -0700
@@ -381,12 +381,18 @@
   start_class(InternalError, java_lang_InternalError)                                                         \
     jvmci_constructor(InternalError, "(Ljava/lang/String;)V")                                                 \
   end_class                                                                                                   \
+  start_class(ClassNotFoundException, java_lang_ClassNotFoundException)                                       \
+    jvmci_constructor(ClassNotFoundException, "(Ljava/lang/String;)V")                                        \
+  end_class                                                                                                   \
   start_class(InvalidInstalledCodeException, jdk_vm_ci_code_InvalidInstalledCodeException)                    \
     jvmci_constructor(InvalidInstalledCodeException, "(Ljava/lang/String;)V")                                 \
   end_class                                                                                                   \
   start_class(UnsatisfiedLinkError, java_lang_UnsatisfiedLinkError)                                           \
     jvmci_constructor(UnsatisfiedLinkError, "(Ljava/lang/String;)V")                                          \
   end_class                                                                                                   \
+  start_class(UnsupportedOperationException, java_lang_UnsupportedOperationException)                         \
+    jvmci_constructor(UnsupportedOperationException, "(Ljava/lang/String;)V")                                 \
+  end_class                                                                                                   \
   start_class(StackTraceElement, java_lang_StackTraceElement)                                                 \
     object_field(StackTraceElement, declaringClass, "Ljava/lang/String;")                                     \
     object_field(StackTraceElement, methodName, "Ljava/lang/String;")                                         \
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Tue May 07 11:52:28 2019 -0700
@@ -655,7 +655,7 @@
 
 // private static JVMCIRuntime JVMCI.initializeRuntime()
 JVM_ENTRY_NO_ENV(jobject, JVM_GetJVMCIRuntime(JNIEnv *env, jclass c))
-  JNI_JVMCIENV(env);
+  JNI_JVMCIENV(thread, env);
   if (!EnableJVMCI) {
     JVMCI_THROW_MSG_NULL(InternalError, "JVMCI is not enabled");
   }
@@ -877,7 +877,7 @@
   fatal("check TLAB allocation code for address space conflicts");
 #endif
 
-  JNI_JVMCIENV(env);
+  JNI_JVMCIENV(thread, env);
 
   if (!EnableJVMCI) {
     JVMCI_THROW_MSG(InternalError, "JVMCI is not enabled");
@@ -1353,6 +1353,10 @@
     compile_state->set_failure(true, "No OSR during boostrap");
     return;
   }
+  if (JVMCI::shutdown_called()) {
+    compile_state->set_failure(false, "Avoiding compilation during shutdown");
+    return;
+  }
 
   HandleMark hm;
   JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);
--- a/src/hotspot/share/jvmci/jvmci_globals.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmci_globals.cpp	Tue May 07 11:52:28 2019 -0700
@@ -83,7 +83,7 @@
     }
     FLAG_SET_DEFAULT(EnableJVMCI, true);
     if (BootstrapJVMCI && UseJVMCINativeLibrary) {
-      jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary");
+      jio_fprintf(defaultStream::error_stream(), "-XX:+BootstrapJVMCI is not compatible with -XX:+UseJVMCINativeLibrary\n");
       return false;
     }
   }
--- a/src/hotspot/share/jvmci/jvmci_globals.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmci_globals.hpp	Tue May 07 11:52:28 2019 -0700
@@ -53,7 +53,10 @@
           "Prints properties used by the JVMCI compiler and exits")         \
                                                                             \
   experimental(bool, BootstrapJVMCI, false,                                 \
-          "Bootstrap JVMCI before running Java main method")                \
+          "Bootstrap JVMCI before running Java main method. This "          \
+          "initializes the compile queue with a small set of methods "      \
+          "and processes the queue until it is empty. Combining this with " \
+          "-XX:-TieredCompilation makes JVMCI compile more of itself.")     \
                                                                             \
   experimental(bool, EagerJVMCI, false,                                     \
           "Force eager JVMCI initialization")                               \
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Tue May 07 11:52:28 2019 -0700
@@ -246,6 +246,10 @@
                                                                                                                                      \
   nonstatic_field(ObjArrayKlass,               _element_klass,                                Klass*)                                \
                                                                                                                                      \
+  volatile_nonstatic_field(ObjectMonitor,      _cxq,                                   ObjectWaiter*)                                \
+  volatile_nonstatic_field(ObjectMonitor,      _EntryList,                             ObjectWaiter*)                                \
+  volatile_nonstatic_field(ObjectMonitor,      _succ,                                  Thread*)                                      \
+                                                                                                                                     \
   volatile_nonstatic_field(oopDesc,            _mark,                                         markOop)                               \
   volatile_nonstatic_field(oopDesc,            _metadata._klass,                              Klass*)                                \
                                                                                                                                      \
@@ -347,6 +351,7 @@
   declare_toplevel_type(JVMCIEnv)                                         \
   declare_toplevel_type(LocalVariableTableElement)                        \
   declare_toplevel_type(narrowKlass)                                      \
+  declare_toplevel_type(ObjectWaiter)                                     \
   declare_toplevel_type(Symbol*)                                          \
   declare_toplevel_type(vtableEntry)                                      \
                                                                           \
--- a/src/hotspot/share/oops/cpCache.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/oops/cpCache.cpp	Tue May 07 11:52:28 2019 -0700
@@ -506,7 +506,7 @@
       switch (invoke_code) {
       case Bytecodes::_invokeinterface:
         assert(f1->is_klass(), "");
-        return klassItable::method_for_itable_index((InstanceKlass*)f1, f2_as_index());
+        return f2_as_interface_method();
       case Bytecodes::_invokestatic:
       case Bytecodes::_invokespecial:
         assert(!has_appendix(), "");
--- a/src/hotspot/share/oops/instanceKlass.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Tue May 07 11:52:28 2019 -0700
@@ -2965,6 +2965,13 @@
 
 // On-stack replacement stuff
 void InstanceKlass::add_osr_nmethod(nmethod* n) {
+#ifndef PRODUCT
+  if (TieredCompilation) {
+      nmethod * prev = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), n->comp_level(), true);
+      assert(prev == NULL || !prev->is_in_use(),
+      "redundunt OSR recompilation detected. memory leak in CodeCache!");
+  }
+#endif
   // only one compilation can be active
   {
     // This is a short non-blocking critical region, so the no safepoint check is ok.
@@ -3083,7 +3090,9 @@
     }
     osr = osr->osr_link();
   }
-  if (best != NULL && best->comp_level() >= comp_level && match_level == false) {
+
+  assert(match_level == false || best == NULL, "shouldn't pick up anything if match_level is set");
+  if (best != NULL && best->comp_level() >= comp_level) {
     return best;
   }
   return NULL;
--- a/src/hotspot/share/oops/klass.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/oops/klass.cpp	Tue May 07 11:52:28 2019 -0700
@@ -733,8 +733,9 @@
   st->cr();
 }
 
+#define BULLET  " - "
+
 void Klass::oop_print_on(oop obj, outputStream* st) {
-  ResourceMark rm;
   // print title
   st->print_cr("%s ", internal_name());
   obj->print_address_on(st);
@@ -742,10 +743,13 @@
   if (WizardMode) {
      // print header
      obj->mark()->print_on(st);
+     st->cr();
+     st->print(BULLET"prototype_header: " INTPTR_FORMAT, p2i(_prototype_header));
+     st->cr();
   }
 
   // print class
-  st->print(" - klass: ");
+  st->print(BULLET"klass: ");
   obj->klass()->print_value_on(st);
   st->cr();
 }
--- a/src/hotspot/share/oops/markOop.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/oops/markOop.cpp	Tue May 07 11:52:28 2019 -0700
@@ -25,45 +25,40 @@
 #include "precompiled.hpp"
 #include "oops/markOop.hpp"
 #include "runtime/thread.inline.hpp"
-#include "runtime/objectMonitor.inline.hpp"
+#include "runtime/objectMonitor.hpp"
 
 void markOopDesc::print_on(outputStream* st) const {
-  if (is_marked()) {
+  if (is_marked()) {  // last bits = 11
     st->print(" marked(" INTPTR_FORMAT ")", value());
-  } else if (has_monitor()) {
+  } else if (has_monitor()) {  // last bits = 10
     // have to check has_monitor() before is_locked()
     st->print(" monitor(" INTPTR_FORMAT ")=", value());
     ObjectMonitor* mon = monitor();
     if (mon == NULL) {
       st->print("NULL (this should never be seen!)");
     } else {
-      st->print("{contentions=0x%08x,waiters=0x%08x"
-                ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
-                mon->contentions(), mon->waiters(), mon->recursions(),
-                p2i(mon->owner()));
+      mon->print_on(st);
     }
-  } else if (is_locked()) {
-    st->print(" locked(" INTPTR_FORMAT ")->", value());
-    if (is_neutral()) {
+  } else if (is_locked()) {  // last bits != 01 => 00
+    // thin locked
+    st->print(" locked(" INTPTR_FORMAT ")", value());
+  } else {
+    st->print(" mark(");
+    // Biased bit is 3rd rightmost bit
+    if (is_neutral()) {   // last bits = 001
       st->print("is_neutral");
       if (has_no_hash()) {
         st->print(" no_hash");
       } else {
         st->print(" hash=" INTPTR_FORMAT, hash());
       }
-      st->print(" age=%d", age());
-    } else if (has_bias_pattern()) {
+    } else if (has_bias_pattern()) {  // last bits = 101
       st->print("is_biased");
       JavaThread* jt = biased_locker();
-      st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt));
+      st->print(" biased_locker=" INTPTR_FORMAT " epoch=%d", p2i(jt), bias_epoch());
     } else {
       st->print("??");
     }
-  } else {
-    assert(is_unlocked() || has_bias_pattern(), "just checking");
-    st->print("mark(");
-    if (has_bias_pattern()) st->print("biased,");
-    st->print("hash " INTPTR_FORMAT ",", hash());
-    st->print("age %d)", age());
+    st->print(" age=%d)", age());
   }
 }
--- a/src/hotspot/share/oops/method.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/oops/method.cpp	Tue May 07 11:52:28 2019 -0700
@@ -624,6 +624,10 @@
   return can_be_statically_bound(method_holder()->access_flags());
 }
 
+bool Method::can_be_statically_bound(InstanceKlass* context) const {
+  return (method_holder() == context) && can_be_statically_bound();
+}
+
 bool Method::is_accessor() const {
   return is_getter() || is_setter();
 }
--- a/src/hotspot/share/oops/method.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/oops/method.hpp	Tue May 07 11:52:28 2019 -0700
@@ -619,6 +619,7 @@
 
   // true if method needs no dynamic dispatch (final and/or no vtable entry)
   bool can_be_statically_bound() const;
+  bool can_be_statically_bound(InstanceKlass* context) const;
   bool can_be_statically_bound(AccessFlags class_access_flags) const;
 
   // returns true if the method has any backward branches.
--- a/src/hotspot/share/opto/bytecodeInfo.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/bytecodeInfo.cpp	Tue May 07 11:52:28 2019 -0700
@@ -321,6 +321,35 @@
   return false;
 }
 
+bool InlineTree::is_not_reached(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile) {
+  if (!UseInterpreter) {
+    return false; // -Xcomp
+  }
+  if (profile.count() > 0) {
+    return false; // reachable according to profile
+  }
+  if (!callee_method->was_executed_more_than(0)) {
+    return true; // callee was never executed
+  }
+  if (caller_method->is_not_reached(caller_bci)) {
+    return true; // call site not resolved
+  }
+  if (profile.count() == -1) {
+    return false; // immature profile; optimistically treat as reached
+  }
+  assert(profile.count() == 0, "sanity");
+
+  // Profile info is scarce.
+  // Try to guess: check if the call site belongs to a start block.
+  // Call sites in a start block should be reachable if no exception is thrown earlier.
+  ciMethodBlocks* caller_blocks = caller_method->get_method_blocks();
+  bool is_start_block = caller_blocks->block_containing(caller_bci)->start_bci() == 0;
+  if (is_start_block) {
+    return false; // treat the call reached as part of start block
+  }
+  return true; // give up and treat the call site as not reached
+}
+
 //-----------------------------try_to_inline-----------------------------------
 // return true if ok
 // Relocated from "InliningClosure::try_to_inline"
@@ -372,7 +401,7 @@
       // inline constructors even if they are not reached.
     } else if (forced_inline()) {
       // Inlining was forced by CompilerOracle, ciReplay or annotation
-    } else if (profile.count() == 0) {
+    } else if (is_not_reached(callee_method, caller_method, caller_bci, profile)) {
       // don't inline unreached call sites
        set_msg("call site not reached");
        return false;
--- a/src/hotspot/share/opto/doCall.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/doCall.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1152,14 +1152,19 @@
       cha_monomorphic_target = NULL;
     }
   }
+
   if (cha_monomorphic_target != NULL) {
     // Hardwiring a virtual.
-    // If we inlined because CHA revealed only a single target method,
-    // then we are dependent on that target method not getting overridden
-    // by dynamic class loading.  Be sure to test the "static" receiver
-    // dest_method here, as opposed to the actual receiver, which may
-    // falsely lead us to believe that the receiver is final or private.
-    dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target);
+    assert(!callee->can_be_statically_bound(), "should have been handled earlier");
+    assert(!cha_monomorphic_target->is_abstract(), "");
+    if (!cha_monomorphic_target->can_be_statically_bound(actual_receiver)) {
+      // If we inlined because CHA revealed only a single target method,
+      // then we are dependent on that target method not getting overridden
+      // by dynamic class loading.  Be sure to test the "static" receiver
+      // dest_method here, as opposed to the actual receiver, which may
+      // falsely lead us to believe that the receiver is final or private.
+      dependencies()->assert_unique_concrete_method(actual_receiver, cha_monomorphic_target);
+    }
     return cha_monomorphic_target;
   }
 
--- a/src/hotspot/share/opto/loopTransform.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/loopTransform.cpp	Tue May 07 11:52:28 2019 -0700
@@ -45,13 +45,13 @@
 // Given an IfNode, return the loop-exiting projection or NULL if both
 // arms remain in the loop.
 Node *IdealLoopTree::is_loop_exit(Node *iff) const {
-  if( iff->outcnt() != 2 ) return NULL; // Ignore partially dead tests
+  if (iff->outcnt() != 2) return NULL;  // Ignore partially dead tests
   PhaseIdealLoop *phase = _phase;
   // Test is an IfNode, has 2 projections.  If BOTH are in the loop
   // we need loop unswitching instead of peeling.
-  if( !is_member(phase->get_loop( iff->raw_out(0) )) )
+  if (!is_member(phase->get_loop(iff->raw_out(0))))
     return iff->raw_out(0);
-  if( !is_member(phase->get_loop( iff->raw_out(1) )) )
+  if (!is_member(phase->get_loop(iff->raw_out(1))))
     return iff->raw_out(1);
   return NULL;
 }
@@ -63,7 +63,7 @@
 //------------------------------record_for_igvn----------------------------
 // Put loop body on igvn work list
 void IdealLoopTree::record_for_igvn() {
-  for( uint i = 0; i < _body.size(); i++ ) {
+  for (uint i = 0; i < _body.size(); i++) {
     Node *n = _body.at(i);
     _phase->_igvn._worklist.push(n);
   }
@@ -145,7 +145,9 @@
       Node *exit = is_loop_exit(iff);
       if (exit) {
         float exit_prob = iff->_prob;
-        if (exit->Opcode() == Op_IfFalse) exit_prob = 1.0 - exit_prob;
+        if (exit->Opcode() == Op_IfFalse) {
+          exit_prob = 1.0 - exit_prob;
+        }
         if (exit_prob > PROB_MIN) {
           float exit_cnt = iff->_fcnt * exit_prob;
           return exit_cnt;
@@ -202,7 +204,7 @@
     // Now compute a loop exit count
     float loop_exit_cnt = 0.0f;
     if (_child == NULL) {
-      for( uint i = 0; i < _body.size(); i++ ) {
+      for (uint i = 0; i < _body.size(); i++) {
         Node *n = _body[i];
         loop_exit_cnt += compute_profile_trip_cnt_helper(n);
       }
@@ -342,33 +344,48 @@
 //------------------------------policy_peeling---------------------------------
 // Return TRUE or FALSE if the loop should be peeled or not.  Peel if we can
 // make some loop-invariant test (usually a null-check) happen before the loop.
-bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
-  Node *test = ((IdealLoopTree*)this)->tail();
-  int  body_size = ((IdealLoopTree*)this)->_body.size();
+bool IdealLoopTree::policy_peeling(PhaseIdealLoop *phase) const {
+  IdealLoopTree *loop = (IdealLoopTree*)this;
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
+  uint body_size = loop->_body.size();
   // Peeling does loop cloning which can result in O(N^2) node construction
-  if( body_size > 255 /* Prevent overflow for large body_size */
-      || (body_size * body_size + phase->C->live_nodes()) > phase->C->max_node_limit() ) {
-    return false;           // too large to safely clone
+  if (body_size > 255) {
+    return false;   // Prevent overflow for large body size
   }
+  uint estimate = body_size * body_size;
+  if (phase->exceeding_node_budget(estimate)) {
+    return false;   // Too large to safely clone
+  }
 
   // check for vectorized loops, any peeling done was already applied
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) return false;
-
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->trip_count() == 1) {
-    return false;
+  if (_head->is_CountedLoop()) {
+    CountedLoopNode* cl = _head->as_CountedLoop();
+    if (cl->is_unroll_only() || cl->trip_count() == 1) {
+      return false;
+    }
   }
 
-  while( test != _head ) {      // Scan till run off top of loop
-    if( test->is_If() ) {       // Test?
+  Node* test = loop->tail();
+
+  while (test != _head) {       // Scan till run off top of loop
+    if (test->is_If()) {        // Test?
       Node *ctrl = phase->get_ctrl(test->in(1));
-      if (ctrl->is_top())
+      if (ctrl->is_top()) {
         return false;           // Found dead test on live IF?  No peeling!
+      }
       // Standard IF only has one input value to check for loop invariance
-      assert(test->Opcode() == Op_If || test->Opcode() == Op_CountedLoopEnd || test->Opcode() == Op_RangeCheck, "Check this code when new subtype is added");
+      assert(test->Opcode() == Op_If ||
+             test->Opcode() == Op_CountedLoopEnd ||
+             test->Opcode() == Op_RangeCheck,
+             "Check this code when new subtype is added");
       // Condition is not a member of this loop?
-      if( !is_member(phase->get_loop(ctrl)) &&
-          is_loop_exit(test) )
-        return true;            // Found reason to peel!
+      if (!is_member(phase->get_loop(ctrl)) && is_loop_exit(test)) {
+        // Found reason to peel!
+        return phase->may_require_nodes(estimate);
+      }
     }
     // Walk up dominators to loop _head looking for test which is
     // executed on every path thru loop.
@@ -381,27 +398,27 @@
 // If we got the effect of peeling, either by actually peeling or by making
 // a pre-loop which must execute at least once, we can remove all
 // loop-invariant dominated tests in the main body.
-void PhaseIdealLoop::peeled_dom_test_elim( IdealLoopTree *loop, Node_List &old_new ) {
+void PhaseIdealLoop::peeled_dom_test_elim(IdealLoopTree *loop, Node_List &old_new) {
   bool progress = true;
-  while( progress ) {
+  while (progress) {
     progress = false;           // Reset for next iteration
     Node *prev = loop->_head->in(LoopNode::LoopBackControl);//loop->tail();
     Node *test = prev->in(0);
-    while( test != loop->_head ) { // Scan till run off top of loop
+    while (test != loop->_head) { // Scan till run off top of loop
 
       int p_op = prev->Opcode();
-      if( (p_op == Op_IfFalse || p_op == Op_IfTrue) &&
+      if ((p_op == Op_IfFalse || p_op == Op_IfTrue) &&
           test->is_If() &&      // Test?
           !test->in(1)->is_Con() && // And not already obvious?
           // Condition is not a member of this loop?
           !loop->is_member(get_loop(get_ctrl(test->in(1))))){
         // Walk loop body looking for instances of this test
-        for( uint i = 0; i < loop->_body.size(); i++ ) {
+        for (uint i = 0; i < loop->_body.size(); i++) {
           Node *n = loop->_body.at(i);
-          if( n->is_If() && n->in(1) == test->in(1) /*&& n != loop->tail()->in(0)*/ ) {
+          if (n->is_If() && n->in(1) == test->in(1) /*&& n != loop->tail()->in(0)*/) {
             // IfNode was dominated by version in peeled loop body
             progress = true;
-            dominated_by( old_new[prev->_idx], n );
+            dominated_by(old_new[prev->_idx], n);
           }
         }
       }
@@ -409,7 +426,7 @@
       test = idom(test);
     } // End of scan tests in loop
 
-  } // End of while( progress )
+  } // End of while (progress)
 }
 
 //------------------------------do_peeling-------------------------------------
@@ -550,7 +567,7 @@
 //              v
 //             exit
 //
-void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) {
+void PhaseIdealLoop::do_peeling(IdealLoopTree *loop, Node_List &old_new) {
 
   C->set_major_progress();
   // Peeling a 'main' loop in a pre/main/post situation obfuscates the
@@ -599,7 +616,7 @@
     Node* old = head->fast_out(j);
     if (old->in(0) == loop->_head && old->req() == 3 && old->is_Phi()) {
       Node* new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx];
-      if (!new_exit_value )     // Backedge value is ALSO loop invariant?
+      if (!new_exit_value)     // Backedge value is ALSO loop invariant?
         // Then loop body backedge value remains the same.
         new_exit_value = old->in(LoopNode::LoopBackControl);
       _igvn.hash_delete(old);
@@ -628,8 +645,9 @@
   for (uint j3 = 0; j3 < loop->_body.size(); j3++) {
     Node *old = loop->_body.at(j3);
     Node *nnn = old_new[old->_idx];
-    if (!has_ctrl(nnn))
+    if (!has_ctrl(nnn)) {
       set_idom(nnn, idom(nnn), dd-1);
+    }
   }
 
   // Now force out all loop-invariant dominating tests.  The optimizer
@@ -644,12 +662,12 @@
 //------------------------------policy_maximally_unroll------------------------
 // Calculate exact loop trip count and return true if loop can be maximally
 // unrolled.
-bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_maximally_unroll(PhaseIdealLoop *phase) const {
   CountedLoopNode *cl = _head->as_CountedLoop();
   assert(cl->is_normal_loop(), "");
-  if (!cl->is_valid_counted_loop())
+  if (!cl->is_valid_counted_loop()) {
     return false; // Malformed counted loop
-
+  }
   if (!cl->has_exact_trip_count()) {
     // Trip count is not exact.
     return false;
@@ -660,31 +678,36 @@
   assert(trip_count > 1, "one iteration loop should be optimized out already");
   assert(trip_count < max_juint, "exact trip_count should be less than max_uint.");
 
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // Real policy: if we maximally unroll, does it get too big?
   // Allow the unrolled mess to get larger than standard loop
   // size.  After all, it will no longer be a loop.
   uint body_size    = _body.size();
   uint unroll_limit = (uint)LoopUnrollLimit * 4;
-  assert( (intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits");
+  assert((intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits");
   if (trip_count > unroll_limit || body_size > unroll_limit) {
     return false;
   }
 
-  // Fully unroll a loop with few iterations regardless next
-  // conditions since following loop optimizations will split
-  // such loop anyway (pre-main-post).
-  if (trip_count <= 3)
-    return true;
-
   // Take into account that after unroll conjoined heads and tails will fold,
   // otherwise policy_unroll() may allow more unrolling than max unrolling.
-  uint new_body_size = EMPTY_LOOP_SIZE + (body_size - EMPTY_LOOP_SIZE) * trip_count;
-  uint tst_body_size = (new_body_size - EMPTY_LOOP_SIZE) / trip_count + EMPTY_LOOP_SIZE;
-  if (body_size != tst_body_size) // Check for int overflow
+  uint new_body_size = est_loop_clone_sz(trip_count, body_size - EMPTY_LOOP_SIZE);
+
+  if (new_body_size == UINT_MAX) { // Check for bad estimate (overflow).
     return false;
+  }
+
+  // Fully unroll a loop with few iterations regardless next conditions since
+  // following loop optimizations will split such loop anyway (pre-main-post).
+  if (trip_count <= 3) {
+    return phase->may_require_nodes(new_body_size);
+  }
+
   if (new_body_size > unroll_limit ||
       // Unrolling can result in a large amount of node construction
-      new_body_size >= phase->C->max_node_limit() - phase->C->live_nodes()) {
+      phase->exceeding_node_budget(new_body_size)) {
     return false;
   }
 
@@ -714,38 +737,43 @@
     } // switch
   }
 
-  return true; // Do maximally unroll
+  return phase->may_require_nodes(new_body_size);
 }
 
 
 //------------------------------policy_unroll----------------------------------
-// Return TRUE or FALSE if the loop should be unrolled or not.  Unroll if
-// the loop is a CountedLoop and the body is small enough.
+// Return TRUE or FALSE if the loop should be unrolled or not.  Unroll if the
+// loop is a CountedLoop and the body is small enough.
 bool IdealLoopTree::policy_unroll(PhaseIdealLoop *phase) {
 
   CountedLoopNode *cl = _head->as_CountedLoop();
   assert(cl->is_normal_loop() || cl->is_main_loop(), "");
 
-  if (!cl->is_valid_counted_loop())
+  if (!cl->is_valid_counted_loop()) {
     return false; // Malformed counted loop
+  }
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
 
   // Protect against over-unrolling.
   // After split at least one iteration will be executed in pre-loop.
-  if (cl->trip_count() <= (uint)(cl->is_normal_loop() ? 2 : 1)) return false;
-
-  _local_loop_unroll_limit = LoopUnrollLimit;
+  if (cl->trip_count() <= (cl->is_normal_loop() ? 2u : 1u)) {
+    return false;
+  }
+  _local_loop_unroll_limit  = LoopUnrollLimit;
   _local_loop_unroll_factor = 4;
-  int future_unroll_ct = cl->unrolled_count() * 2;
+  int future_unroll_cnt = cl->unrolled_count() * 2;
   if (!cl->is_vectorized_loop()) {
-    if (future_unroll_ct > LoopMaxUnroll) return false;
+    if (future_unroll_cnt > LoopMaxUnroll) return false;
   } else {
     // obey user constraints on vector mapped loops with additional unrolling applied
     int unroll_constraint = (cl->slp_max_unroll()) ? cl->slp_max_unroll() : 1;
-    if ((future_unroll_ct / unroll_constraint) > LoopMaxUnroll) return false;
+    if ((future_unroll_cnt / unroll_constraint) > LoopMaxUnroll) return false;
   }
 
   // Check for initial stride being a small enough constant
-  if (abs(cl->stride_con()) > (1<<2)*future_unroll_ct) return false;
+  if (abs(cl->stride_con()) > (1<<2)*future_unroll_cnt) return false;
 
   // Don't unroll if the next round of unrolling would push us
   // over the expected trip count of the loop.  One is subtracted
@@ -753,8 +781,8 @@
   // executes 1 iteration.
   if (UnrollLimitForProfileCheck > 0 &&
       cl->profile_trip_cnt() != COUNT_UNKNOWN &&
-      future_unroll_ct        > UnrollLimitForProfileCheck &&
-      (float)future_unroll_ct > cl->profile_trip_cnt() - 1.0) {
+      future_unroll_cnt        > UnrollLimitForProfileCheck &&
+      (float)future_unroll_cnt > cl->profile_trip_cnt() - 1.0) {
     return false;
   }
 
@@ -763,8 +791,8 @@
   //   and rounds of "unroll,optimize" are not making significant progress
   //   Progress defined as current size less than 20% larger than previous size.
   if (UseSuperWord && cl->node_count_before_unroll() > 0 &&
-      future_unroll_ct > LoopUnrollMin &&
-      (future_unroll_ct - 1) * (100 / LoopPercentProfileLimit) > cl->profile_trip_cnt() &&
+      future_unroll_cnt > LoopUnrollMin &&
+      (future_unroll_cnt - 1) * (100 / LoopPercentProfileLimit) > cl->profile_trip_cnt() &&
       1.2 * cl->node_count_before_unroll() < (double)_body.size()) {
     return false;
   }
@@ -848,8 +876,8 @@
     if (LoopMaxUnroll > _local_loop_unroll_factor) {
       // Once policy_slp_analysis succeeds, mark the loop with the
       // maximal unroll factor so that we minimize analysis passes
-      if (future_unroll_ct >= _local_loop_unroll_factor) {
-        policy_unroll_slp_analysis(cl, phase, future_unroll_ct);
+      if (future_unroll_cnt >= _local_loop_unroll_factor) {
+        policy_unroll_slp_analysis(cl, phase, future_unroll_cnt);
       }
     }
   }
@@ -858,32 +886,40 @@
   if ((LoopMaxUnroll < slp_max_unroll_factor) && FLAG_IS_DEFAULT(LoopMaxUnroll) && UseSubwordForMaxVector) {
     LoopMaxUnroll = slp_max_unroll_factor;
   }
+
+  uint estimate = est_loop_clone_sz(2, body_size);
+
   if (cl->has_passed_slp()) {
-    if (slp_max_unroll_factor >= future_unroll_ct) return true;
-    // Normal case: loop too big
-    return false;
+    if (slp_max_unroll_factor >= future_unroll_cnt) {
+      return phase->may_require_nodes(estimate);
+    }
+    return false; // Loop too big.
   }
 
   // Check for being too big
   if (body_size > (uint)_local_loop_unroll_limit) {
-    if ((cl->is_subword_loop() || xors_in_loop >= 4) && body_size < (uint)LoopUnrollLimit * 4) {
-      return true;
+    if ((cl->is_subword_loop() || xors_in_loop >= 4) && body_size < 4u * LoopUnrollLimit) {
+      return phase->may_require_nodes(estimate);
     }
-    // Normal case: loop too big
-    return false;
+    return false; // Loop too big.
   }
 
-  if (cl->do_unroll_only()) {
+  if (cl->is_unroll_only()) {
     if (TraceSuperWordLoopUnrollAnalysis) {
-      tty->print_cr("policy_unroll passed vector loop(vlen=%d,factor = %d)\n", slp_max_unroll_factor, future_unroll_ct);
+      tty->print_cr("policy_unroll passed vector loop(vlen=%d, factor=%d)\n",
+                    slp_max_unroll_factor, future_unroll_cnt);
     }
   }
 
   // Unroll once!  (Each trip will soon do double iterations)
-  return true;
+  return phase->may_require_nodes(estimate);
 }
 
-void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLoop *phase, int future_unroll_ct) {
+void IdealLoopTree::policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLoop *phase, int future_unroll_cnt) {
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // Enable this functionality target by target as needed
   if (SuperWordLoopUnrollAnalysis) {
     if (!cl->was_slp_analyzed()) {
@@ -898,7 +934,7 @@
 
     if (cl->has_passed_slp()) {
       int slp_max_unroll_factor = cl->slp_max_unroll();
-      if (slp_max_unroll_factor >= future_unroll_ct) {
+      if (slp_max_unroll_factor >= future_unroll_cnt) {
         int new_limit = cl->node_count_before_unroll() * slp_max_unroll_factor;
         if (new_limit > LoopUnrollLimit) {
           if (TraceSuperWordLoopUnrollAnalysis) {
@@ -917,16 +953,19 @@
 // aligned in a loop (unless the VM guarantees mutual alignment).  Note that
 // if we vectorize short memory ops into longer memory ops, we may want to
 // increase alignment.
-bool IdealLoopTree::policy_align( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_align(PhaseIdealLoop *phase) const {
   return false;
 }
 
 //------------------------------policy_range_check-----------------------------
 // Return TRUE or FALSE if the loop should be range-check-eliminated.
 // Actually we do iteration-splitting, a more powerful form of RCE.
-bool IdealLoopTree::policy_range_check( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_range_check(PhaseIdealLoop *phase) const {
   if (!RangeCheckElimination) return false;
 
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   CountedLoopNode *cl = _head->as_CountedLoop();
   // If we unrolled with no intention of doing RCE and we later
   // changed our minds, we got no pre-loop.  Either we need to
@@ -935,7 +974,7 @@
   Node *trip_counter = cl->phi();
 
   // check for vectorized loops, some opts are no longer needed
-  if (cl->do_unroll_only()) return false;
+  if (cl->is_unroll_only()) return false;
 
   // Check loop body for tests of trip-counter plus loop-invariant vs
   // loop-invariant.
@@ -946,38 +985,45 @@
 
       // Comparing trip+off vs limit
       Node *bol = iff->in(1);
-      if (bol->req() != 2) continue; // dead constant test
+      if (bol->req() != 2) {
+        continue; // dead constant test
+      }
       if (!bol->is_Bool()) {
         assert(bol->Opcode() == Op_Conv2B, "predicate check only");
         continue;
       }
-      if (bol->as_Bool()->_test._test == BoolTest::ne)
+      if (bol->as_Bool()->_test._test == BoolTest::ne) {
         continue; // not RC
-
+      }
       Node *cmp = bol->in(1);
       Node *rc_exp = cmp->in(1);
       Node *limit = cmp->in(2);
 
       Node *limit_c = phase->get_ctrl(limit);
-      if( limit_c == phase->C->top() )
+      if (limit_c == phase->C->top()) {
         return false;           // Found dead test on live IF?  No RCE!
-      if( is_member(phase->get_loop(limit_c) ) ) {
+      }
+      if (is_member(phase->get_loop(limit_c))) {
         // Compare might have operands swapped; commute them
         rc_exp = cmp->in(2);
         limit  = cmp->in(1);
         limit_c = phase->get_ctrl(limit);
-        if( is_member(phase->get_loop(limit_c) ) )
+        if (is_member(phase->get_loop(limit_c))) {
           continue;             // Both inputs are loop varying; cannot RCE
+        }
       }
 
       if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL)) {
         continue;
       }
-      // Yeah!  Found a test like 'trip+off vs limit'
-      // Test is an IfNode, has 2 projections.  If BOTH are in the loop
-      // we need loop unswitching instead of iteration splitting.
-      if( is_loop_exit(iff) )
-        return true;            // Found reason to split iterations
+      // Found a test like 'trip+off vs  limit'.  Test is an IfNode, has two
+      // (2) projections.  If BOTH are in  the loop we need loop unswitching
+      // instead of iteration splitting.
+      if (is_loop_exit(iff)) {
+        // Found valid reason to split iterations (if there is room).
+        // NOTE: Usually a gross overestimate.
+        return phase->may_require_nodes(est_loop_clone_sz(2, _body.size()));
+      }
     } // End of is IF
   }
 
@@ -987,14 +1033,21 @@
 //------------------------------policy_peel_only-------------------------------
 // Return TRUE or FALSE if the loop should NEVER be RCE'd or aligned.  Useful
 // for unrolling loops with NO array accesses.
-bool IdealLoopTree::policy_peel_only( PhaseIdealLoop *phase ) const {
+bool IdealLoopTree::policy_peel_only(PhaseIdealLoop *phase) const {
+
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // check for vectorized loops, any peeling done was already applied
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) return false;
-
-  for( uint i = 0; i < _body.size(); i++ )
-    if( _body[i]->is_Mem() )
+  if (_head->is_CountedLoop() && _head->as_CountedLoop()->is_unroll_only()) {
+    return false;
+  }
+
+  for (uint i = 0; i < _body.size(); i++) {
+    if (_body[i]->is_Mem()) {
       return false;
-
+    }
+  }
   // No memory accesses at all!
   return true;
 }
@@ -1002,33 +1055,31 @@
 //------------------------------clone_up_backedge_goo--------------------------
 // If Node n lives in the back_ctrl block and cannot float, we clone a private
 // version of n in preheader_ctrl block and return that, otherwise return n.
-Node *PhaseIdealLoop::clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones ) {
-  if( get_ctrl(n) != back_ctrl ) return n;
+Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones) {
+  if (get_ctrl(n) != back_ctrl) return n;
 
   // Only visit once
   if (visited.test_set(n->_idx)) {
     Node *x = clones.find(n->_idx);
-    if (x != NULL)
-      return x;
-    return n;
+    return (x != NULL) ? x : n;
   }
 
   Node *x = NULL;               // If required, a clone of 'n'
   // Check for 'n' being pinned in the backedge.
-  if( n->in(0) && n->in(0) == back_ctrl ) {
+  if (n->in(0) && n->in(0) == back_ctrl) {
     assert(clones.find(n->_idx) == NULL, "dead loop");
     x = n->clone();             // Clone a copy of 'n' to preheader
     clones.push(x, n->_idx);
-    x->set_req( 0, preheader_ctrl ); // Fix x's control input to preheader
+    x->set_req(0, preheader_ctrl); // Fix x's control input to preheader
   }
 
   // Recursive fixup any other input edges into x.
   // If there are no changes we can just return 'n', otherwise
   // we need to clone a private copy and change it.
-  for( uint i = 1; i < n->req(); i++ ) {
-    Node *g = clone_up_backedge_goo( back_ctrl, preheader_ctrl, n->in(i), visited, clones );
-    if( g != n->in(i) ) {
-      if( !x ) {
+  for (uint i = 1; i < n->req(); i++) {
+    Node *g = clone_up_backedge_goo(back_ctrl, preheader_ctrl, n->in(i), visited, clones);
+    if (g != n->in(i)) {
+      if (!x) {
         assert(clones.find(n->_idx) == NULL, "dead loop");
         x = n->clone();
         clones.push(x, n->_idx);
@@ -1036,11 +1087,11 @@
       x->set_req(i, g);
     }
   }
-  if( x ) {                     // x can legally float to pre-header location
-    register_new_node( x, preheader_ctrl );
+  if (x) {                     // x can legally float to pre-header location
+    register_new_node(x, preheader_ctrl);
     return x;
   } else {                      // raise n to cover LCA of uses
-    set_ctrl( n, find_non_split_ctrl(back_ctrl->in(0)) );
+    set_ctrl(n, find_non_split_ctrl(back_ctrl->in(0)));
   }
   return n;
 }
@@ -1244,7 +1295,7 @@
 // Insert pre and post loops.  If peel_only is set, the pre-loop can not have
 // more iterations added.  It acts as a 'peel' only, no lower-bound RCE, no
 // alignment.  Useful to unroll loops that do no array accesses.
-void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only ) {
+void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_new, bool peel_only) {
 
 #ifndef PRODUCT
   if (TraceLoopOpts) {
@@ -1259,9 +1310,9 @@
 
   // Find common pieces of the loop being guarded with pre & post loops
   CountedLoopNode *main_head = loop->_head->as_CountedLoop();
-  assert( main_head->is_normal_loop(), "" );
+  assert(main_head->is_normal_loop(), "");
   CountedLoopEndNode *main_end = main_head->loopexit();
-  assert( main_end->outcnt() == 2, "1 true, 1 false path only" );
+  assert(main_end->outcnt() == 2, "1 true, 1 false path only");
 
   Node *pre_header= main_head->in(LoopNode::EntryControl);
   Node *init      = main_head->init_trip();
@@ -1273,13 +1324,13 @@
 
   // Need only 1 user of 'bol' because I will be hacking the loop bounds.
   Node *bol = main_end->in(CountedLoopEndNode::TestValue);
-  if( bol->outcnt() != 1 ) {
+  if (bol->outcnt() != 1) {
     bol = bol->clone();
     register_new_node(bol,main_end->in(CountedLoopEndNode::TestControl));
     _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, bol);
   }
   // Need only 1 user of 'cmp' because I will be hacking the loop bounds.
-  if( cmp->outcnt() != 1 ) {
+  if (cmp->outcnt() != 1) {
     cmp = cmp->clone();
     register_new_node(cmp,main_end->in(CountedLoopEndNode::TestControl));
     _igvn.replace_input_of(bol, 1, cmp);
@@ -1314,9 +1365,9 @@
 
   // Find the pre-loop normal exit.
   Node* pre_exit = pre_end->proj_out(false);
-  assert( pre_exit->Opcode() == Op_IfFalse, "" );
+  assert(pre_exit->Opcode() == Op_IfFalse, "");
   IfFalseNode *new_pre_exit = new IfFalseNode(pre_end);
-  _igvn.register_new_node_with_optimizer( new_pre_exit );
+  _igvn.register_new_node_with_optimizer(new_pre_exit);
   set_idom(new_pre_exit, pre_end, dd_main_head);
   set_loop(new_pre_exit, outer_loop->_parent);
 
@@ -1325,26 +1376,26 @@
   // zero-trip guard will become the minimum-trip guard when we unroll
   // the main-loop.
   Node *min_opaq = new Opaque1Node(C, limit);
-  Node *min_cmp  = new CmpINode( pre_incr, min_opaq );
-  Node *min_bol  = new BoolNode( min_cmp, b_test );
-  register_new_node( min_opaq, new_pre_exit );
-  register_new_node( min_cmp , new_pre_exit );
-  register_new_node( min_bol , new_pre_exit );
+  Node *min_cmp  = new CmpINode(pre_incr, min_opaq);
+  Node *min_bol  = new BoolNode(min_cmp, b_test);
+  register_new_node(min_opaq, new_pre_exit);
+  register_new_node(min_cmp , new_pre_exit);
+  register_new_node(min_bol , new_pre_exit);
 
   // Build the IfNode (assume the main-loop is executed always).
-  IfNode *min_iff = new IfNode( new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN );
-  _igvn.register_new_node_with_optimizer( min_iff );
+  IfNode *min_iff = new IfNode(new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN);
+  _igvn.register_new_node_with_optimizer(min_iff);
   set_idom(min_iff, new_pre_exit, dd_main_head);
   set_loop(min_iff, outer_loop->_parent);
 
   // Plug in the false-path, taken if we need to skip main-loop
-  _igvn.hash_delete( pre_exit );
+  _igvn.hash_delete(pre_exit);
   pre_exit->set_req(0, min_iff);
   set_idom(pre_exit, min_iff, dd_main_head);
   set_idom(pre_exit->unique_ctrl_out(), min_iff, dd_main_head);
   // Make the true-path, must enter the main loop
-  Node *min_taken = new IfTrueNode( min_iff );
-  _igvn.register_new_node_with_optimizer( min_taken );
+  Node *min_taken = new IfTrueNode(min_iff);
+  _igvn.register_new_node_with_optimizer(min_taken);
   set_idom(min_taken, min_iff, dd_main_head);
   set_loop(min_taken, outer_loop->_parent);
   // Plug in the true path
@@ -1359,14 +1410,14 @@
   // fall-out values of the pre-loop.
   for (DUIterator_Fast i2max, i2 = main_head->fast_outs(i2max); i2 < i2max; i2++) {
     Node* main_phi = main_head->fast_out(i2);
-    if( main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0 ) {
+    if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0) {
       Node *pre_phi = old_new[main_phi->_idx];
       Node *fallpre  = clone_up_backedge_goo(pre_head->back_control(),
                                              main_head->skip_strip_mined()->in(LoopNode::EntryControl),
                                              pre_phi->in(LoopNode::LoopBackControl),
                                              visited, clones);
       _igvn.hash_delete(main_phi);
-      main_phi->set_req( LoopNode::EntryControl, fallpre );
+      main_phi->set_req(LoopNode::EntryControl, fallpre);
     }
   }
 
@@ -1381,7 +1432,7 @@
   // dependencies.
 
   // CastII for the main loop:
-  Node* castii = cast_incr_before_loop( pre_incr, min_taken, main_head );
+  Node* castii = cast_incr_before_loop(pre_incr, min_taken, main_head);
   assert(castii != NULL, "no castII inserted");
   Node* opaque_castii = new Opaque1Node(C, castii);
   register_new_node(opaque_castii, outer_main_head->in(LoopNode::EntryControl));
@@ -1390,18 +1441,18 @@
   // Step B4: Shorten the pre-loop to run only 1 iteration (for now).
   // RCE and alignment may change this later.
   Node *cmp_end = pre_end->cmp_node();
-  assert( cmp_end->in(2) == limit, "" );
-  Node *pre_limit = new AddINode( init, stride );
+  assert(cmp_end->in(2) == limit, "");
+  Node *pre_limit = new AddINode(init, stride);
 
   // Save the original loop limit in this Opaque1 node for
   // use by range check elimination.
   Node *pre_opaq  = new Opaque1Node(C, pre_limit, limit);
 
-  register_new_node( pre_limit, pre_head->in(0) );
-  register_new_node( pre_opaq , pre_head->in(0) );
+  register_new_node(pre_limit, pre_head->in(0));
+  register_new_node(pre_opaq , pre_head->in(0));
 
   // Since no other users of pre-loop compare, I can hack limit directly
-  assert( cmp_end->outcnt() == 1, "no other users" );
+  assert(cmp_end->outcnt() == 1, "no other users");
   _igvn.hash_delete(cmp_end);
   cmp_end->set_req(2, peel_only ? pre_limit : pre_opaq);
 
@@ -1421,24 +1472,26 @@
     // Modify pre loop end condition
     Node* pre_bol = pre_end->in(CountedLoopEndNode::TestValue)->as_Bool();
     BoolNode* new_bol0 = new BoolNode(pre_bol->in(1), new_test);
-    register_new_node( new_bol0, pre_head->in(0) );
+    register_new_node(new_bol0, pre_head->in(0));
     _igvn.replace_input_of(pre_end, CountedLoopEndNode::TestValue, new_bol0);
     // Modify main loop guard condition
     assert(min_iff->in(CountedLoopEndNode::TestValue) == min_bol, "guard okay");
     BoolNode* new_bol1 = new BoolNode(min_bol->in(1), new_test);
-    register_new_node( new_bol1, new_pre_exit );
+    register_new_node(new_bol1, new_pre_exit);
     _igvn.hash_delete(min_iff);
     min_iff->set_req(CountedLoopEndNode::TestValue, new_bol1);
     // Modify main loop end condition
     BoolNode* main_bol = main_end->in(CountedLoopEndNode::TestValue)->as_Bool();
     BoolNode* new_bol2 = new BoolNode(main_bol->in(1), new_test);
-    register_new_node( new_bol2, main_end->in(CountedLoopEndNode::TestControl) );
+    register_new_node(new_bol2, main_end->in(CountedLoopEndNode::TestControl));
     _igvn.replace_input_of(main_end, CountedLoopEndNode::TestValue, new_bol2);
   }
 
   // Flag main loop
   main_head->set_main_loop();
-  if( peel_only ) main_head->set_main_no_pre_loop();
+  if (peel_only) {
+    main_head->set_main_no_pre_loop();
+  }
 
   // Subtract a trip count for the pre-loop.
   main_head->set_trip_count(main_head->trip_count() - 1);
@@ -1457,8 +1510,9 @@
 
 //------------------------------insert_vector_post_loop------------------------
 // Insert a copy of the atomic unrolled vectorized main loop as a post loop,
-// unroll_policy has already informed us that more unrolling is about to happen to
-// the main loop.  The resultant post loop will serve as a vectorized drain loop.
+// unroll_policy has  already informed  us that more  unrolling is  about to
+// happen  to the  main  loop.  The  resultant  post loop  will  serve as  a
+// vectorized drain loop.
 void PhaseIdealLoop::insert_vector_post_loop(IdealLoopTree *loop, Node_List &old_new) {
   if (!loop->_head->is_CountedLoop()) return;
 
@@ -1467,6 +1521,9 @@
   // only process vectorized main loops
   if (!cl->is_vectorized_loop() || !cl->is_main_loop()) return;
 
+  if (!may_require_nodes(est_loop_clone_sz(2, loop->_body.size()))) {
+    return;
+  }
   int slp_max_unroll_factor = cl->slp_max_unroll();
   int cur_unroll = cl->unrolled_count();
 
@@ -1638,7 +1695,7 @@
   // fall-out values of the main-loop.
   for (DUIterator_Fast imax, i = main_head->fast_outs(imax); i < imax; i++) {
     Node* main_phi = main_head->fast_out(i);
-    if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() >0) {
+    if (main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0) {
       Node *cur_phi = old_new[main_phi->_idx];
       Node *fallnew = clone_up_backedge_goo(main_head->back_control(),
                                             post_head->init_control(),
@@ -1710,7 +1767,7 @@
 
 //------------------------------do_unroll--------------------------------------
 // Unroll the loop body one step - make each trip do 2 iterations.
-void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip ) {
+void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip) {
   assert(LoopUnrollLimit, "");
   CountedLoopNode *loop_head = loop->_head->as_CountedLoop();
   CountedLoopEndNode *loop_end = loop_head->loopexit();
@@ -1733,8 +1790,8 @@
     Node_List rpo_list;
     VectorSet visited(arena);
     visited.set(loop_head->_idx);
-    rpo( loop_head, stack, visited, rpo_list );
-    dump(loop, rpo_list.size(), rpo_list );
+    rpo(loop_head, stack, visited, rpo_list);
+    dump(loop, rpo_list.size(), rpo_list);
   }
 #endif
 
@@ -1811,7 +1868,8 @@
     // Verify that policy_unroll result is still valid.
     const TypeInt* limit_type = _igvn.type(limit)->is_int();
     assert(stride_con > 0 && ((limit_type->_hi - stride_con) < limit_type->_hi) ||
-        stride_con < 0 && ((limit_type->_lo - stride_con) > limit_type->_lo), "sanity");
+           stride_con < 0 && ((limit_type->_lo - stride_con) > limit_type->_lo),
+           "sanity");
 
     if (limit->is_Con()) {
       // The check in policy_unroll and the assert above guarantee
@@ -1829,8 +1887,8 @@
         // zero trip guard limit will be different from loop limit.
         assert(has_ctrl(opaq), "should have it");
         Node* opaq_ctrl = get_ctrl(opaq);
-        limit = new Opaque2Node( C, limit );
-        register_new_node( limit, opaq_ctrl );
+        limit = new Opaque2Node(C, limit);
+        register_new_node(limit, opaq_ctrl);
       }
       if ((stride_con > 0 && (java_subtract(limit_type->_lo, stride_con) < limit_type->_lo)) ||
           (stride_con < 0 && (java_subtract(limit_type->_hi, stride_con) > limit_type->_hi))) {
@@ -1871,15 +1929,16 @@
           adj_limit = new SubINode(limit, stride);
         }
         assert(old_limit != NULL && adj_limit != NULL, "");
-        register_new_node( adj_limit, ctrl ); // adjust amount
+        register_new_node(adj_limit, ctrl); // adjust amount
         Node* adj_cmp = new CmpINode(old_limit, adj_limit);
-        register_new_node( adj_cmp, ctrl );
+        register_new_node(adj_cmp, ctrl);
         Node* adj_bool = new BoolNode(adj_cmp, bt);
-        register_new_node( adj_bool, ctrl );
+        register_new_node(adj_bool, ctrl);
         new_limit = new CMoveINode(adj_bool, adj_limit, adj_max, TypeInt::INT);
       }
       register_new_node(new_limit, ctrl);
     }
+
     assert(new_limit != NULL, "");
     // Replace in loop test.
     assert(loop_end->in(1)->in(1) == cmp, "sanity");
@@ -1929,10 +1988,10 @@
   // Make the fall-in from the original come from the fall-out of the clone.
   for (DUIterator_Fast jmax, j = loop_head->fast_outs(jmax); j < jmax; j++) {
     Node* phi = loop_head->fast_out(j);
-    if( phi->is_Phi() && phi->in(0) == loop_head && phi->outcnt() > 0 ) {
+    if (phi->is_Phi() && phi->in(0) == loop_head && phi->outcnt() > 0) {
       Node *newphi = old_new[phi->_idx];
-      _igvn.hash_delete( phi );
-      _igvn.hash_delete( newphi );
+      _igvn.hash_delete(phi);
+      _igvn.hash_delete(newphi);
 
       phi   ->set_req(LoopNode::   EntryControl, newphi->in(LoopNode::LoopBackControl));
       newphi->set_req(LoopNode::LoopBackControl, phi   ->in(LoopNode::LoopBackControl));
@@ -1940,7 +1999,7 @@
     }
   }
   Node *clone_head = old_new[loop_head->_idx];
-  _igvn.hash_delete( clone_head );
+  _igvn.hash_delete(clone_head);
   loop_head ->set_req(LoopNode::   EntryControl, clone_head->in(LoopNode::LoopBackControl));
   clone_head->set_req(LoopNode::LoopBackControl, loop_head ->in(LoopNode::LoopBackControl));
   loop_head ->set_req(LoopNode::LoopBackControl, C->top());
@@ -1951,18 +2010,19 @@
 
   // Kill the clone's backedge
   Node *newcle = old_new[loop_end->_idx];
-  _igvn.hash_delete( newcle );
+  _igvn.hash_delete(newcle);
   Node *one = _igvn.intcon(1);
   set_ctrl(one, C->root());
   newcle->set_req(1, one);
   // Force clone into same loop body
   uint max = loop->_body.size();
-  for( uint k = 0; k < max; k++ ) {
+  for (uint k = 0; k < max; k++) {
     Node *old = loop->_body.at(k);
     Node *nnn = old_new[old->_idx];
     loop->_body.push(nnn);
-    if (!has_ctrl(old))
+    if (!has_ctrl(old)) {
       set_loop(nnn, loop);
+    }
   }
 
   loop->record_for_igvn();
@@ -1974,7 +2034,7 @@
     for (uint i = 0; i < loop->_body.size(); i++) {
       loop->_body.at(i)->dump();
     }
-    if(C->clone_map().is_debug()) {
+    if (C->clone_map().is_debug()) {
       tty->print("\nCloneMap\n");
       Dict* dict = C->clone_map().dict();
       DictI i(dict);
@@ -1990,12 +2050,11 @@
     }
   }
 #endif
-
 }
 
 //------------------------------do_maximally_unroll----------------------------
 
-void PhaseIdealLoop::do_maximally_unroll( IdealLoopTree *loop, Node_List &old_new ) {
+void PhaseIdealLoop::do_maximally_unroll(IdealLoopTree *loop, Node_List &old_new) {
   CountedLoopNode *cl = loop->_head->as_CountedLoop();
   assert(cl->has_exact_trip_count(), "trip count is not exact");
   assert(cl->trip_count() > 0, "");
@@ -2113,7 +2172,7 @@
 // the pre-loop or the post-loop until the condition holds true in the main
 // loop.  Stride, scale, offset and limit are all loop invariant.  Further,
 // stride and scale are constants (offset and limit often are).
-void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset, Node *low_limit, Node *upper_limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit ) {
+void PhaseIdealLoop::add_constraint(int stride_con, int scale_con, Node *offset, Node *low_limit, Node *upper_limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit) {
   // For positive stride, the pre-loop limit always uses a MAX function
   // and the main loop a MIN function.  For negative stride these are
   // reversed.
@@ -2198,7 +2257,7 @@
     set_ctrl(one, C->root());
 
     Node *plus_one = new AddINode(offset, one);
-    register_new_node( plus_one, pre_ctrl );
+    register_new_node(plus_one, pre_ctrl);
     // Pass (-stride) to indicate pre_loop_cond = NOT(main_loop_cond);
     *pre_limit = adjust_limit((-stride_con), scale, plus_one, upper_limit, *pre_limit, pre_ctrl,
                               scale_con < -1 && stride_con > 0);
@@ -2367,7 +2426,7 @@
 
 //------------------------------do_range_check---------------------------------
 // Eliminate range-checks and other trip-counter vs loop-invariant tests.
-int PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
+int PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
 #ifndef PRODUCT
   if (PrintOpto && VerifyLoopOptimizations) {
     tty->print("Range Check Elimination ");
@@ -2377,15 +2436,16 @@
     loop->dump_head();
   }
 #endif
+
   assert(RangeCheckElimination, "");
   CountedLoopNode *cl = loop->_head->as_CountedLoop();
   // If we fail before trying to eliminate range checks, set multiversion state
   int closed_range_checks = 1;
 
   // protect against stride not being a constant
-  if (!cl->stride_is_con())
+  if (!cl->stride_is_con()) {
     return closed_range_checks;
-
+  }
   // Find the trip counter; we are iteration splitting based on it
   Node *trip_counter = cl->phi();
   // Find the main loop limit; we will trim it's iterations
@@ -2400,7 +2460,7 @@
   }
 
   // Need to find the main-loop zero-trip guard
-  Node *ctrl  = cl->skip_predicates();
+  Node *ctrl = cl->skip_predicates();
   Node *iffm = ctrl->in(0);
   Node *opqzm = iffm->in(1)->in(1)->in(2);
   assert(opqzm->in(1) == main_limit, "do not understand situation");
@@ -2418,8 +2478,9 @@
   // Occasionally it's possible for a pre-loop Opaque1 node to be
   // optimized away and then another round of loop opts attempted.
   // We can not optimize this particular loop in that case.
-  if (pre_opaq1->Opcode() != Op_Opaque1)
+  if (pre_opaq1->Opcode() != Op_Opaque1) {
     return closed_range_checks;
+  }
   Opaque1Node *pre_opaq = (Opaque1Node*)pre_opaq1;
   Node *pre_limit = pre_opaq->in(1);
 
@@ -2429,9 +2490,9 @@
   // Ensure the original loop limit is available from the
   // pre-loop Opaque1 node.
   Node *orig_limit = pre_opaq->original_loop_limit();
-  if (orig_limit == NULL || _igvn.type(orig_limit) == Type::TOP)
+  if (orig_limit == NULL || _igvn.type(orig_limit) == Type::TOP) {
     return closed_range_checks;
-
+  }
   // Must know if its a count-up or count-down loop
 
   int stride_con = cl->stride_con();
@@ -2457,8 +2518,9 @@
 
   Node* predicate_proj = cl->skip_strip_mined()->in(LoopNode::EntryControl);
   assert(predicate_proj->is_Proj() && predicate_proj->in(0)->is_If(), "if projection only");
+
   // Check loop body for tests of trip-counter plus loop-invariant vs loop-variant.
-  for( uint i = 0; i < loop->_body.size(); i++ ) {
+  for (uint i = 0; i < loop->_body.size(); i++) {
     Node *iff = loop->_body[i];
     if (iff->Opcode() == Op_If ||
         iff->Opcode() == Op_RangeCheck) { // Test?
@@ -2466,18 +2528,18 @@
       // we need loop unswitching instead of iteration splitting.
       closed_range_checks++;
       Node *exit = loop->is_loop_exit(iff);
-      if( !exit ) continue;
+      if (!exit) continue;
       int flip = (exit->Opcode() == Op_IfTrue) ? 1 : 0;
 
       // Get boolean condition to test
       Node *i1 = iff->in(1);
-      if( !i1->is_Bool() ) continue;
+      if (!i1->is_Bool()) continue;
       BoolNode *bol = i1->as_Bool();
       BoolTest b_test = bol->_test;
       // Flip sense of test if exit condition is flipped
-      if( flip )
+      if (flip) {
         b_test = b_test.negate();
-
+      }
       // Get compare
       Node *cmp = bol->in(1);
 
@@ -2487,14 +2549,15 @@
       int scale_con= 1;        // Assume trip counter not scaled
 
       Node *limit_c = get_ctrl(limit);
-      if( loop->is_member(get_loop(limit_c) ) ) {
+      if (loop->is_member(get_loop(limit_c))) {
         // Compare might have operands swapped; commute them
         b_test = b_test.commute();
         rc_exp = cmp->in(2);
         limit  = cmp->in(1);
         limit_c = get_ctrl(limit);
-        if( loop->is_member(get_loop(limit_c) ) )
+        if (loop->is_member(get_loop(limit_c))) {
           continue;             // Both inputs are loop varying; cannot RCE
+        }
       }
       // Here we know 'limit' is loop invariant
 
@@ -2513,8 +2576,9 @@
       }
 
       Node *offset_c = get_ctrl(offset);
-      if( loop->is_member( get_loop(offset_c) ) )
+      if (loop->is_member(get_loop(offset_c))) {
         continue;               // Offset is not really loop invariant
+      }
       // Here we know 'offset' is loop invariant.
 
       // As above for the 'limit', the 'offset' maybe pinned below the
@@ -2536,10 +2600,10 @@
       // sense of the test.
 
       // Adjust pre and main loop limits to guard the correct iteration set
-      if( cmp->Opcode() == Op_CmpU ) {// Unsigned compare is really 2 tests
-        if( b_test._test == BoolTest::lt ) { // Range checks always use lt
+      if (cmp->Opcode() == Op_CmpU) { // Unsigned compare is really 2 tests
+        if (b_test._test == BoolTest::lt) { // Range checks always use lt
           // The underflow and overflow limits: 0 <= scale*I+offset < limit
-          add_constraint( stride_con, scale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit );
+          add_constraint(stride_con, scale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit);
           // (0-offset)/scale could be outside of loop iterations range.
           conditional_rc = true;
           Node* init = cl->init_trip();
@@ -2566,29 +2630,29 @@
           continue;             // In release mode, ignore it
         }
       } else {                  // Otherwise work on normal compares
-        switch( b_test._test ) {
+        switch(b_test._test) {
         case BoolTest::gt:
           // Fall into GE case
         case BoolTest::ge:
           // Convert (I*scale+offset) >= Limit to (I*(-scale)+(-offset)) <= -Limit
           scale_con = -scale_con;
-          offset = new SubINode( zero, offset );
-          register_new_node( offset, pre_ctrl );
-          limit  = new SubINode( zero, limit );
-          register_new_node( limit, pre_ctrl );
+          offset = new SubINode(zero, offset);
+          register_new_node(offset, pre_ctrl);
+          limit  = new SubINode(zero, limit);
+          register_new_node(limit, pre_ctrl);
           // Fall into LE case
         case BoolTest::le:
           if (b_test._test != BoolTest::gt) {
             // Convert X <= Y to X < Y+1
-            limit = new AddINode( limit, one );
-            register_new_node( limit, pre_ctrl );
+            limit = new AddINode(limit, one);
+            register_new_node(limit, pre_ctrl);
           }
           // Fall into LT case
         case BoolTest::lt:
           // The underflow and overflow limits: MIN_INT <= scale*I+offset < limit
           // Note: (MIN_INT+1 == -MAX_INT) is used instead of MIN_INT here
           // to avoid problem with scale == -1: MIN_INT/(-1) == MIN_INT.
-          add_constraint( stride_con, scale_con, offset, mini, limit, pre_ctrl, &pre_limit, &main_limit );
+          add_constraint(stride_con, scale_con, offset, mini, limit, pre_ctrl, &pre_limit, &main_limit);
           // ((MIN_INT+1)-offset)/scale could be outside of loop iterations range.
           // Note: negative offset is replaced with 0 but (MIN_INT+1)/scale could
           // still be outside of loop range.
@@ -2604,7 +2668,7 @@
 
       // Kill the eliminated test
       C->set_major_progress();
-      Node *kill_con = _igvn.intcon( 1-flip );
+      Node *kill_con = _igvn.intcon(1-flip);
       set_ctrl(kill_con, C->root());
       _igvn.replace_input_of(iff, 1, kill_con);
       // Find surviving projection
@@ -2624,9 +2688,7 @@
       if (limit->Opcode() == Op_LoadRange) {
         closed_range_checks--;
       }
-
     } // End of is IF
-
   }
   if (predicate_proj != cl->skip_strip_mined()->in(LoopNode::EntryControl)) {
     _igvn.replace_input_of(cl->skip_strip_mined(), LoopNode::EntryControl, predicate_proj);
@@ -2647,21 +2709,21 @@
   Node *main_cle = cl->loopexit();
   Node *main_bol = main_cle->in(1);
   // Hacking loop bounds; need private copies of exit test
-  if( main_bol->outcnt() > 1 ) {// BoolNode shared?
-    main_bol = main_bol->clone();// Clone a private BoolNode
-    register_new_node( main_bol, main_cle->in(0) );
+  if (main_bol->outcnt() > 1) {     // BoolNode shared?
+    main_bol = main_bol->clone();   // Clone a private BoolNode
+    register_new_node(main_bol, main_cle->in(0));
     _igvn.replace_input_of(main_cle, 1, main_bol);
   }
   Node *main_cmp = main_bol->in(1);
-  if( main_cmp->outcnt() > 1 ) { // CmpNode shared?
-    main_cmp = main_cmp->clone();// Clone a private CmpNode
-    register_new_node( main_cmp, main_cle->in(0) );
+  if (main_cmp->outcnt() > 1) {     // CmpNode shared?
+    main_cmp = main_cmp->clone();   // Clone a private CmpNode
+    register_new_node(main_cmp, main_cle->in(0));
     _igvn.replace_input_of(main_bol, 1, main_cmp);
   }
   // Hack the now-private loop bounds
   _igvn.replace_input_of(main_cmp, 2, main_limit);
   // The OpaqueNode is unshared by design
-  assert( opqzm->outcnt() == 1, "cannot hack shared node" );
+  assert(opqzm->outcnt() == 1, "cannot hack shared node");
   _igvn.replace_input_of(opqzm, 1, main_limit);
 
   return closed_range_checks;
@@ -2830,64 +2892,67 @@
 //------------------------------DCE_loop_body----------------------------------
 // Remove simplistic dead code from loop body
 void IdealLoopTree::DCE_loop_body() {
-  for( uint i = 0; i < _body.size(); i++ )
-    if( _body.at(i)->outcnt() == 0 )
-      _body.map( i--, _body.pop() );
+  for (uint i = 0; i < _body.size(); i++) {
+    if (_body.at(i)->outcnt() == 0) {
+      _body.map(i, _body.pop());
+      i--; // Ensure we revisit the updated index.
+    }
+  }
 }
 
 
 //------------------------------adjust_loop_exit_prob--------------------------
 // Look for loop-exit tests with the 50/50 (or worse) guesses from the parsing stage.
 // Replace with a 1-in-10 exit guess.
-void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
+void IdealLoopTree::adjust_loop_exit_prob(PhaseIdealLoop *phase) {
   Node *test = tail();
-  while( test != _head ) {
+  while (test != _head) {
     uint top = test->Opcode();
-    if( top == Op_IfTrue || top == Op_IfFalse ) {
+    if (top == Op_IfTrue || top == Op_IfFalse) {
       int test_con = ((ProjNode*)test)->_con;
       assert(top == (uint)(test_con? Op_IfTrue: Op_IfFalse), "sanity");
       IfNode *iff = test->in(0)->as_If();
-      if( iff->outcnt() == 2 ) {        // Ignore dead tests
+      if (iff->outcnt() == 2) {         // Ignore dead tests
         Node *bol = iff->in(1);
-        if( bol && bol->req() > 1 && bol->in(1) &&
-            ((bol->in(1)->Opcode() == Op_StorePConditional ) ||
-             (bol->in(1)->Opcode() == Op_StoreIConditional ) ||
-             (bol->in(1)->Opcode() == Op_StoreLConditional ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeB ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeS ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeI ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeL ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeP ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndExchangeN ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapB ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapS ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapI ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapL ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapN ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapB ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapS ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapI ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_CompareAndSwapN ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeP ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeN ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapN ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapP ) ||
-             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapN )))
+        if (bol && bol->req() > 1 && bol->in(1) &&
+            ((bol->in(1)->Opcode() == Op_StorePConditional) ||
+             (bol->in(1)->Opcode() == Op_StoreIConditional) ||
+             (bol->in(1)->Opcode() == Op_StoreLConditional) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeB) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeS) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeI) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeL) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeP) ||
+             (bol->in(1)->Opcode() == Op_CompareAndExchangeN) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapB) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapS) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapI) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapL) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_WeakCompareAndSwapN) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapB) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapS) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapI) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapL) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_CompareAndSwapN) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeP) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndExchangeN) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahWeakCompareAndSwapN) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapP) ||
+             (bol->in(1)->Opcode() == Op_ShenandoahCompareAndSwapN)))
           return;               // Allocation loops RARELY take backedge
         // Find the OTHER exit path from the IF
         Node* ex = iff->proj_out(1-test_con);
         float p = iff->_prob;
-        if( !phase->is_member( this, ex ) && iff->_fcnt == COUNT_UNKNOWN ) {
-          if( top == Op_IfTrue ) {
-            if( p < (PROB_FAIR + PROB_UNLIKELY_MAG(3))) {
+        if (!phase->is_member(this, ex) && iff->_fcnt == COUNT_UNKNOWN) {
+          if (top == Op_IfTrue) {
+            if (p < (PROB_FAIR + PROB_UNLIKELY_MAG(3))) {
               iff->_prob = PROB_STATIC_FREQUENT;
             }
           } else {
-            if( p > (PROB_FAIR - PROB_UNLIKELY_MAG(3))) {
+            if (p > (PROB_FAIR - PROB_UNLIKELY_MAG(3))) {
               iff->_prob = PROB_STATIC_INFREQUENT;
             }
           }
@@ -2949,26 +3014,28 @@
   phase->_igvn.replace_input_of(main_cmp, 2, main_cmp->in(2)->in(1));
 }
 
-//------------------------------policy_do_remove_empty_loop--------------------
-// Micro-benchmark spamming.  Policy is to always remove empty loops.
-// The 'DO' part is to replace the trip counter with the value it will
-// have on the last iteration.  This will break the loop.
-bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
+//------------------------------do_remove_empty_loop---------------------------
+// We always attempt remove empty loops.   The approach is to replace the trip
+// counter with the value it will have on the last iteration.  This will break
+// the loop.
+bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) {
   // Minimum size must be empty loop
-  if (_body.size() > EMPTY_LOOP_SIZE)
+  if (_body.size() > EMPTY_LOOP_SIZE) {
     return false;
-
-  if (!_head->is_CountedLoop())
-    return false;     // Dead loop
+  }
+  if (!_head->is_CountedLoop()) {
+    return false;   // Dead loop
+  }
   CountedLoopNode *cl = _head->as_CountedLoop();
-  if (!cl->is_valid_counted_loop())
-    return false; // Malformed loop
-  if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue))))
-    return false;             // Infinite loop
-
+  if (!cl->is_valid_counted_loop()) {
+    return false;   // Malformed loop
+  }
+  if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) {
+    return false;   // Infinite loop
+  }
   if (cl->is_pre_loop()) {
-    // If the loop we are removing is a pre-loop then the main and
-    // post loop can be removed as well
+    // If the loop we are removing is a pre-loop then the main and post loop
+    // can be removed as well.
     remove_main_post_loops(cl, phase);
   }
 
@@ -2978,11 +3045,11 @@
   for (DUIterator_Fast imax, i = cl->fast_outs(imax); i < imax; i++) {
     Node* n = cl->fast_out(i);
     if (n->Opcode() == Op_Phi) {
-      assert(iv == NULL, "Too many phis" );
+      assert(iv == NULL, "Too many phis");
       iv = n;
     }
   }
-  assert(iv == cl->phi(), "Wrong phi" );
+  assert(iv == cl->phi(), "Wrong phi");
 #endif
 
   // main and post loops have explicitly created zero trip guard
@@ -3056,26 +3123,26 @@
   }
   // Note: the final value after increment should not overflow since
   // counted loop has limit check predicate.
-  Node *final = new SubINode( exact_limit, cl->stride() );
+  Node *final = new SubINode(exact_limit, cl->stride());
   phase->register_new_node(final,cl->in(LoopNode::EntryControl));
   phase->_igvn.replace_node(phi,final);
   phase->C->set_major_progress();
   return true;
 }
 
-//------------------------------policy_do_one_iteration_loop-------------------
+//------------------------------do_one_iteration_loop--------------------------
 // Convert one iteration loop into normal code.
-bool IdealLoopTree::policy_do_one_iteration_loop( PhaseIdealLoop *phase ) {
-  if (!_head->as_Loop()->is_valid_counted_loop())
+bool IdealLoopTree::do_one_iteration_loop(PhaseIdealLoop *phase) {
+  if (!_head->as_Loop()->is_valid_counted_loop()) {
     return false; // Only for counted loop
-
+  }
   CountedLoopNode *cl = _head->as_CountedLoop();
   if (!cl->has_exact_trip_count() || cl->trip_count() != 1) {
     return false;
   }
 
 #ifndef PRODUCT
-  if(TraceLoopOpts) {
+  if (TraceLoopOpts) {
     tty->print("OneIteration ");
     this->dump_head();
   }
@@ -3096,20 +3163,22 @@
 
 //=============================================================================
 //------------------------------iteration_split_impl---------------------------
-bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_new ) {
+bool IdealLoopTree::iteration_split_impl(PhaseIdealLoop *phase, Node_List &old_new) {
   // Compute loop trip count if possible.
   compute_trip_count(phase);
 
   // Convert one iteration loop into normal code.
-  if (policy_do_one_iteration_loop(phase))
+  if (do_one_iteration_loop(phase)) {
     return true;
-
+  }
   // Check and remove empty loops (spam micro-benchmarks)
-  if (policy_do_remove_empty_loop(phase))
+  if (do_remove_empty_loop(phase)) {
     return true;  // Here we removed an empty loop
-
-  bool should_peel = policy_peeling(phase); // Should we peel?
-
+  }
+
+  AutoNodeBudget node_budget(phase);
+
+  bool should_peel     = policy_peeling(phase);
   bool should_unswitch = policy_unswitching(phase);
 
   // Non-counted loops may be peeled; exactly 1 iteration is peeled.
@@ -3144,22 +3213,15 @@
       phase->do_unswitching(this, old_new);
       return true;
     }
-    bool should_maximally_unroll =  policy_maximally_unroll(phase);
+    bool should_maximally_unroll = policy_maximally_unroll(phase);
     if (should_maximally_unroll) {
       // Here we did some unrolling and peeling.  Eventually we will
       // completely unroll this loop and it will no longer be a loop.
-      phase->do_maximally_unroll(this,old_new);
+      phase->do_maximally_unroll(this, old_new);
       return true;
     }
   }
 
-  // Skip next optimizations if running low on nodes. Note that
-  // policy_unswitching and policy_maximally_unroll have this check.
-  int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
-  if ((int)(2 * _body.size()) > nodes_left) {
-    return true;
-  }
-
   // Counted loops may be peeled, may need some iterations run up
   // front for RCE, and may want to align loop refs to a cache
   // line.  Thus we clone a full loop up front whose trip count is
@@ -3173,26 +3235,28 @@
   // unrolling), plus any needed for RCE purposes.
 
   bool should_unroll = policy_unroll(phase);
-
-  bool should_rce = policy_range_check(phase);
-
-  bool should_align = policy_align(phase);
-
-  // If not RCE'ing (iteration splitting) or Aligning, then we do not
-  // need a pre-loop.  We may still need to peel an initial iteration but
-  // we will not be needing an unknown number of pre-iterations.
+  bool should_rce    = policy_range_check(phase);
+  // TODO: Remove align -- not used.
+  bool should_align  = policy_align(phase);
+
+  // If not RCE'ing  (iteration splitting) or Aligning, then we  do not need a
+  // pre-loop.  We may still need to peel an initial iteration but we will not
+  // be needing an unknown number of pre-iterations.
   //
-  // Basically, if may_rce_align reports FALSE first time through,
-  // we will not be able to later do RCE or Aligning on this loop.
+  // Basically, if may_rce_align reports FALSE first time through, we will not
+  // be able to later do RCE or Aligning on this loop.
   bool may_rce_align = !policy_peel_only(phase) || should_rce || should_align;
 
   // If we have any of these conditions (RCE, alignment, unrolling) met, then
   // we switch to the pre-/main-/post-loop model.  This model also covers
   // peeling.
   if (should_rce || should_align || should_unroll) {
-    if (cl->is_normal_loop())  // Convert to 'pre/main/post' loops
+    if (cl->is_normal_loop()) { // Convert to 'pre/main/post' loops
+      if (!phase->may_require_nodes(est_loop_clone_sz(3, _body.size()))) {
+        return false;
+      }
       phase->insert_pre_post_loops(this,old_new, !may_rce_align);
-
+    }
     // Adjust the pre- and main-loop limits to let the pre and post loops run
     // with full checks, but the main-loop with no checks.  Remove said
     // checks from the main body.
@@ -3223,14 +3287,14 @@
       phase->do_unroll(this, old_new, true);
     }
 
-    // Adjust the pre-loop limits to align the main body
-    // iterations.
-    if (should_align)
+    // Adjust the pre-loop limits to align the main body iterations.
+    if (should_align) {
       Unimplemented();
-
+    }
   } else {                      // Else we have an unchanged counted loop
-    if (should_peel)           // Might want to peel but do nothing else
+    if (should_peel) {          // Might want to peel but do nothing else
       phase->do_peeling(this,old_new);
+    }
   }
   return true;
 }
@@ -3238,35 +3302,32 @@
 
 //=============================================================================
 //------------------------------iteration_split--------------------------------
-bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new ) {
+bool IdealLoopTree::iteration_split(PhaseIdealLoop* phase, Node_List &old_new) {
   // Recursively iteration split nested loops
-  if (_child && !_child->iteration_split(phase, old_new))
+  if (_child && !_child->iteration_split(phase, old_new)) {
     return false;
+  }
 
   // Clean out prior deadwood
   DCE_loop_body();
 
-
   // Look for loop-exit tests with my 50/50 guesses from the Parsing stage.
   // Replace with a 1-in-10 exit guess.
-  if (_parent /*not the root loop*/ &&
-      !_irreducible &&
-      // Also ignore the occasional dead backedge
-      !tail()->is_top()) {
+  if (!is_root() && is_loop()) {
     adjust_loop_exit_prob(phase);
   }
 
-  // Gate unrolling, RCE and peeling efforts.
-  if (!_child &&                // If not an inner loop, do not split
-      !_irreducible &&
-      _allow_optimizations &&
-      !tail()->is_top()) {     // Also ignore the occasional dead backedge
+  // Unrolling, RCE and peeling efforts, iff innermost loop.
+  if (_allow_optimizations && is_innermost()) {
     if (!_has_call) {
-        if (!iteration_split_impl(phase, old_new)) {
-          return false;
-        }
-    } else if (policy_unswitching(phase)) {
-      phase->do_unswitching(this, old_new);
+      if (!iteration_split_impl(phase, old_new)) {
+        return false;
+      }
+    } else {
+      AutoNodeBudget node_budget(phase);
+      if (policy_unswitching(phase)) {
+        phase->do_unswitching(this, old_new);
+      }
     }
   }
 
@@ -3274,8 +3335,9 @@
   // trip counter when there was no major reshaping.
   phase->reorg_offsets(this);
 
-  if (_next && !_next->iteration_split(phase, old_new))
+  if (_next && !_next->iteration_split(phase, old_new)) {
     return false;
+  }
   return true;
 }
 
@@ -3537,7 +3599,7 @@
 
 bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) {
   // Only for counted inner loops
-  if (!lpt->is_counted() || !lpt->is_inner()) {
+  if (!lpt->is_counted() || !lpt->is_innermost()) {
     return false;
   }
 
--- a/src/hotspot/share/opto/loopUnswitch.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/loopUnswitch.cpp	Tue May 07 11:52:28 2019 -0700
@@ -55,27 +55,31 @@
 // Return TRUE or FALSE if the loop should be unswitched
 // (ie. clone loop with an invariant test that does not exit the loop)
 bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
-  if( !LoopUnswitching ) {
+  if (!LoopUnswitching) {
     return false;
   }
   if (!_head->is_Loop()) {
     return false;
   }
 
+  // If nodes are depleted, some transform has miscalculated its needs.
+  assert(!phase->exceeding_node_budget(), "sanity");
+
   // check for vectorized loops, any unswitching was already applied
-  if (_head->is_CountedLoop() && _head->as_CountedLoop()->do_unroll_only()) {
+  if (_head->is_CountedLoop() && _head->as_CountedLoop()->is_unroll_only()) {
     return false;
   }
 
-  int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
-  if ((int)(2 * _body.size()) > nodes_left) {
-    return false; // Too speculative if running low on nodes.
-  }
   LoopNode* head = _head->as_Loop();
   if (head->unswitch_count() + 1 > head->unswitch_max()) {
     return false;
   }
-  return phase->find_unswitching_candidate(this) != NULL;
+  if (phase->find_unswitching_candidate(this) == NULL) {
+    return false;
+  }
+
+  // Too speculative if running low on nodes.
+  return phase->may_require_nodes(est_loop_clone_sz(3, _body.size()));
 }
 
 //------------------------------find_unswitching_candidate-----------------------------
--- a/src/hotspot/share/opto/loopnode.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/loopnode.cpp	Tue May 07 11:52:28 2019 -0700
@@ -42,17 +42,13 @@
 #include "opto/superword.hpp"
 
 //=============================================================================
-//------------------------------is_loop_iv-------------------------------------
-// Determine if a node is Counted loop induction variable.
-// The method is declared in node.hpp.
-const Node* Node::is_loop_iv() const {
-  if (this->is_Phi() && !this->as_Phi()->is_copy() &&
-      this->as_Phi()->region()->is_CountedLoop() &&
-      this->as_Phi()->region()->as_CountedLoop()->phi() == this) {
-    return this;
-  } else {
-    return NULL;
-  }
+//--------------------------is_cloop_ind_var-----------------------------------
+// Determine if a node is a counted loop induction variable.
+// NOTE: The method is declared in "node.hpp".
+bool Node::is_cloop_ind_var() const {
+  return (is_Phi() && !as_Phi()->is_copy() &&
+          as_Phi()->region()->is_CountedLoop() &&
+          as_Phi()->region()->as_CountedLoop()->phi() == this);
 }
 
 //=============================================================================
@@ -2942,14 +2938,15 @@
   }
 
   if (ReassociateInvariants) {
+    AutoNodeBudget node_budget(this, AutoNodeBudget::NO_BUDGET_CHECK);
     // Reassociate invariants and prep for split_thru_phi
     for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
       IdealLoopTree* lpt = iter.current();
       bool is_counted = lpt->is_counted();
-      if (!is_counted || !lpt->is_inner()) continue;
+      if (!is_counted || !lpt->is_innermost()) continue;
 
       // check for vectorized loops, any reassociation of invariants was already done
-      if (is_counted && lpt->_head->as_CountedLoop()->do_unroll_only()) continue;
+      if (is_counted && lpt->_head->as_CountedLoop()->is_unroll_only()) continue;
 
       lpt->reassociate_invariants(this);
 
--- a/src/hotspot/share/opto/loopnode.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/loopnode.hpp	Tue May 07 11:52:28 2019 -0700
@@ -264,7 +264,7 @@
   bool is_reduction_loop() const { return (_loop_flags&HasReductions) == HasReductions; }
   bool was_slp_analyzed () const { return (_loop_flags&WasSlpAnalyzed) == WasSlpAnalyzed; }
   bool has_passed_slp   () const { return (_loop_flags&PassedSlpAnalysis) == PassedSlpAnalysis; }
-  bool do_unroll_only      () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; }
+  bool is_unroll_only   () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; }
   bool is_main_no_pre_loop() const { return _loop_flags & MainHasNoPreLoop; }
   bool has_atomic_post_loop  () const { return (_loop_flags & HasAtomicPostLoop) == HasAtomicPostLoop; }
   void set_main_no_pre_loop() { _loop_flags |= MainHasNoPreLoop; }
@@ -370,26 +370,49 @@
 };
 
 
-inline CountedLoopEndNode *CountedLoopNode::loopexit_or_null() const {
-  Node *bc = back_control();
-  if( bc == NULL ) return NULL;
-  Node *le = bc->in(0);
-  if( le->Opcode() != Op_CountedLoopEnd )
-    return NULL;
-  return (CountedLoopEndNode*)le;
+inline CountedLoopEndNode* CountedLoopNode::loopexit_or_null() const {
+  Node* bctrl = back_control();
+  if (bctrl == NULL) return NULL;
+
+  Node* lexit = bctrl->in(0);
+  return (CountedLoopEndNode*)
+      (lexit->Opcode() == Op_CountedLoopEnd ? lexit : NULL);
 }
-inline CountedLoopEndNode *CountedLoopNode::loopexit() const {
+
+inline CountedLoopEndNode* CountedLoopNode::loopexit() const {
   CountedLoopEndNode* cle = loopexit_or_null();
   assert(cle != NULL, "loopexit is NULL");
   return cle;
 }
-inline Node *CountedLoopNode::init_trip() const { return loopexit_or_null() ? loopexit()->init_trip() : NULL; }
-inline Node *CountedLoopNode::stride() const { return loopexit_or_null() ? loopexit()->stride() : NULL; }
-inline int CountedLoopNode::stride_con() const { return loopexit_or_null() ? loopexit()->stride_con() : 0; }
-inline bool CountedLoopNode::stride_is_con() const { return loopexit_or_null() && loopexit()->stride_is_con(); }
-inline Node *CountedLoopNode::limit() const { return loopexit_or_null() ? loopexit()->limit() : NULL; }
-inline Node *CountedLoopNode::incr() const { return loopexit_or_null() ? loopexit()->incr() : NULL; }
-inline Node *CountedLoopNode::phi() const { return loopexit_or_null() ? loopexit()->phi() : NULL; }
+
+inline Node* CountedLoopNode::init_trip() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->init_trip() : NULL;
+}
+inline Node* CountedLoopNode::stride() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->stride() : NULL;
+}
+inline int CountedLoopNode::stride_con() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->stride_con() : 0;
+}
+inline bool CountedLoopNode::stride_is_con() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL && cle->stride_is_con();
+}
+inline Node* CountedLoopNode::limit() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->limit() : NULL;
+}
+inline Node* CountedLoopNode::incr() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->incr() : NULL;
+}
+inline Node* CountedLoopNode::phi() const {
+  CountedLoopEndNode* cle = loopexit_or_null();
+  return cle != NULL ? cle->phi() : NULL;
+}
 
 //------------------------------LoopLimitNode-----------------------------
 // Counted Loop limit node which represents exact final iterator value:
@@ -456,9 +479,9 @@
   IdealLoopTree *_child;        // First child in loop tree
 
   // The head-tail backedge defines the loop.
-  // If tail is NULL then this loop has multiple backedges as part of the
-  // same loop.  During cleanup I'll peel off the multiple backedges; merge
-  // them at the loop bottom and flow 1 real backedge into the loop.
+  // If a loop has multiple backedges, this is addressed during cleanup where
+  // we peel off the multiple backedges,  merging all edges at the bottom and
+  // ensuring that one proper backedge flow into the loop.
   Node *_head;                  // Head of loop
   Node *_tail;                  // Tail of loop
   inline Node *tail();          // Handle lazy update of _tail field
@@ -487,7 +510,10 @@
       _safepts(NULL),
       _required_safept(NULL),
       _allow_optimizations(true)
-  { }
+  {
+    precond(_head != NULL);
+    precond(_tail != NULL);
+  }
 
   // Is 'l' a member of 'this'?
   bool is_member(const IdealLoopTree *l) const; // Test for nested membership
@@ -558,10 +584,10 @@
   bool policy_unswitching( PhaseIdealLoop *phase ) const;
 
   // Micro-benchmark spamming.  Remove empty loops.
-  bool policy_do_remove_empty_loop( PhaseIdealLoop *phase );
+  bool do_remove_empty_loop( PhaseIdealLoop *phase );
 
   // Convert one iteration loop into normal code.
-  bool policy_do_one_iteration_loop( PhaseIdealLoop *phase );
+  bool do_one_iteration_loop( PhaseIdealLoop *phase );
 
   // Return TRUE or FALSE if the loop should be peeled or not.  Peel if we can
   // make some loop-invariant test (usually a null-check) happen before the
@@ -615,9 +641,11 @@
   // Put loop body on igvn work list
   void record_for_igvn();
 
-  bool is_loop()    { return !_irreducible && _tail && !_tail->is_top(); }
-  bool is_inner()   { return is_loop() && _child == NULL; }
-  bool is_counted() { return is_loop() && _head != NULL && _head->is_CountedLoop(); }
+  bool is_root() { return _parent == NULL; }
+  // A proper/reducible loop w/o any (occasional) dead back-edge.
+  bool is_loop() { return !_irreducible && !tail()->is_top(); }
+  bool is_counted()   { return is_loop() && _head->is_CountedLoop(); }
+  bool is_innermost() { return is_loop() && _child == NULL; }
 
   void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase);
 
@@ -630,13 +658,14 @@
 };
 
 // -----------------------------PhaseIdealLoop---------------------------------
-// Computes the mapping from Nodes to IdealLoopTrees.  Organizes IdealLoopTrees into a
-// loop tree.  Drives the loop-based transformations on the ideal graph.
+// Computes the mapping from Nodes to IdealLoopTrees. Organizes IdealLoopTrees
+// into a loop tree. Drives the loop-based transformations on the ideal graph.
 class PhaseIdealLoop : public PhaseTransform {
   friend class IdealLoopTree;
   friend class SuperWord;
   friend class CountedLoopReserveKit;
   friend class ShenandoahBarrierC2Support;
+  friend class AutoNodeBudget;
 
   // Pre-computed def-use info
   PhaseIterGVN &_igvn;
@@ -731,8 +760,7 @@
   }
   Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag );
 
-  // Helper function for directing control inputs away from CFG split
-  // points.
+  // Helper function for directing control inputs away from CFG split points.
   Node *find_non_split_ctrl( Node *ctrl ) const {
     if (ctrl != NULL) {
       if (ctrl->is_MultiBranch()) {
@@ -883,7 +911,8 @@
     _igvn(igvn),
     _verify_me(NULL),
     _verify_only(true),
-    _dom_lca_tags(arena()) { // Thread::resource_area
+    _dom_lca_tags(arena()),  // Thread::resource_area
+    _nodes_required(UINT_MAX) {
     build_and_optimize(LoopOptsVerify);
   }
 
@@ -899,7 +928,8 @@
     _igvn(igvn),
     _verify_me(NULL),
     _verify_only(false),
-    _dom_lca_tags(arena()) { // Thread::resource_area
+    _dom_lca_tags(arena()),  // Thread::resource_area
+    _nodes_required(UINT_MAX) {
     build_and_optimize(mode);
   }
 
@@ -909,7 +939,8 @@
     _igvn(igvn),
     _verify_me(verify_me),
     _verify_only(false),
-    _dom_lca_tags(arena()) { // Thread::resource_area
+    _dom_lca_tags(arena()),  // Thread::resource_area
+    _nodes_required(UINT_MAX) {
     build_and_optimize(LoopOptsVerify);
   }
 
@@ -1320,8 +1351,54 @@
     return C->live_nodes() > threshold;
   }
 
+  // A simplistic node request tracking mechanism, where
+  //   = UINT_MAX   Request not valid or made final.
+  //   < UINT_MAX   Nodes currently requested (estimate).
+  uint _nodes_required;
+
+  bool exceeding_node_budget(uint required = 0) {
+    assert(C->live_nodes() < C->max_node_limit(), "sanity");
+    uint available = C->max_node_limit() - C->live_nodes();
+    return available < required + _nodes_required;
+  }
+
+  uint require_nodes(uint require) {
+    precond(require > 0);
+    _nodes_required += MAX2(100u, require); // Keep requests at minimum 100.
+    return _nodes_required;
+  }
+
+  bool may_require_nodes(uint require) {
+    return !exceeding_node_budget(require) && require_nodes(require) > 0;
+  }
+
+  void require_nodes_begin() {
+    assert(_nodes_required == UINT_MAX, "Bad state (begin).");
+    _nodes_required = 0;
+  }
+
+  // Final check  that the requested nodes  did not exceed the  limit and that
+  // the request  was reasonably  correct with  respect to  the number  of new
+  // nodes introduced by any transform since the last 'begin'.
+  void require_nodes_final_check(uint live_at_begin) {
+    uint required = _nodes_required;
+    require_nodes_final();
+    uint delta = C->live_nodes() - live_at_begin;
+    assert(delta <= 2 * required, "Bad node estimate (actual: %d, request: %d)",
+           delta, required);
+  }
+
+  void require_nodes_final() {
+    assert(_nodes_required < UINT_MAX, "Bad state (final).");
+    assert(!exceeding_node_budget(), "Too many NODES required!");
+    _nodes_required = UINT_MAX;
+  }
+
   bool _created_loop_node;
+
 public:
+  uint nodes_required() const { return _nodes_required; }
+
   void set_created_loop_node() { _created_loop_node = true; }
   bool created_loop_node()     { return _created_loop_node; }
   void register_new_node( Node *n, Node *blk );
@@ -1347,6 +1424,62 @@
   void rpo( Node *start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list ) const;
 };
 
+
+class AutoNodeBudget : public StackObj
+{
+public:
+  enum budget_check_t { BUDGET_CHECK, NO_BUDGET_CHECK };
+
+  AutoNodeBudget(PhaseIdealLoop* phase, budget_check_t chk = BUDGET_CHECK)
+    : _phase(phase),
+      _check_at_final(chk == BUDGET_CHECK),
+      _nodes_at_begin(0)
+  {
+    precond(_phase != NULL);
+
+    _nodes_at_begin = _phase->C->live_nodes();
+    _phase->require_nodes_begin();
+  }
+
+  ~AutoNodeBudget() {
+    if (_check_at_final) {
+#ifndef PRODUCT
+      if (TraceLoopOpts) {
+        uint request = _phase->nodes_required();
+
+        if (request > 0) {
+          uint delta = _phase->C->live_nodes() - _nodes_at_begin;
+
+          if (request < delta) {
+            tty->print_cr("Exceeding node budget: %d < %d", request, delta);
+          }
+        }
+      }
+#endif
+      _phase->require_nodes_final_check(_nodes_at_begin);
+    } else {
+      _phase->require_nodes_final();
+    }
+  }
+
+private:
+  PhaseIdealLoop* _phase;
+  bool _check_at_final;
+  uint _nodes_at_begin;
+};
+
+// The Estimated Loop Clone Size: CloneFactor * (BodySize + BC) + CC, where BC
+// and CC are totally ad-hoc/magic "body" and "clone" constants, respectively,
+// used to ensure that node usage estimates made are on the safe side, for the
+// most part.
+static inline uint est_loop_clone_sz(uint fact, uint size) {
+  uint const bc = 31;
+  uint const cc = 41;
+  uint estimate = fact * (size + bc) + cc;
+  return (estimate - cc) / fact == size + bc ? estimate : UINT_MAX;
+}
+
+
 // This kit may be used for making of a reserved copy of a loop before this loop
 //  goes under non-reversible changes.
 //
@@ -1410,14 +1543,11 @@
 };// class CountedLoopReserveKit
 
 inline Node* IdealLoopTree::tail() {
-// Handle lazy update of _tail field
-  Node *n = _tail;
-  //while( !n->in(0) )  // Skip dead CFG nodes
-    //n = n->in(1);
-  if (n->in(0) == NULL)
-    n = _phase->get_ctrl(n);
-  _tail = n;
-  return n;
+  // Handle lazy update of _tail field.
+  if (_tail->in(0) == NULL) {
+    _tail = _phase->get_ctrl(_tail);
+  }
+  return _tail;
 }
 
 
--- a/src/hotspot/share/opto/loopopts.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/loopopts.cpp	Tue May 07 11:52:28 2019 -0700
@@ -2662,7 +2662,7 @@
     assert(!loop->is_member(get_loop(use_c)), "should be outside loop");
     get_loop(use_c)->_body.push(n_clone);
     _igvn.register_new_node_with_optimizer(n_clone);
-#if !defined(PRODUCT)
+#ifndef PRODUCT
     if (TracePartialPeeling) {
       tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx);
     }
@@ -2700,7 +2700,7 @@
     set_ctrl(n_clone, get_ctrl(n));
     sink_list.push(n_clone);
     not_peel <<= n_clone->_idx;  // add n_clone to not_peel set.
-#if !defined(PRODUCT)
+#ifndef PRODUCT
     if (TracePartialPeeling) {
       tty->print_cr("special not_peeled cloning old: %d new: %d", n->_idx, n_clone->_idx);
     }
@@ -3046,7 +3046,7 @@
         opc == Op_CatchProj ||
         opc == Op_Jump      ||
         opc == Op_JumpProj) {
-#if !defined(PRODUCT)
+#ifndef PRODUCT
       if (TracePartialPeeling) {
         tty->print_cr("\nExit control too complex: lp: %d", head->_idx);
       }
@@ -3102,7 +3102,7 @@
     return false;
   }
 
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TraceLoopOpts) {
     tty->print("PartialPeel  ");
     loop->dump_head();
@@ -3131,6 +3131,10 @@
   Node_List worklist(area);
   Node_List sink_list(area);
 
+  if (!may_require_nodes(est_loop_clone_sz(2, loop->_body.size()))) {
+    return false;
+  }
+
   // Set of cfg nodes to peel are those that are executable from
   // the head through last_peel.
   assert(worklist.size() == 0, "should be empty");
@@ -3179,7 +3183,7 @@
     if (use->is_Phi()) old_phi_cnt++;
   }
 
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TracePartialPeeling) {
     tty->print_cr("\npeeled list");
   }
@@ -3190,7 +3194,7 @@
   uint cloned_for_outside_use = 0;
   for (i = 0; i < peel_list.size();) {
     Node* n = peel_list.at(i);
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TracePartialPeeling) n->dump();
 #endif
     bool incr = true;
@@ -3212,7 +3216,7 @@
             not_peel <<= n->_idx; // add n to not_peel set.
             peel_list.remove(i);
             incr = false;
-#if !defined(PRODUCT)
+#ifndef PRODUCT
             if (TracePartialPeeling) {
               tty->print_cr("sink to not_peeled region: %d newbb: %d",
                             n->_idx, get_ctrl(n)->_idx);
@@ -3231,7 +3235,7 @@
   }
 
   if (new_phi_cnt > old_phi_cnt + PartialPeelNewPhiDelta) {
-#if !defined(PRODUCT)
+#ifndef PRODUCT
     if (TracePartialPeeling) {
       tty->print_cr("\nToo many new phis: %d  old %d new cmpi: %c",
                     new_phi_cnt, old_phi_cnt, new_peel_if != NULL?'T':'F');
@@ -3389,7 +3393,7 @@
   C->set_major_progress();
   loop->record_for_igvn();
 
-#if !defined(PRODUCT)
+#ifndef PRODUCT
   if (TracePartialPeeling) {
     tty->print_cr("\nafter partial peel one iteration");
     Node_List wl(area);
@@ -3429,10 +3433,10 @@
   Node *exit = cle->proj_out(false);
   Node *phi = cl->phi();
 
-  // Check for the special case of folks using the pre-incremented
-  // trip-counter on the fall-out path (forces the pre-incremented
-  // and post-incremented trip counter to be live at the same time).
-  // Fix this by adjusting to use the post-increment trip counter.
+  // Check for the special case when using the pre-incremented trip-counter on
+  // the fall-out  path (forces the pre-incremented  and post-incremented trip
+  // counter to be live  at the same time).  Fix this by  adjusting to use the
+  // post-increment trip counter.
 
   bool progress = true;
   while (progress) {
--- a/src/hotspot/share/opto/memnode.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/memnode.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1047,11 +1047,11 @@
         // Try harder before giving up. Unify base pointers with casts (e.g., raw/non-raw pointers).
         intptr_t st_off = 0;
         Node* st_base = AddPNode::Ideal_base_and_offset(st_adr, phase, st_off);
-        if (ld_base == NULL)                        return NULL;
-        if (st_base == NULL)                        return NULL;
-        if (ld_base->uncast() != st_base->uncast()) return NULL;
-        if (ld_off != st_off)                       return NULL;
-        if (ld_off == Type::OffsetBot)              return NULL;
+        if (ld_base == NULL)                                   return NULL;
+        if (st_base == NULL)                                   return NULL;
+        if (!ld_base->eqv_uncast(st_base, /*keep_deps=*/true)) return NULL;
+        if (ld_off != st_off)                                  return NULL;
+        if (ld_off == Type::OffsetBot)                         return NULL;
         // Same base, same offset.
         // Possible improvement for arrays: check index value instead of absolute offset.
 
@@ -1062,6 +1062,7 @@
         // (Actually, we haven't yet proven the Q's are the same.)
         // In other words, we are loading from a casted version of
         // the same pointer-and-offset that we stored to.
+        // Casted version may carry a dependency and it is respected.
         // Thus, we are able to replace L by V.
       }
       // Now prove that we have a LoadQ matched to a StoreQ, for some Q.
--- a/src/hotspot/share/opto/node.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/node.cpp	Tue May 07 11:52:28 2019 -0700
@@ -891,13 +891,15 @@
 //-----------------------------uncast---------------------------------------
 // %%% Temporary, until we sort out CheckCastPP vs. CastPP.
 // Strip away casting.  (It is depth-limited.)
-Node* Node::uncast() const {
+// Optionally, keep casts with dependencies.
+Node* Node::uncast(bool keep_deps) const {
   // Should be inline:
   //return is_ConstraintCast() ? uncast_helper(this) : (Node*) this;
-  if (is_ConstraintCast())
-    return uncast_helper(this);
-  else
+  if (is_ConstraintCast()) {
+    return uncast_helper(this, keep_deps);
+  } else {
     return (Node*) this;
+  }
 }
 
 // Find out of current node that matches opcode.
@@ -929,7 +931,7 @@
 
 
 //---------------------------uncast_helper-------------------------------------
-Node* Node::uncast_helper(const Node* p) {
+Node* Node::uncast_helper(const Node* p, bool keep_deps) {
 #ifdef ASSERT
   uint depth_count = 0;
   const Node* orig_p = p;
@@ -947,6 +949,9 @@
     if (p == NULL || p->req() != 2) {
       break;
     } else if (p->is_ConstraintCast()) {
+      if (keep_deps && p->as_ConstraintCast()->carry_dependency()) {
+        break; // stop at casts with dependencies
+      }
       p = p->in(1);
     } else {
       break;
--- a/src/hotspot/share/opto/node.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/node.hpp	Tue May 07 11:52:28 2019 -0700
@@ -456,10 +456,10 @@
   void setup_is_top();
 
   // Strip away casting.  (It is depth-limited.)
-  Node* uncast() const;
+  Node* uncast(bool keep_deps = false) const;
   // Return whether two Nodes are equivalent, after stripping casting.
-  bool eqv_uncast(const Node* n) const {
-    return (this->uncast() == n->uncast());
+  bool eqv_uncast(const Node* n, bool keep_deps = false) const {
+    return (this->uncast(keep_deps) == n->uncast(keep_deps));
   }
 
   // Find out of current node that matches opcode.
@@ -470,7 +470,7 @@
   bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4);
 
 private:
-  static Node* uncast_helper(const Node* n);
+  static Node* uncast_helper(const Node* n, bool keep_deps);
 
   // Add an output edge to the end of the list
   void add_out( Node *n ) {
@@ -1007,9 +1007,9 @@
   // value, if it appears (by local graph inspection) to be computed by a simple conditional.
   bool is_iteratively_computed();
 
-  // Determine if a node is Counted loop induction variable.
-  // The method is defined in loopnode.cpp.
-  const Node* is_loop_iv() const;
+  // Determine if a node is a counted loop induction variable.
+  // NOTE: The method is defined in "loopnode.cpp".
+  bool is_cloop_ind_var() const;
 
   // Return a node with opcode "opc" and same inputs as "this" if one can
   // be found; Otherwise return NULL;
--- a/src/hotspot/share/opto/parse.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/parse.hpp	Tue May 07 11:52:28 2019 -0700
@@ -88,6 +88,10 @@
                                 ciMethod* caller_method,
                                 JVMState* jvms,
                                 WarmCallInfo* wci_result);
+  bool        is_not_reached(ciMethod* callee_method,
+                             ciMethod* caller_method,
+                             int caller_bci,
+                             ciCallProfile& profile);
   void        print_inlining(ciMethod* callee_method, int caller_bci,
                              ciMethod* caller_method, bool success) const;
 
--- a/src/hotspot/share/opto/subnode.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/subnode.cpp	Tue May 07 11:52:28 2019 -0700
@@ -114,31 +114,37 @@
 }
 
 //=============================================================================
+//------------------------------Helper function--------------------------------
 
-//------------------------------Helper function--------------------------------
-static bool ok_to_convert(Node* inc, Node* iv) {
-    // Do not collapse (x+c0)-y if "+" is a loop increment, because the
-    // "-" is loop invariant and collapsing extends the live-range of "x"
-    // to overlap with the "+", forcing another register to be used in
-    // the loop.
-    // This test will be clearer with '&&' (apply DeMorgan's rule)
-    // but I like the early cutouts that happen here.
-    const PhiNode *phi;
-    if( ( !inc->in(1)->is_Phi() ||
-          !(phi=inc->in(1)->as_Phi()) ||
-          phi->is_copy() ||
-          !phi->region()->is_CountedLoop() ||
-          inc != phi->region()->as_CountedLoop()->incr() )
-       &&
-        // Do not collapse (x+c0)-iv if "iv" is a loop induction variable,
-        // because "x" maybe invariant.
-        ( !iv->is_loop_iv() )
-      ) {
-      return true;
-    } else {
-      return false;
-    }
+static bool is_cloop_increment(Node* inc) {
+  precond(inc->Opcode() == Op_AddI || inc->Opcode() == Op_AddL);
+
+  if (!inc->in(1)->is_Phi()) {
+    return false;
+  }
+  const PhiNode* phi = inc->in(1)->as_Phi();
+
+  if (phi->is_copy() || !phi->region()->is_CountedLoop()) {
+    return false;
+  }
+
+  return inc == phi->region()->as_CountedLoop()->incr();
 }
+
+// Given the expression '(x + C) - v', or
+//                      'v - (x + C)', we examine nodes '+' and 'v':
+//
+//  1. Do not convert if '+' is a counted-loop increment, because the '-' is
+//     loop invariant and converting extends the live-range of 'x' to overlap
+//     with the '+', forcing another register to be used in the loop.
+//
+//  2. Do not convert if 'v' is a counted-loop induction variable, because
+//     'x' might be invariant.
+//
+static bool ok_to_convert(Node* inc, Node* var) {
+  return !(is_cloop_increment(inc) || var->is_cloop_ind_var());
+}
+
 //------------------------------Ideal------------------------------------------
 Node *SubINode::Ideal(PhaseGVN *phase, bool can_reshape){
   Node *in1 = in(1);
--- a/src/hotspot/share/opto/superword.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/opto/superword.cpp	Tue May 07 11:52:28 2019 -0700
@@ -145,7 +145,7 @@
   // Skip any loops already optimized by slp
   if (cl->is_vectorized_loop()) return;
 
-  if (cl->do_unroll_only()) return;
+  if (cl->is_unroll_only()) return;
 
   if (cl->is_main_loop()) {
     // Check for pre-loop ending with CountedLoopEnd(Bool(Cmp(x,Opaque1(limit))))
--- a/src/hotspot/share/prims/jvmtiEnvBase.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiEnvBase.hpp	Tue May 07 11:52:28 2019 -0700
@@ -254,7 +254,7 @@
     return _tag_map;
   }
 
-  JvmtiTagMap* acquire_tag_map() {
+  JvmtiTagMap* tag_map_acquire() {
     return OrderAccess::load_acquire(&_tag_map);
   }
 
--- a/src/hotspot/share/prims/jvmtiTagMap.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/prims/jvmtiTagMap.cpp	Tue May 07 11:52:28 2019 -0700
@@ -514,7 +514,7 @@
 // returns the tag map for the given environments. If the tag map
 // doesn't exist then it is created.
 JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
-  JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->acquire_tag_map();
+  JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map_acquire();
   if (tag_map == NULL) {
     MutexLocker mu(JvmtiThreadState_lock);
     tag_map = ((JvmtiEnvBase*)env)->tag_map();
@@ -3318,7 +3318,7 @@
   if (JvmtiEnv::environments_might_exist()) {
     JvmtiEnvIterator it;
     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
-      JvmtiTagMap* tag_map = env->acquire_tag_map();
+      JvmtiTagMap* tag_map = env->tag_map_acquire();
       if (tag_map != NULL && !tag_map->is_empty()) {
         tag_map->do_weak_oops(is_alive, f);
       }
--- a/src/hotspot/share/prims/whitebox.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/prims/whitebox.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1080,6 +1080,24 @@
   return result;
 WB_END
 
+WB_ENTRY(void, WB_MarkMethodProfiled(JNIEnv* env, jobject o, jobject method))
+  jmethodID jmid = reflected_method_to_jmid(thread, env, method);
+  CHECK_JNI_EXCEPTION(env);
+  methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid));
+
+  MethodData* mdo = mh->method_data();
+  if (mdo == NULL) {
+    Method::build_interpreter_method_data(mh, CHECK_AND_CLEAR);
+    mdo = mh->method_data();
+  }
+  mdo->init();
+  InvocationCounter* icnt = mdo->invocation_counter();
+  InvocationCounter* bcnt = mdo->backedge_counter();
+  // set i-counter according to TieredThresholdPolicy::is_method_profiled
+  icnt->set(InvocationCounter::wait_for_compile, Tier4MinInvocationThreshold);
+  bcnt->set(InvocationCounter::wait_for_compile, Tier4CompileThreshold);
+WB_END
+
 WB_ENTRY(void, WB_ClearMethodState(JNIEnv* env, jobject o, jobject method))
   jmethodID jmid = reflected_method_to_jmid(thread, env, method);
   CHECK_JNI_EXCEPTION(env);
@@ -2209,6 +2227,8 @@
       CC"(Ljava/lang/reflect/Executable;II)Z",        (void*)&WB_EnqueueMethodForCompilation},
   {CC"enqueueInitializerForCompilation0",
       CC"(Ljava/lang/Class;I)Z",                      (void*)&WB_EnqueueInitializerForCompilation},
+  {CC"markMethodProfiled",
+      CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_MarkMethodProfiled},
   {CC"clearMethodState0",
       CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
   {CC"lockCompilation",    CC"()V",                   (void*)&WB_LockCompilation},
--- a/src/hotspot/share/runtime/biasedLocking.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/biasedLocking.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -499,6 +499,7 @@
   JavaThread* _requesting_thread;
   BiasedLocking::Condition _status_code;
   traceid _biased_locker_id;
+  uint64_t _safepoint_id;
 
 public:
   VM_RevokeBias(Handle* obj, JavaThread* requesting_thread)
@@ -506,14 +507,16 @@
     , _objs(NULL)
     , _requesting_thread(requesting_thread)
     , _status_code(BiasedLocking::NOT_BIASED)
-    , _biased_locker_id(0) {}
+    , _biased_locker_id(0)
+    , _safepoint_id(0) {}
 
   VM_RevokeBias(GrowableArray<Handle>* objs, JavaThread* requesting_thread)
     : _obj(NULL)
     , _objs(objs)
     , _requesting_thread(requesting_thread)
     , _status_code(BiasedLocking::NOT_BIASED)
-    , _biased_locker_id(0) {}
+    , _biased_locker_id(0)
+    , _safepoint_id(0) {}
 
   virtual VMOp_Type type() const { return VMOp_RevokeBias; }
 
@@ -545,6 +548,7 @@
       if (biased_locker != NULL) {
         _biased_locker_id = JFR_THREAD_ID(biased_locker);
       }
+      _safepoint_id = SafepointSynchronize::safepoint_counter();
       clean_up_cached_monitor_info();
       return;
     } else {
@@ -560,6 +564,10 @@
   traceid biased_locker() const {
     return _biased_locker_id;
   }
+
+  uint64_t safepoint_id() const {
+    return _safepoint_id;
+  }
 };
 
 
@@ -581,17 +589,15 @@
 
   virtual void doit() {
     _status_code = bulk_revoke_or_rebias_at_safepoint((*_obj)(), _bulk_rebias, _attempt_rebias_of_object, _requesting_thread);
+    _safepoint_id = SafepointSynchronize::safepoint_counter();
     clean_up_cached_monitor_info();
   }
+
+  bool is_bulk_rebias() const {
+    return _bulk_rebias;
+  }
 };
 
-template <typename E>
-static void set_safepoint_id(E* event) {
-  assert(event != NULL, "invariant");
-  // Subtract 1 to match the id of events committed inside the safepoint
-  event->set_safepointId(SafepointSynchronize::safepoint_counter() - 1);
-}
-
 static void post_self_revocation_event(EventBiasedLockSelfRevocation* event, Klass* k) {
   assert(event != NULL, "invariant");
   assert(k != NULL, "invariant");
@@ -600,24 +606,25 @@
   event->commit();
 }
 
-static void post_revocation_event(EventBiasedLockRevocation* event, Klass* k, VM_RevokeBias* revoke) {
+static void post_revocation_event(EventBiasedLockRevocation* event, Klass* k, VM_RevokeBias* op) {
   assert(event != NULL, "invariant");
   assert(k != NULL, "invariant");
-  assert(revoke != NULL, "invariant");
+  assert(op != NULL, "invariant");
   assert(event->should_commit(), "invariant");
   event->set_lockClass(k);
-  set_safepoint_id(event);
-  event->set_previousOwner(revoke->biased_locker());
+  event->set_safepointId(op->safepoint_id());
+  event->set_previousOwner(op->biased_locker());
   event->commit();
 }
 
-static void post_class_revocation_event(EventBiasedLockClassRevocation* event, Klass* k, bool disabled_bias) {
+static void post_class_revocation_event(EventBiasedLockClassRevocation* event, Klass* k, VM_BulkRevokeBias* op) {
   assert(event != NULL, "invariant");
   assert(k != NULL, "invariant");
+  assert(op != NULL, "invariant");
   assert(event->should_commit(), "invariant");
   event->set_revokedClass(k);
-  event->set_disableBiasing(disabled_bias);
-  set_safepoint_id(event);
+  event->set_disableBiasing(!op->is_bulk_rebias());
+  event->set_safepointId(op->safepoint_id());
   event->commit();
 }
 
@@ -729,7 +736,7 @@
                                 attempt_rebias);
   VMThread::execute(&bulk_revoke);
   if (event.should_commit()) {
-    post_class_revocation_event(&event, obj->klass(), heuristics != HR_BULK_REBIAS);
+    post_class_revocation_event(&event, obj->klass(), &bulk_revoke);
   }
   return bulk_revoke.status_code();
 }
--- a/src/hotspot/share/runtime/deoptimization.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/deoptimization.cpp	Tue May 07 11:52:28 2019 -0700
@@ -674,8 +674,7 @@
       int top_frame_expression_stack_adjustment = 0;
       methodHandle mh(thread, iframe->interpreter_frame_method());
       OopMapCache::compute_one_oop_map(mh, iframe->interpreter_frame_bci(), &mask);
-      BytecodeStream str(mh);
-      str.set_start(iframe->interpreter_frame_bci());
+      BytecodeStream str(mh, iframe->interpreter_frame_bci());
       int max_bci = mh->code_size();
       // Get to the next bytecode if possible
       assert(str.bci() < max_bci, "bci in interpreter frame out of bounds");
--- a/src/hotspot/share/runtime/java.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/java.cpp	Tue May 07 11:52:28 2019 -0700
@@ -526,11 +526,31 @@
     vm_direct_exit(code);
   }
 
+  // We'd like to add an entry to the XML log to show that the VM is
+  // terminating, but we can't safely do that here. The logic to make
+  // XML termination logging safe is tied to the termination of the
+  // VMThread, and it doesn't terminate on this exit path. See 8222534.
+
   if (VMThread::vm_thread() != NULL) {
+    if (thread->is_Java_thread()) {
+      // We must be "in_vm" for the code below to work correctly.
+      // Historically there must have been some exit path for which
+      // that was not the case and so we set it explicitly - even
+      // though we no longer know what that path may be.
+      ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
+    }
+
     // Fire off a VM_Exit operation to bring VM to a safepoint and exit
     VM_Exit op(code);
-    if (thread->is_Java_thread())
-      ((JavaThread*)thread)->set_thread_state(_thread_in_vm);
+
+    // 4945125 The vm thread comes to a safepoint during exit.
+    // GC vm_operations can get caught at the safepoint, and the
+    // heap is unparseable if they are caught. Grab the Heap_lock
+    // to prevent this. The GC vm_operations will not be able to
+    // queue until after we release it, but we never do that as we
+    // are terminating the VM process.
+    MutexLocker ml(Heap_lock);
+
     VMThread::execute(&op);
     // should never reach here; but in case something wrong with VM Thread.
     vm_direct_exit(code);
--- a/src/hotspot/share/runtime/objectMonitor.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1926,3 +1926,11 @@
 
   DEBUG_ONLY(InitDone = true;)
 }
+
+void ObjectMonitor::print_on(outputStream* st) const {
+  // The minimal things to print for markOop printing, more can be added for debugging and logging.
+  st->print("{contentions=0x%08x,waiters=0x%08x"
+            ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
+            contentions(), waiters(), recursions(),
+            p2i(owner()));
+}
--- a/src/hotspot/share/runtime/objectMonitor.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/objectMonitor.hpp	Tue May 07 11:52:28 2019 -0700
@@ -139,6 +139,7 @@
   friend class ObjectSynchronizer;
   friend class ObjectWaiter;
   friend class VMStructs;
+  JVMCI_ONLY(friend class JVMCIVMStructs;)
 
   volatile markOop   _header;       // displaced object header word - mark
   void*     volatile _object;       // backward object pointer - strong root
@@ -291,6 +292,9 @@
   void      notify(TRAPS);
   void      notifyAll(TRAPS);
 
+  void      print() const { print_on(tty); }
+  void      print_on(outputStream* st) const;
+
 // Use the following at your own risk
   intptr_t  complete_exit(TRAPS);
   void      reenter(intptr_t recursions, TRAPS);
--- a/src/hotspot/share/runtime/thread.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/thread.cpp	Tue May 07 11:52:28 2019 -0700
@@ -1575,18 +1575,15 @@
   return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
 }
 
-void JavaThread::collect_counters(JVMCIEnv* jvmci_env, JVMCIPrimitiveArray array) {
-  if (JVMCICounterSize > 0) {
-    JavaThreadIteratorWithHandle jtiwh;
-    int len = jvmci_env->get_length(array);
-    for (int i = 0; i < len; i++) {
-      jvmci_env->put_long_at(array, i, _jvmci_old_thread_counters[i]);
-    }
-    for (; JavaThread *tp = jtiwh.next(); ) {
-      if (jvmci_counters_include(tp)) {
-        for (int i = 0; i < len; i++) {
-          jvmci_env->put_long_at(array, i, jvmci_env->get_long_at(array, i) + tp->_jvmci_counters[i]);
-        }
+void JavaThread::collect_counters(jlong* array, int length) {
+  assert(length == JVMCICounterSize, "wrong value");
+  for (int i = 0; i < length; i++) {
+    array[i] = _jvmci_old_thread_counters[i];
+  }
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) {
+    if (jvmci_counters_include(tp)) {
+      for (int i = 0; i < length; i++) {
+        array[i] += tp->_jvmci_counters[i];
       }
     }
   }
--- a/src/hotspot/share/runtime/thread.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/thread.hpp	Tue May 07 11:52:28 2019 -0700
@@ -1152,7 +1152,7 @@
 
  public:
   static jlong* _jvmci_old_thread_counters;
-  static void collect_counters(JVMCIEnv* JVMCIENV, JVMCIPrimitiveArray array);
+  static void collect_counters(jlong* array, int length);
  private:
 #endif // INCLUDE_JVMCI
 
--- a/src/hotspot/share/runtime/tieredThresholdPolicy.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/tieredThresholdPolicy.cpp	Tue May 07 11:52:28 2019 -0700
@@ -353,6 +353,16 @@
       TieredStopAtLevel > CompLevel_full_profile &&
       max_method != NULL && is_method_profiled(max_method)) {
     max_task->set_comp_level(CompLevel_limited_profile);
+
+    if (CompileBroker::compilation_is_complete(max_method, max_task->osr_bci(), CompLevel_limited_profile)) {
+      if (PrintTieredEvents) {
+        print_event(REMOVE_FROM_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
+      }
+      compile_queue->remove_and_mark_stale(max_task);
+      max_method->clear_queued_for_compilation();
+      return NULL;
+    }
+
     if (PrintTieredEvents) {
       print_event(UPDATE_IN_QUEUE, max_method, max_method, max_task->osr_bci(), (CompLevel)max_task->comp_level());
     }
--- a/src/hotspot/share/runtime/vmOperations.cpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/runtime/vmOperations.cpp	Tue May 07 11:52:28 2019 -0700
@@ -30,6 +30,7 @@
 #include "gc/shared/isGCActiveMark.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
+#include "logging/logConfiguration.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/symbol.hpp"
@@ -437,14 +438,14 @@
         if (thr->is_Compiler_thread()) {
 #if INCLUDE_JVMCI
           CompilerThread* ct = (CompilerThread*) thr;
-          if (ct->compiler() == NULL || !ct->compiler()->is_jvmci() || !UseJVMCINativeLibrary) {
+          if (ct->compiler() == NULL || !ct->compiler()->is_jvmci()) {
             num_active_compiler_thread++;
           } else {
-            // When using a compiler in a JVMCI shared library, it's possible
-            // for one compiler thread to grab a lock in the shared library,
-            // enter HotSpot and go to sleep on the shutdown safepoint. Another
-            // JVMCI shared library compiler thread can then attempt to grab the
-            // lock and thus never make progress.
+            // A JVMCI compiler thread never accesses VM data structures
+            // while in _thread_in_native state so there's no need to wait
+            // for it and potentially add a 300 millisecond delay to VM
+            // shutdown.
+            num_active--;
           }
 #else
           num_active_compiler_thread++;
@@ -469,6 +470,16 @@
 }
 
 void VM_Exit::doit() {
+
+  if (VerifyBeforeExit) {
+    HandleMark hm(VMThread::vm_thread());
+    // Among other things, this ensures that Eden top is correct.
+    Universe::heap()->prepare_for_verify();
+    // Silent verification so as not to pollute normal output,
+    // unless we really asked for it.
+    Universe::verify();
+  }
+
   CompileBroker::set_should_block();
 
   // Wait for a short period for threads in native to block. Any thread
@@ -480,10 +491,17 @@
 
   set_vm_exited();
 
+  // We'd like to call IdealGraphPrinter::clean_up() to finalize the
+  // XML logging, but we can't safely do that here. The logic to make
+  // XML termination logging safe is tied to the termination of the
+  // VMThread, and it doesn't terminate on this exit path. See 8222534.
+
   // cleanup globals resources before exiting. exit_globals() currently
   // cleans up outputStream resources and PerfMemory resources.
   exit_globals();
 
+  LogConfiguration::finalize();
+
   // Check for exit hook
   exit_hook_t exit_hook = Arguments::exit_hook();
   if (exit_hook != NULL) {
--- a/src/hotspot/share/utilities/debug.hpp	Fri May 03 17:06:42 2019 -0700
+++ b/src/hotspot/share/utilities/debug.hpp	Tue May 07 11:52:28 2019 -0700
@@ -63,6 +63,9 @@
 // For backward compatibility.
 #define assert(p, ...) vmassert(p, __VA_ARGS__)
 
+#define precond(p)   assert(p, "precond")
+#define postcond(p)  assert(p, "postcond")
+
 #ifndef ASSERT
 #define vmassert_status(p, status, msg)
 #else
--- a/src/java.base/share/classes/java/lang/String.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/lang/String.java	Tue May 07 11:52:28 2019 -0700
@@ -75,7 +75,7 @@
  *     System.out.println("abc");
  *     String cde = "cde";
  *     System.out.println("abc" + cde);
- *     String c = "abc".substring(2,3);
+ *     String c = "abc".substring(2, 3);
  *     String d = cde.substring(1, 2);
  * </pre></blockquote>
  * <p>
@@ -2160,27 +2160,48 @@
      * @since 1.5
      */
     public String replace(CharSequence target, CharSequence replacement) {
-        String tgtStr = target.toString();
+        String trgtStr = target.toString();
         String replStr = replacement.toString();
-        int j = indexOf(tgtStr);
-        if (j < 0) {
+        int thisLen = length();
+        int trgtLen = trgtStr.length();
+        int replLen = replStr.length();
+
+        if (trgtLen > 0) {
+            if (trgtLen == 1 && replLen == 1) {
+                return replace(trgtStr.charAt(0), replStr.charAt(0));
+            }
+
+            boolean thisIsLatin1 = this.isLatin1();
+            boolean trgtIsLatin1 = trgtStr.isLatin1();
+            boolean replIsLatin1 = replStr.isLatin1();
+            String ret = (thisIsLatin1 && trgtIsLatin1 && replIsLatin1)
+                    ? StringLatin1.replace(value, thisLen,
+                                           trgtStr.value, trgtLen,
+                                           replStr.value, replLen)
+                    : StringUTF16.replace(value, thisLen, thisIsLatin1,
+                                          trgtStr.value, trgtLen, trgtIsLatin1,
+                                          replStr.value, replLen, replIsLatin1);
+            if (ret != null) {
+                return ret;
+            }
             return this;
+
+        } else { // trgtLen == 0
+            int resultLen;
+            try {
+                resultLen = Math.addExact(thisLen, Math.multiplyExact(
+                        Math.addExact(thisLen, 1), replLen));
+            } catch (ArithmeticException ignored) {
+                throw new OutOfMemoryError();
+            }
+
+            StringBuilder sb = new StringBuilder(resultLen);
+            sb.append(replStr);
+            for (int i = 0; i < thisLen; ++i) {
+                sb.append(charAt(i)).append(replStr);
+            }
+            return sb.toString();
         }
-        int tgtLen = tgtStr.length();
-        int tgtLen1 = Math.max(tgtLen, 1);
-        int thisLen = length();
-
-        int newLenHint = thisLen - tgtLen + replStr.length();
-        if (newLenHint < 0) {
-            throw new OutOfMemoryError();
-        }
-        StringBuilder sb = new StringBuilder(newLenHint);
-        int i = 0;
-        do {
-            sb.append(this, i, j).append(replStr);
-            i = j + tgtLen;
-        } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
-        return sb.append(this, i, thisLen).toString();
     }
 
     /**
--- a/src/java.base/share/classes/java/lang/StringLatin1.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/lang/StringLatin1.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,6 +42,14 @@
 
 final class StringLatin1 {
 
+    /**
+     * The maximum size of array to allocate (unless necessary).
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
+     */
+    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
     public static char charAt(byte[] value, int index) {
         if (index < 0 || index >= value.length) {
             throw new StringIndexOutOfBoundsException(index);
@@ -304,7 +312,7 @@
             }
             if (i < len) {
                 if (canEncode(newChar)) {
-                    byte buf[] = new byte[len];
+                    byte[] buf = StringConcatHelper.newArray(len);
                     for (int j = 0; j < i; j++) {    // TBD arraycopy?
                         buf[j] = value[j];
                     }
@@ -330,6 +338,64 @@
         return null; // for string to return this;
     }
 
+    public static String replace(byte[] value, int valLen, byte[] targ,
+                                 int targLen, byte[] repl, int replLen)
+    {
+        assert targLen > 0;
+        int i, j, p = 0;
+        if (valLen == 0 || (i = indexOf(value, valLen, targ, targLen, 0)) < 0) {
+            return null; // for string to return this;
+        }
+
+        // find and store indices of substrings to replace
+        int[] pos = new int[16];
+        pos[0] = i;
+        i += targLen;
+        while ((j = indexOf(value, valLen, targ, targLen, i)) > 0) {
+            if (++p == pos.length) {
+                int cap = p + (p >> 1);
+                // overflow-conscious code
+                if (cap - MAX_ARRAY_SIZE > 0) {
+                    if (p == MAX_ARRAY_SIZE) {
+                        throw new OutOfMemoryError();
+                    }
+                    cap = MAX_ARRAY_SIZE;
+                }
+                pos = Arrays.copyOf(pos, cap);
+            }
+            pos[p] = j;
+            i = j + targLen;
+        }
+
+        int resultLen;
+        try {
+            resultLen = Math.addExact(valLen,
+                    Math.multiplyExact(++p, replLen - targLen));
+        } catch (ArithmeticException ignored) {
+            throw new OutOfMemoryError();
+        }
+        if (resultLen == 0) {
+            return "";
+        }
+
+        byte[] result = StringConcatHelper.newArray(resultLen);
+        int posFrom = 0, posTo = 0;
+        for (int q = 0; q < p; ++q) {
+            int nextPos = pos[q];
+            while (posFrom < nextPos) {
+                result[posTo++] = value[posFrom++];
+            }
+            posFrom += targLen;
+            for (int k = 0; k < replLen; ++k) {
+                result[posTo++] = repl[k];
+            }
+        }
+        while (posFrom < valLen) {
+            result[posTo++] = value[posFrom++];
+        }
+        return new String(result, LATIN1);
+    }
+
     // case insensitive
     public static boolean regionMatchesCI(byte[] value, int toffset,
                                           byte[] other, int ooffset, int len) {
--- a/src/java.base/share/classes/java/lang/StringUTF16.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/lang/StringUTF16.java	Tue May 07 11:52:28 2019 -0700
@@ -574,7 +574,7 @@
             }
         }
         if (i < len) {
-            byte buf[] = new byte[value.length];
+            byte[] buf = new byte[value.length];
             for (int j = 0; j < i; j++) {
                 putChar(buf, j, getChar(value, j)); // TBD:arraycopy?
             }
@@ -582,21 +582,145 @@
                 char c = getChar(value, i);
                 putChar(buf, i, c == oldChar ? newChar : c);
                 i++;
-           }
-           // Check if we should try to compress to latin1
-           if (String.COMPACT_STRINGS &&
-               !StringLatin1.canEncode(oldChar) &&
-               StringLatin1.canEncode(newChar)) {
-               byte[] val = compress(buf, 0, len);
-               if (val != null) {
-                   return new String(val, LATIN1);
-               }
-           }
-           return new String(buf, UTF16);
+            }
+            // Check if we should try to compress to latin1
+            if (String.COMPACT_STRINGS &&
+                !StringLatin1.canEncode(oldChar) &&
+                StringLatin1.canEncode(newChar)) {
+                byte[] val = compress(buf, 0, len);
+                if (val != null) {
+                    return new String(val, LATIN1);
+                }
+            }
+            return new String(buf, UTF16);
         }
         return null;
     }
 
+    public static String replace(byte[] value, int valLen, boolean valLat1,
+                                 byte[] targ, int targLen, boolean targLat1,
+                                 byte[] repl, int replLen, boolean replLat1)
+    {
+        assert targLen > 0;
+        assert !valLat1 || !targLat1 || !replLat1;
+
+        //  Possible combinations of the arguments/result encodings:
+        //  +---+--------+--------+--------+-----------------------+
+        //  | # | VALUE  | TARGET | REPL   | RESULT                |
+        //  +===+========+========+========+=======================+
+        //  | 1 | Latin1 | Latin1 |  UTF16 | null or UTF16         |
+        //  +---+--------+--------+--------+-----------------------+
+        //  | 2 | Latin1 |  UTF16 | Latin1 | null                  |
+        //  +---+--------+--------+--------+-----------------------+
+        //  | 3 | Latin1 |  UTF16 |  UTF16 | null                  |
+        //  +---+--------+--------+--------+-----------------------+
+        //  | 4 |  UTF16 | Latin1 | Latin1 | null or UTF16         |
+        //  +---+--------+--------+--------+-----------------------+
+        //  | 5 |  UTF16 | Latin1 |  UTF16 | null or UTF16         |
+        //  +---+--------+--------+--------+-----------------------+
+        //  | 6 |  UTF16 |  UTF16 | Latin1 | null, Latin1 or UTF16 |
+        //  +---+--------+--------+--------+-----------------------+
+        //  | 7 |  UTF16 |  UTF16 |  UTF16 | null or UTF16         |
+        //  +---+--------+--------+--------+-----------------------+
+
+        if (String.COMPACT_STRINGS && valLat1 && !targLat1) {
+            // combinations 2 or 3
+            return null; // for string to return this;
+        }
+
+        int i = (String.COMPACT_STRINGS && valLat1)
+                        ? StringLatin1.indexOf(value, targ) :
+                (String.COMPACT_STRINGS && targLat1)
+                        ? indexOfLatin1(value, targ)
+                        : indexOf(value, targ);
+        if (i < 0) {
+            return null; // for string to return this;
+        }
+
+        // find and store indices of substrings to replace
+        int j, p = 0;
+        int[] pos = new int[16];
+        pos[0] = i;
+        i += targLen;
+        while ((j = ((String.COMPACT_STRINGS && valLat1)
+                            ? StringLatin1.indexOf(value, valLen, targ, targLen, i) :
+                     (String.COMPACT_STRINGS && targLat1)
+                            ? indexOfLatin1(value, valLen, targ, targLen, i)
+                            : indexOf(value, valLen, targ, targLen, i))) > 0)
+        {
+            if (++p == pos.length) {
+                int cap = p + (p >> 1);
+                // overflow-conscious code
+                if (cap - MAX_ARRAY_SIZE > 0) {
+                    if (p == MAX_ARRAY_SIZE) {
+                        throw new OutOfMemoryError();
+                    }
+                    cap = MAX_ARRAY_SIZE;
+                }
+                pos = Arrays.copyOf(pos, cap);
+            }
+            pos[p] = j;
+            i = j + targLen;
+        }
+
+        int resultLen;
+        try {
+            resultLen = Math.addExact(valLen,
+                    Math.multiplyExact(++p, replLen - targLen));
+        } catch (ArithmeticException ignored) {
+            throw new OutOfMemoryError();
+        }
+        if (resultLen == 0) {
+            return "";
+        }
+
+        byte[] result = newBytesFor(resultLen);
+        int posFrom = 0, posTo = 0;
+        for (int q = 0; q < p; ++q) {
+            int nextPos = pos[q];
+            if (String.COMPACT_STRINGS && valLat1) {
+                while (posFrom < nextPos) {
+                    char c = (char)(value[posFrom++] & 0xff);
+                    putChar(result, posTo++, c);
+                }
+            } else {
+                while (posFrom < nextPos) {
+                    putChar(result, posTo++, getChar(value, posFrom++));
+                }
+            }
+            posFrom += targLen;
+            if (String.COMPACT_STRINGS && replLat1) {
+                for (int k = 0; k < replLen; ++k) {
+                    char c = (char)(repl[k] & 0xff);
+                    putChar(result, posTo++, c);
+                }
+            } else {
+                for (int k = 0; k < replLen; ++k) {
+                    putChar(result, posTo++, getChar(repl, k));
+                }
+            }
+        }
+        if (String.COMPACT_STRINGS && valLat1) {
+            while (posFrom < valLen) {
+                char c = (char)(value[posFrom++] & 0xff);
+                putChar(result, posTo++, c);
+            }
+        } else {
+            while (posFrom < valLen) {
+                putChar(result, posTo++, getChar(value, posFrom++));
+            }
+        }
+
+        if (String.COMPACT_STRINGS && replLat1 && !targLat1) {
+            // combination 6
+            byte[] lat1Result = compress(result, 0, resultLen);
+            if (lat1Result != null) {
+                return new String(lat1Result, LATIN1);
+            }
+        }
+        return new String(result, UTF16);
+    }
+
     public static boolean regionMatchesCI(byte[] value, int toffset,
                                           byte[] other, int ooffset, int len) {
         int last = toffset + len;
@@ -1430,6 +1554,15 @@
 
     static final int MAX_LENGTH = Integer.MAX_VALUE >> 1;
 
+
+    /**
+     * The maximum size of array to allocate (unless necessary).
+     * Some VMs reserve some header words in an array.
+     * Attempts to allocate larger arrays may result in
+     * OutOfMemoryError: Requested array size exceeds VM limit
+     */
+    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
+
     // Used by trusted callers.  Assumes all necessary bounds checks have
     // been done by the caller.
 
--- a/src/java.base/share/classes/java/lang/constant/ClassDesc.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/lang/constant/ClassDesc.java	Tue May 07 11:52:28 2019 -0700
@@ -213,7 +213,7 @@
      * @param moreNestedNames the unqualified name(s) of the remaining levels of
      *                       nested class
      * @return a {@linkplain ClassDesc} describing the nested class
-     * @throws NullPointerException if any argument is {@code null}
+     * @throws NullPointerException if any argument or its contents is {@code null}
      * @throws IllegalStateException if this {@linkplain ClassDesc} does not
      * describe a class or interface type
      * @throws IllegalArgumentException if the nested class name is invalid
@@ -221,6 +221,11 @@
     default ClassDesc nested(String firstNestedName, String... moreNestedNames) {
         if (!isClassOrInterface())
             throw new IllegalStateException("Outer class is not a class or interface type");
+        validateMemberName(firstNestedName, false);
+        requireNonNull(moreNestedNames);
+        for (String addNestedNames : moreNestedNames) {
+            validateMemberName(addNestedNames, false);
+        }
         return moreNestedNames.length == 0
                ? nested(firstNestedName)
                : nested(firstNestedName + Stream.of(moreNestedNames).collect(joining("$", "$", "")));
--- a/src/java.base/share/classes/java/net/ServerSocket.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/net/ServerSocket.java	Tue May 07 11:52:28 2019 -0700
@@ -32,6 +32,7 @@
 import java.nio.channels.ServerSocketChannel;
 import java.security.AccessController;
 import java.security.PrivilegedExceptionAction;
+import java.util.Objects;
 import java.util.Set;
 import java.util.Collections;
 
@@ -81,6 +82,7 @@
      * @since 12
      */
     protected ServerSocket(SocketImpl impl) {
+        Objects.requireNonNull(impl);
         this.impl = impl;
     }
 
--- a/src/java.base/share/classes/java/net/URL.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/net/URL.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1403,8 +1403,9 @@
 
         URLStreamHandlerFactory fac;
         boolean checkedWithFactory = false;
+        boolean overrideableProtocol = isOverrideable(protocol);
 
-        if (isOverrideable(protocol) && jdk.internal.misc.VM.isBooted()) {
+        if (overrideableProtocol && jdk.internal.misc.VM.isBooted()) {
             // Use the factory (if any). Volatile read makes
             // URLStreamHandlerFactory appear fully initialized to current thread.
             fac = factory;
@@ -1440,7 +1441,8 @@
 
             // Check with factory if another thread set a
             // factory since our last check
-            if (!checkedWithFactory && (fac = factory) != null) {
+            if (overrideableProtocol && !checkedWithFactory &&
+                (fac = factory) != null) {
                 handler2 = fac.createURLStreamHandler(protocol);
             }
 
--- a/src/java.base/share/classes/java/nio/file/FileSystems.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/nio/file/FileSystems.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -252,10 +252,8 @@
      * Suppose there is a provider identified by the scheme {@code "memory"}
      * installed:
      * <pre>
-     *   Map&lt;String,String&gt; env = new HashMap&lt;&gt;();
-     *   env.put("capacity", "16G");
-     *   env.put("blockSize", "4k");
-     *   FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"), env);
+     *  FileSystem fs = FileSystems.newFileSystem(URI.create("memory:///?name=logfs"),
+     *                                            Map.of("capacity", "16G", "blockSize", "4k"));
      * </pre>
      *
      * @param   uri
@@ -365,14 +363,13 @@
      * systems where the contents of one or more files is treated as a file
      * system.
      *
-     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
-     * installed} providers. It invokes, in turn, each provider's {@link
-     * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)} method
-     * with an empty map. If a provider returns a file system then the iteration
-     * terminates and the file system is returned. If none of the installed
-     * providers return a {@code FileSystem} then an attempt is made to locate
-     * the provider using the given class loader. If a provider returns a file
-     * system then the lookup terminates and the file system is returned.
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path, Map, ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method with an empty map. If none
+     * of the installed providers return a {@code FileSystem} then an attempt is
+     * made to locate the provider using the given class loader. If a provider
+     * returns a file system then the lookup terminates and the file system is
+     * returned.
      *
      * @param   path
      *          the path to the file
@@ -396,10 +393,131 @@
                                            ClassLoader loader)
         throws IOException
     {
+        return newFileSystem(path, Map.of(), loader);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
+     * {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
+     * method is invoked to construct the new file system.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   env
+     *          a map of provider specific properties to configure the file system;
+     *          may be empty
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path, Map<String,?> env)
+        throws IOException
+    {
+        return newFileSystem(path, env, null);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method first attempts to locate an installed provider in exactly
+     * the same manner as the {@link #newFileSystem(Path,Map,ClassLoader)
+     * newFileSystem(Path, Map, ClassLoader)} method. If found, the provider's
+     * {@link FileSystemProvider#newFileSystem(Path, Map) newFileSystem(Path, Map)}
+     * method is invoked with an empty map to construct the new file system.
+     *
+     * @param   path
+     *          the path to the file
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path) throws IOException {
+        return newFileSystem(path, Map.of(), null);
+    }
+
+    /**
+     * Constructs a new {@code FileSystem} to access the contents of a file as a
+     * file system.
+     *
+     * <p> This method makes use of specialized providers that create pseudo file
+     * systems where the contents of one or more files is treated as a file
+     * system.
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers. It invokes, in turn, each provider's {@link
+     * FileSystemProvider#newFileSystem(Path,Map) newFileSystem(Path,Map)}
+     * method. If a provider returns a file system then the iteration
+     * terminates and the file system is returned.
+     * If none of the installed providers return a {@code FileSystem} then
+     * an attempt is made to locate the provider using the given class loader.
+     * If a provider returns a file
+     * system, then the lookup terminates and the file system is returned.
+     *
+     * @param   path
+     *          the path to the file
+     * @param   env
+     *          a map of provider specific properties to configure the file system;
+     *          may be empty
+     * @param   loader
+     *          the class loader to locate the provider or {@code null} to only
+     *          attempt to locate an installed provider
+     *
+     * @return  a new file system
+     *
+     * @throws  ProviderNotFoundException
+     *          if a provider supporting this file type cannot be located
+     * @throws  ServiceConfigurationError
+     *          when an error occurs while loading a service provider
+     * @throws  IOException
+     *          if an I/O error occurs
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission
+     *
+     * @since 13
+     */
+    public static FileSystem newFileSystem(Path path, Map<String,?> env,
+                                           ClassLoader loader)
+        throws IOException
+    {
         if (path == null)
             throw new NullPointerException();
-        Map<String,?> env = Collections.emptyMap();
-
         // check installed providers
         for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
             try {
--- a/src/java.base/share/classes/java/util/Objects.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/util/Objects.java	Tue May 07 11:52:28 2019 -0700
@@ -62,10 +62,11 @@
      * Returns {@code true} if the arguments are equal to each other
      * and {@code false} otherwise.
      * Consequently, if both arguments are {@code null}, {@code true}
-     * is returned and if exactly one argument is {@code null}, {@code
-     * false} is returned.  Otherwise, equality is determined by using
-     * the {@link Object#equals equals} method of the first
-     * argument.
+     * is returned.  Otherwise, if the first argument is not {@code
+     * null}, equality is determined by calling the {@link
+     * Object#equals equals} method of the first argument with the
+     * second argument of this method. Otherwise, {@code false} is
+     * returned.
      *
      * @param a an object
      * @param b an object to be compared with {@code a} for equality
--- a/src/java.base/share/classes/java/util/regex/Pattern.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/java/util/regex/Pattern.java	Tue May 07 11:52:28 2019 -0700
@@ -1678,7 +1678,13 @@
             return;
         int j = i;
         i += 2;
-        int[] newtemp = new int[j + 3*(pLen-i) + 2];
+        int newTempLen;
+        try {
+            newTempLen = Math.addExact(j + 2, Math.multiplyExact(3, pLen - i));
+        } catch (ArithmeticException ae) {
+            throw new OutOfMemoryError();
+        }
+        int[] newtemp = new int[newTempLen];
         System.arraycopy(temp, 0, newtemp, 0, j);
 
         boolean inQuote = true;
--- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java	Tue May 07 11:52:28 2019 -0700
@@ -826,6 +826,10 @@
         // reading lock
         private final ReentrantLock readLock = new ReentrantLock();
 
+        // closing status
+        private volatile boolean isClosing;
+        private volatile boolean hasDepleted;
+
         AppInputStream() {
             this.appDataIsAvailable = false;
             this.buffer = ByteBuffer.allocate(4096);
@@ -871,8 +875,7 @@
          * and returning "-1" on non-fault EOF status.
          */
         @Override
-        public int read(byte[] b, int off, int len)
-                throws IOException {
+        public int read(byte[] b, int off, int len) throws IOException {
             if (b == null) {
                 throw new NullPointerException("the target buffer is null");
             } else if (off < 0 || len < 0 || len > b.length - off) {
@@ -900,12 +903,40 @@
                 throw new SocketException("Connection or inbound has closed");
             }
 
+            // Check if the input stream has been depleted.
+            //
+            // Note that the "hasDepleted" rather than the isClosing
+            // filed is checked here, in case the closing process is
+            // still in progress.
+            if (hasDepleted) {
+                if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                    SSLLogger.fine("The input stream has been depleted");
+                }
+
+                return -1;
+            }
+
             // Read the available bytes at first.
             //
             // Note that the receiving and processing of post-handshake message
             // are also synchronized with the read lock.
             readLock.lock();
             try {
+                // Double check if the Socket is invalid (error or closed).
+                if (conContext.isBroken || conContext.isInboundClosed()) {
+                    throw new SocketException(
+                            "Connection or inbound has closed");
+                }
+
+                // Double check if the input stream has been depleted.
+                if (hasDepleted) {
+                    if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                        SSLLogger.fine("The input stream is closing");
+                    }
+
+                    return -1;
+                }
+
                 int remains = available();
                 if (remains > 0) {
                     int howmany = Math.min(remains, len);
@@ -938,7 +969,17 @@
                     return -1;
                 }
             } finally {
-                readLock.unlock();
+                // Check if the input stream is closing.
+                //
+                // If the deplete() did not hold the lock, clean up the
+                // input stream here.
+                try {
+                    if (isClosing) {
+                        readLockedDeplete();
+                    }
+                } finally {
+                    readLock.unlock();
+                }
             }
         }
 
@@ -1016,34 +1057,48 @@
          * socket gracefully, without impact the performance too much.
          */
         private void deplete() {
-            if (conContext.isInboundClosed()) {
+            if (conContext.isInboundClosed() || isClosing) {
                 return;
             }
 
-            readLock.lock();
+            isClosing = true;
+            if (readLock.tryLock()) {
+                try {
+                    readLockedDeplete();
+                } finally {
+                    readLock.unlock();
+                }
+            }
+        }
+
+        /**
+         * Try to use up the input records.
+         *
+         * Please don't call this method unless the readLock is held by
+         * the current thread.
+         */
+        private void readLockedDeplete() {
+            // double check
+            if (hasDepleted || conContext.isInboundClosed()) {
+                return;
+            }
+
+            if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) {
+                return;
+            }
+
+            SSLSocketInputRecord socketInputRecord =
+                    (SSLSocketInputRecord)conContext.inputRecord;
             try {
-                // double check
-                if (conContext.isInboundClosed()) {
-                    return;
-                }
-
-                if (!(conContext.inputRecord instanceof SSLSocketInputRecord)) {
-                    return;
-                }
-
-                SSLSocketInputRecord socketInputRecord =
-                        (SSLSocketInputRecord)conContext.inputRecord;
-                try {
-                    socketInputRecord.deplete(
-                        conContext.isNegotiated && (getSoTimeout() > 0));
-                } catch (IOException ioe) {
-                    if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
-                        SSLLogger.warning(
-                            "input stream close depletion failed", ioe);
-                    }
+                socketInputRecord.deplete(
+                    conContext.isNegotiated && (getSoTimeout() > 0));
+            } catch (Exception ex) {
+                if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
+                    SSLLogger.warning(
+                        "input stream close depletion failed", ex);
                 }
             } finally {
-                readLock.unlock();
+                hasDepleted = true;
             }
         }
     }
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileAttributeViews.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,15 +73,23 @@
 
             boolean haveFd = false;
             boolean useFutimes = false;
+            boolean useLutimes = false;
             int fd = -1;
             try {
-                fd = file.openForAttributeAccess(followLinks);
-                if (fd != -1) {
-                    haveFd = true;
-                    useFutimes = futimesSupported();
+                if (!followLinks) {
+                    useLutimes = lutimesSupported() &&
+                        UnixFileAttributes.get(file, false).isSymbolicLink();
+                }
+                if (!useLutimes) {
+                    fd = file.openForAttributeAccess(followLinks);
+                    if (fd != -1) {
+                        haveFd = true;
+                        useFutimes = futimesSupported();
+                    }
                 }
             } catch (UnixException x) {
-                if (x.errno() != UnixConstants.ENXIO) {
+                if (!(x.errno() == UnixConstants.ENXIO ||
+                     (x.errno() == UnixConstants.ELOOP && useLutimes))) {
                     x.rethrowAsIOException(file);
                 }
             }
@@ -112,6 +120,8 @@
                 try {
                     if (useFutimes) {
                         futimes(fd, accessValue, modValue);
+                    } else if (useLutimes) {
+                        lutimes(file, accessValue, modValue);
                     } else {
                         utimes(file, accessValue, modValue);
                     }
@@ -131,6 +141,8 @@
                     try {
                         if (useFutimes) {
                             futimes(fd, accessValue, modValue);
+                        } else if (useLutimes) {
+                            lutimes(file, accessValue, modValue);
                         } else {
                             utimes(file, accessValue, modValue);
                         }
--- a/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixNativeDispatcher.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -401,7 +401,7 @@
     static native void fchmod(int fd, int mode) throws UnixException;
 
     /**
-     * utimes(conar char* path, const struct timeval times[2])
+     * utimes(const char* path, const struct timeval times[2])
      */
     static void utimes(UnixPath path, long times0, long times1)
         throws UnixException
@@ -417,11 +417,27 @@
         throws UnixException;
 
     /**
-     * futimes(int fildes,, const struct timeval times[2])
+     * futimes(int fildes, const struct timeval times[2])
      */
     static native void futimes(int fd, long times0, long times1) throws UnixException;
 
     /**
+     * lutimes(const char* path, const struct timeval times[2])
+     */
+    static void lutimes(UnixPath path, long times0, long times1)
+        throws UnixException
+    {
+        NativeBuffer buffer = copyToNativeBuffer(path);
+        try {
+            lutimes0(buffer.address(), times0, times1);
+        } finally {
+            buffer.release();
+        }
+    }
+    private static native void lutimes0(long pathAddress, long times0, long times1)
+        throws UnixException;
+
+    /**
      * DIR *opendir(const char* dirname)
      */
     static long opendir(UnixPath path) throws UnixException {
@@ -578,9 +594,10 @@
     /**
      * Capabilities
      */
-    private static final int SUPPORTS_OPENAT        = 1 << 1;    // syscalls
+    private static final int SUPPORTS_OPENAT        = 1 << 1;  // syscalls
     private static final int SUPPORTS_FUTIMES       = 1 << 2;
-    private static final int SUPPORTS_BIRTHTIME     = 1 << 16;   // other features
+    private static final int SUPPORTS_LUTIMES       = 1 << 4;
+    private static final int SUPPORTS_BIRTHTIME     = 1 << 16; // other features
     private static final int capabilities;
 
     /**
@@ -598,6 +615,13 @@
     }
 
     /**
+     * Supports lutimes
+     */
+    static boolean lutimesSupported() {
+        return (capabilities & SUPPORTS_LUTIMES) != 0;
+    }
+
+    /**
      * Supports file birth (creation) time attribute
      */
     static boolean birthtimeSupported() {
--- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -143,6 +143,7 @@
 typedef int unlinkat_func(int, const char*, int);
 typedef int renameat_func(int, const char*, int, const char*);
 typedef int futimesat_func(int, const char *, const struct timeval *);
+typedef int lutimes_func(const char *, const struct timeval *);
 typedef DIR* fdopendir_func(int);
 
 static openat64_func* my_openat64_func = NULL;
@@ -150,6 +151,7 @@
 static unlinkat_func* my_unlinkat_func = NULL;
 static renameat_func* my_renameat_func = NULL;
 static futimesat_func* my_futimesat_func = NULL;
+static lutimes_func* my_lutimes_func = NULL;
 static fdopendir_func* my_fdopendir_func = NULL;
 
 /**
@@ -269,7 +271,10 @@
 #endif
     my_unlinkat_func = (unlinkat_func*) dlsym(RTLD_DEFAULT, "unlinkat");
     my_renameat_func = (renameat_func*) dlsym(RTLD_DEFAULT, "renameat");
+#ifndef _ALLBSD_SOURCE
     my_futimesat_func = (futimesat_func*) dlsym(RTLD_DEFAULT, "futimesat");
+    my_lutimes_func = (lutimes_func*) dlsym(RTLD_DEFAULT, "lutimes");
+#endif
 #if defined(_AIX)
     my_fdopendir_func = (fdopendir_func*) dlsym(RTLD_DEFAULT, "fdopendir64");
 #else
@@ -282,13 +287,16 @@
         my_fstatat64_func = (fstatat64_func*)&fstatat64_wrapper;
 #endif
 
-    /* supports futimes or futimesat */
+    /* supports futimes or futimesat and/or lutimes */
 
 #ifdef _ALLBSD_SOURCE
     capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
+    capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
 #else
     if (my_futimesat_func != NULL)
         capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_FUTIMES;
+    if (my_lutimes_func != NULL)
+        capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_LUTIMES;
 #endif
 
     /* supports openat, etc. */
@@ -675,7 +683,7 @@
     RESTARTABLE(futimes(filedes, &times[0]), err);
 #else
     if (my_futimesat_func == NULL) {
-        JNU_ThrowInternalError(env, "my_ftimesat_func is NULL");
+        JNU_ThrowInternalError(env, "my_futimesat_func is NULL");
         return;
     }
     RESTARTABLE((*my_futimesat_func)(filedes, NULL, &times[0]), err);
@@ -685,6 +693,34 @@
     }
 }
 
+JNIEXPORT void JNICALL
+Java_sun_nio_fs_UnixNativeDispatcher_lutimes0(JNIEnv* env, jclass this,
+    jlong pathAddress, jlong accessTime, jlong modificationTime)
+{
+    int err;
+    struct timeval times[2];
+    const char* path = (const char*)jlong_to_ptr(pathAddress);
+
+    times[0].tv_sec = accessTime / 1000000;
+    times[0].tv_usec = accessTime % 1000000;
+
+    times[1].tv_sec = modificationTime / 1000000;
+    times[1].tv_usec = modificationTime % 1000000;
+
+#ifdef _ALLBSD_SOURCE
+    RESTARTABLE(lutimes(path, &times[0]), err);
+#else
+    if (my_lutimes_func == NULL) {
+        JNU_ThrowInternalError(env, "my_lutimes_func is NULL");
+        return;
+    }
+    RESTARTABLE((*my_lutimes_func)(path, &times[0]), err);
+#endif
+    if (err == -1) {
+        throwUnixException(env, errno);
+    }
+}
+
 JNIEXPORT jlong JNICALL
 Java_sun_nio_fs_UnixNativeDispatcher_opendir0(JNIEnv* env, jclass this,
     jlong pathAddress)
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java	Tue May 07 11:52:28 2019 -0700
@@ -40,6 +40,7 @@
 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 import org.w3c.dom.Text;
 
 public abstract class IntegrityHmac extends SignatureAlgorithmSpi {
@@ -325,12 +326,13 @@
             throw new IllegalArgumentException("element null");
         }
 
-        Text hmaclength =
-            XMLUtils.selectDsNodeText(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0);
-
-        if (hmaclength != null) {
-            this.HMACOutputLength = Integer.parseInt(hmaclength.getData());
-            this.HMACOutputLengthSet = true;
+        Node n = XMLUtils.selectDsNode(element.getFirstChild(), Constants._TAG_HMACOUTPUTLENGTH, 0);
+        if (n != null) {
+            String hmacLength = XMLUtils.getFullTextChildrenFromNode(n);
+            if (hmacLength != null && !"".equals(hmacLength)) {
+                this.HMACOutputLength = Integer.parseInt(hmacLength);
+                this.HMACOutputLengthSet = true;
+            }
         }
     }
 
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureDSA.java	Tue May 07 11:52:28 2019 -0700
@@ -33,7 +33,6 @@
 import java.security.SignatureException;
 import java.security.interfaces.DSAKey;
 import java.security.spec.AlgorithmParameterSpec;
-import java.util.Base64;
 
 import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi;
@@ -41,6 +40,7 @@
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
 import com.sun.org.apache.xml.internal.security.utils.Constants;
 import com.sun.org.apache.xml.internal.security.utils.JavaUtils;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 
 public class SignatureDSA extends SignatureAlgorithmSpi {
 
@@ -109,7 +109,7 @@
         throws XMLSignatureException {
         try {
             if (LOG.isDebugEnabled()) {
-                LOG.debug("Called DSA.verify() on " + Base64.getMimeEncoder().encodeToString(signature));
+                LOG.debug("Called DSA.verify() on " + XMLUtils.encodeToString(signature));
             }
 
             byte[] jcebytes = JavaUtils.convertDsaXMLDSIGtoASN1(signature,
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureECDSA.java	Tue May 07 11:52:28 2019 -0700
@@ -33,12 +33,12 @@
 import java.security.Signature;
 import java.security.SignatureException;
 import java.security.spec.AlgorithmParameterSpec;
-import java.util.Base64;
 
 import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper;
 import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi;
 import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 
 /**
  *
@@ -132,7 +132,7 @@
             byte[] jcebytes = SignatureECDSA.convertXMLDSIGtoASN1(signature);
 
             if (LOG.isDebugEnabled()) {
-                LOG.debug("Called ECDSA.verify() on " + Base64.getMimeEncoder().encodeToString(signature));
+                LOG.debug("Called ECDSA.verify() on " + XMLUtils.encodeToString(signature));
             }
 
             return this.signatureAlgorithm.verify(jcebytes);
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315.java	Tue May 07 11:52:28 2019 -0700
@@ -331,7 +331,7 @@
                     ns.addMapping(NName, NValue, attribute);
                 }
             } else if (XML_LANG_URI.equals(attribute.getNamespaceURI())
-                && (!c14n11 || c14n11 && !"id".equals(NName))) {
+                && (!c14n11 || !"id".equals(NName))) {
                 xmlattrStack.addXmlnsAttr(attribute);
             }
         }
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer20010315Excl.java	Tue May 07 11:52:28 2019 -0700
@@ -342,7 +342,7 @@
     protected void circumventBugIfNeeded(XMLSignatureInput input)
         throws CanonicalizationException, ParserConfigurationException,
                IOException, SAXException {
-        if (!input.isNeedsToBeExpanded() || inclusiveNSSet.isEmpty() || inclusiveNSSet.isEmpty()) {
+        if (!input.isNeedsToBeExpanded() || inclusiveNSSet.isEmpty()) {
             return;
         }
         Document doc = null;
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/KeyInfo.java	Tue May 07 11:52:28 2019 -0700
@@ -50,7 +50,6 @@
 import com.sun.org.apache.xml.internal.security.transforms.Transforms;
 import com.sun.org.apache.xml.internal.security.utils.Constants;
 import com.sun.org.apache.xml.internal.security.utils.ElementProxy;
-import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants;
 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 import org.w3c.dom.Attr;
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/KeyValue.java	Tue May 07 11:52:28 2019 -0700
@@ -26,6 +26,7 @@
 
 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
 import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.DSAKeyValue;
+import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.ECKeyValue;
 import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.RSAKeyValue;
 import com.sun.org.apache.xml.internal.security.utils.Constants;
 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
@@ -107,9 +108,14 @@
 
             appendSelf(rsa);
             addReturnToSelf();
+        } else if (pk instanceof java.security.interfaces.ECPublicKey) {
+            ECKeyValue ec = new ECKeyValue(getDocument(), pk);
+
+            appendSelf(ec);
+            addReturnToSelf();
         } else {
             String error = "The given PublicKey type " + pk + " is not supported. Only DSAPublicKey and "
-                + "RSAPublicKey types are currently supported";
+                + "RSAPublicKey and ECPublicKey types are currently supported";
             throw new IllegalArgumentException(error);
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/keyvalues/ECKeyValue.java	Tue May 07 11:52:28 2019 -0700
@@ -0,0 +1,366 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.sun.org.apache.xml.internal.security.keys.content.keyvalues;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.Key;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECField;
+import java.security.spec.ECFieldFp;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+import java.security.spec.ECPublicKeySpec;
+import java.security.spec.EllipticCurve;
+import java.security.spec.InvalidKeySpecException;
+import java.util.Arrays;
+
+import javax.xml.crypto.MarshalException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
+import com.sun.org.apache.xml.internal.security.utils.Constants;
+import com.sun.org.apache.xml.internal.security.utils.I18n;
+import com.sun.org.apache.xml.internal.security.utils.Signature11ElementProxy;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
+
+public class ECKeyValue extends Signature11ElementProxy implements KeyValueContent {
+
+    /* Supported curve, secp256r1 */
+    private static final Curve SECP256R1 = initializeCurve(
+        "secp256r1 [NIST P-256, X9.62 prime256v1]",
+        "1.2.840.10045.3.1.7",
+        "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
+        "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
+        "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
+        "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
+        "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
+        "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
+        1
+    );
+
+    /* Supported curve secp384r1 */
+    private static final Curve SECP384R1 = initializeCurve(
+        "secp384r1 [NIST P-384]",
+        "1.3.132.0.34",
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
+        "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
+        "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
+        "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
+        "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
+        1
+    );
+
+    /* Supported curve secp521r1 */
+    private static final Curve SECP521R1 = initializeCurve(
+        "secp521r1 [NIST P-521]",
+        "1.3.132.0.35",
+        "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+        "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
+        "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
+        "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
+        "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
+        "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
+        1
+    );
+
+    private static Curve initializeCurve(String name, String oid,
+            String sfield, String a, String b,
+            String x, String y, String n, int h) {
+        BigInteger p = bigInt(sfield);
+        ECField field = new ECFieldFp(p);
+        EllipticCurve curve = new EllipticCurve(field, bigInt(a),
+                                                bigInt(b));
+        ECPoint g = new ECPoint(bigInt(x), bigInt(y));
+        return new Curve(name, oid, curve, g, bigInt(n), h);
+    }
+
+
+    /**
+     * Constructor DSAKeyValue
+     *
+     * @param element
+     * @param baseURI
+     * @throws XMLSecurityException
+     */
+    public ECKeyValue(Element element, String baseURI) throws XMLSecurityException {
+        super(element, baseURI);
+    }
+
+    /**
+     * Constructor DSAKeyValue
+     *
+     * @param doc
+     * @param key
+     * @throws IllegalArgumentException
+     */
+    public ECKeyValue(Document doc, Key key) throws IllegalArgumentException {
+        super(doc);
+
+        addReturnToSelf();
+
+        if (key instanceof ECPublicKey) {
+            ECParameterSpec ecParams = ((ECPublicKey)key).getParams();
+
+            // NamedCurve
+            String oid = getCurveOid(ecParams);
+            if (oid == null) {
+                throw new IllegalArgumentException("Invalid ECParameterSpec");
+            }
+
+            Element namedCurveElement = XMLUtils.createElementInSignature11Space(getDocument(), "NamedCurve");
+            namedCurveElement.setAttributeNS(null, "URI", "urn:oid:" + oid);
+            appendSelf(namedCurveElement);
+            addReturnToSelf();
+
+            // PublicKey
+            ECPoint ecPoint = ((ECPublicKey)key).getW();
+            byte[] secPublicKey = encodePoint(ecPoint, ecParams.getCurve());
+            String encoded = XMLUtils.encodeToString(secPublicKey);
+            Element publicKeyElement = XMLUtils.createElementInSignature11Space(getDocument(), "PublicKey");
+            Text text = getDocument().createTextNode(encoded);
+
+            publicKeyElement.appendChild(text);
+
+            appendSelf(publicKeyElement);
+            addReturnToSelf();
+
+        } else {
+            Object[] exArgs = { Constants._TAG_ECKEYVALUE, key.getClass().getName() };
+
+            throw new IllegalArgumentException(I18n.translate("KeyValue.IllegalArgument", exArgs));
+        }
+    }
+
+    /** {@inheritDoc} */
+    public PublicKey getPublicKey() throws XMLSecurityException {
+        try {
+            ECParameterSpec ecParams = null;
+            Element curElem = getFirstChildElement(getElement());
+            if (curElem == null) {
+                throw new MarshalException("KeyValue must contain at least one type");
+            }
+
+            if ("ECParameters".equals(curElem.getLocalName())
+                && Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) {
+                throw new UnsupportedOperationException
+                    ("ECParameters not supported");
+            } else if ("NamedCurve".equals(curElem.getLocalName())
+                && Constants.SignatureSpec11NS.equals(curElem.getNamespaceURI())) {
+                String uri = null;
+                if (curElem.hasAttributeNS(null, "URI")) {
+                    uri = curElem.getAttributeNS(null, "URI");
+                }
+                // strip off "urn:oid"
+                if (uri.startsWith("urn:oid:")) {
+                    String oid = uri.substring("urn:oid:".length());
+                    ecParams = getECParameterSpec(oid);
+                    if (ecParams == null) {
+                        throw new MarshalException("Invalid curve OID");
+                    }
+                } else {
+                    throw new MarshalException("Invalid NamedCurve URI");
+                }
+            } else {
+                throw new MarshalException("Invalid ECKeyValue");
+            }
+            curElem = getNextSiblingElement(curElem, "PublicKey", Constants.SignatureSpec11NS);
+            ECPoint ecPoint = null;
+
+            try {
+                String content = XMLUtils.getFullTextChildrenFromNode(curElem);
+                ecPoint = decodePoint(XMLUtils.decode(content), ecParams.getCurve());
+            } catch (IOException ioe) {
+                throw new MarshalException("Invalid EC Point", ioe);
+            }
+
+            ECPublicKeySpec spec = new ECPublicKeySpec(ecPoint, ecParams);
+            return KeyFactory.getInstance("EC").generatePublic(spec);
+        } catch (NoSuchAlgorithmException ex) {
+            throw new XMLSecurityException(ex);
+        } catch (InvalidKeySpecException ex) {
+            throw new XMLSecurityException(ex);
+        } catch (MarshalException ex) {
+            throw new XMLSecurityException(ex);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public String getBaseLocalName() {
+        return Constants._TAG_ECKEYVALUE;
+    }
+
+    private static Element getFirstChildElement(Node node) {
+        Node child = node.getFirstChild();
+        while (child != null && child.getNodeType() != Node.ELEMENT_NODE) {
+            child = child.getNextSibling();
+        }
+        return (Element)child;
+    }
+
+    private static Element getNextSiblingElement(Node node, String localName, String namespaceURI)
+        throws MarshalException
+    {
+        return verifyElement(getNextSiblingElement(node), localName, namespaceURI);
+    }
+
+    private static Element getNextSiblingElement(Node node) {
+        Node sibling = node.getNextSibling();
+        while (sibling != null && sibling.getNodeType() != Node.ELEMENT_NODE) {
+            sibling = sibling.getNextSibling();
+        }
+        return (Element)sibling;
+    }
+
+    private static Element verifyElement(Element elem, String localName, String namespaceURI)
+        throws MarshalException
+    {
+        if (elem == null) {
+            throw new MarshalException("Missing " + localName + " element");
+        }
+        String name = elem.getLocalName();
+        String namespace = elem.getNamespaceURI();
+        if (!name.equals(localName) || namespace == null && namespaceURI != null
+            || namespace != null && !namespace.equals(namespaceURI)) {
+            throw new MarshalException("Invalid element name: " +
+                namespace + ":" + name + ", expected " + namespaceURI + ":" + localName);
+        }
+        return elem;
+    }
+
+    private static String getCurveOid(ECParameterSpec params) {
+        // Check that the params represent one of the supported
+        // curves. If there is a match, return the object identifier
+        // of the curve.
+        Curve match;
+        if (matchCurve(params, SECP256R1)) {
+            match = SECP256R1;
+        } else if (matchCurve(params, SECP384R1)) {
+            match = SECP384R1;
+        } else if (matchCurve(params, SECP521R1)) {
+            match = SECP521R1;
+        } else {
+            return null;
+        }
+        return match.getObjectId();
+    }
+
+    private static boolean matchCurve(ECParameterSpec params, Curve curve) {
+        int fieldSize = params.getCurve().getField().getFieldSize();
+        return curve.getCurve().getField().getFieldSize() == fieldSize
+            && curve.getCurve().equals(params.getCurve())
+            && curve.getGenerator().equals(params.getGenerator())
+            && curve.getOrder().equals(params.getOrder())
+            && curve.getCofactor() == params.getCofactor();
+    }
+
+    private static ECPoint decodePoint(byte[] data, EllipticCurve curve)
+        throws IOException {
+        if (data.length == 0 || data[0] != 4) {
+            throw new IOException("Only uncompressed point format " +
+                "supported");
+        }
+        // Per ANSI X9.62, an encoded point is a 1 byte type followed by
+        // ceiling(LOG base 2 field-size / 8) bytes of x and the same of y.
+        int n = (data.length - 1) / 2;
+        if (n != (curve.getField().getFieldSize() + 7) >> 3) {
+            throw new IOException("Point does not match field size");
+        }
+
+        byte[] xb = Arrays.copyOfRange(data, 1, 1 + n);
+        byte[] yb = Arrays.copyOfRange(data, n + 1, n + 1 + n);
+
+        return new ECPoint(new BigInteger(1, xb), new BigInteger(1, yb));
+    }
+
+    private static byte[] encodePoint(ECPoint point, EllipticCurve curve) {
+        // get field size in bytes (rounding up)
+        int n = (curve.getField().getFieldSize() + 7) >> 3;
+        byte[] xb = trimZeroes(point.getAffineX().toByteArray());
+        byte[] yb = trimZeroes(point.getAffineY().toByteArray());
+        if (xb.length > n || yb.length > n) {
+            throw new RuntimeException("Point coordinates do not " +
+                                       "match field size");
+        }
+        byte[] b = new byte[1 + (n << 1)];
+        b[0] = 4; // uncompressed
+        System.arraycopy(xb, 0, b, n - xb.length + 1, xb.length);
+        System.arraycopy(yb, 0, b, b.length - yb.length, yb.length);
+        return b;
+    }
+
+    private static byte[] trimZeroes(byte[] b) {
+        int i = 0;
+        while (i < b.length - 1 && b[i] == 0) {
+            i++;
+        }
+        if (i == 0) {
+            return b;
+        }
+        return Arrays.copyOfRange(b, i, b.length);
+    }
+
+    private static ECParameterSpec getECParameterSpec(String oid) {
+        if (oid.equals(SECP256R1.getObjectId())) {
+            return SECP256R1;
+        } else if (oid.equals(SECP384R1.getObjectId())) {
+            return SECP384R1;
+        } else if (oid.equals(SECP521R1.getObjectId())) {
+            return SECP521R1;
+        } else {
+            return null;
+        }
+    }
+
+    static final class Curve extends ECParameterSpec {
+        private final String name;
+        private final String oid;
+
+        Curve(String name, String oid, EllipticCurve curve,
+              ECPoint g, BigInteger n, int h) {
+            super(curve, g, n, h);
+            this.name = name;
+            this.oid = oid;
+        }
+
+        private String getName() {
+            return name;
+        }
+
+        private String getObjectId() {
+            return oid;
+        }
+    }
+
+    private static BigInteger bigInt(String s) {
+        return new BigInteger(s, 16);
+    }
+}
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SKI.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/x509/XMLX509SKI.java	Tue May 07 11:52:28 2019 -0700
@@ -24,18 +24,18 @@
 
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
-import java.util.Base64;
 
 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
 import com.sun.org.apache.xml.internal.security.utils.Constants;
 import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 
 /**
  * Handles SubjectKeyIdentifier (SKI) for X.509v3.
  *
- * @see <A HREF="http://docs.oracle.com/javase/1.5.0/docs/api/java/security/cert/X509Extension.html">
+ * @see <A HREF="http://docs.oracle.com/javase/8/docs/api/java/security/cert/X509Extension.html">
  * Interface X509Extension</A>
  */
 public class XMLX509SKI extends SignatureElementProxy implements XMLX509DataContent {
@@ -138,7 +138,7 @@
         System.arraycopy(extensionValue, 4, skidValue, 0, skidValue.length);
 
         if (LOG.isDebugEnabled()) {
-            LOG.debug("Base64 of SKI is " + Base64.getMimeEncoder().encodeToString(skidValue));
+            LOG.debug("Base64 of SKI is " + XMLUtils.encodeToString(skidValue));
         }
 
         return skidValue;
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java	Tue May 07 11:52:28 2019 -0700
@@ -33,6 +33,7 @@
 
 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DEREncodedKeyValueResolver;
 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.DSAKeyValueResolver;
+import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.ECKeyValueResolver;
 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.KeyInfoReferenceResolver;
 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RSAKeyValueResolver;
 import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.RetrievalMethodResolver;
@@ -295,6 +296,7 @@
         keyResolverList.add(new KeyResolver(new DEREncodedKeyValueResolver()));
         keyResolverList.add(new KeyResolver(new KeyInfoReferenceResolver()));
         keyResolverList.add(new KeyResolver(new X509DigestResolver()));
+        keyResolverList.add(new KeyResolver(new ECKeyValueResolver()));
 
         resolverVector.addAll(keyResolverList);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/ECKeyValueResolver.java	Tue May 07 11:52:28 2019 -0700
@@ -0,0 +1,97 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations;
+
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
+import com.sun.org.apache.xml.internal.security.keys.content.keyvalues.ECKeyValue;
+import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolverSpi;
+import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver;
+import com.sun.org.apache.xml.internal.security.utils.Constants;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
+import org.w3c.dom.Element;
+
+public class ECKeyValueResolver extends KeyResolverSpi {
+
+    private static final com.sun.org.slf4j.internal.Logger LOG =
+        com.sun.org.slf4j.internal.LoggerFactory.getLogger(ECKeyValueResolver.class);
+
+
+    /**
+     * Method engineResolvePublicKey
+     *
+     * @param element
+     * @param baseURI
+     * @param storage
+     * @return null if no {@link PublicKey} could be obtained
+     */
+    public PublicKey engineLookupAndResolvePublicKey(
+        Element element, String baseURI, StorageResolver storage
+    ) {
+        if (element == null) {
+            return null;
+        }
+        Element ecKeyElement = null;
+        boolean isKeyValue =
+            XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYVALUE);
+        if (isKeyValue) {
+            ecKeyElement =
+                XMLUtils.selectDs11Node(element.getFirstChild(), Constants._TAG_ECKEYVALUE, 0);
+        } else if (XMLUtils.elementIsInSignature11Space(element, Constants._TAG_ECKEYVALUE)) {
+            // this trick is needed to allow the RetrievalMethodResolver to eat a
+            // ds:ECKeyValue directly (without KeyValue)
+            ecKeyElement = element;
+        }
+
+        if (ecKeyElement == null) {
+            return null;
+        }
+
+        try {
+            ECKeyValue ecKeyValue = new ECKeyValue(ecKeyElement, baseURI);
+            return ecKeyValue.getPublicKey();
+        } catch (XMLSecurityException ex) {
+            LOG.debug(ex.getMessage(), ex);
+            //do nothing
+        }
+
+        return null;
+    }
+
+
+    /** {@inheritDoc} */
+    public X509Certificate engineLookupResolveX509Certificate(
+        Element element, String baseURI, StorageResolver storage
+    ) {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public javax.crypto.SecretKey engineLookupAndResolveSecretKey(
+        Element element, String baseURI, StorageResolver storage
+    ) {
+        return null;
+    }
+}
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RSAKeyValueResolver.java	Tue May 07 11:52:28 2019 -0700
@@ -44,11 +44,12 @@
     public PublicKey engineLookupAndResolvePublicKey(
         Element element, String baseURI, StorageResolver storage
     ) {
-        LOG.debug("Can I resolve {}", element.getTagName());
         if (element == null) {
             return null;
         }
 
+        LOG.debug("Can I resolve {}", element.getTagName());
+
         boolean isKeyValue = XMLUtils.elementIsInSignatureSpace(element, Constants._TAG_KEYVALUE);
         Element rsaKeyElement = null;
         if (isKeyValue) {
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/CertsInFilesystemDirectoryResolver.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/storage/implementations/CertsInFilesystemDirectoryResolver.java	Tue May 07 11:52:28 2019 -0700
@@ -35,12 +35,12 @@
 import java.security.cert.CertificateNotYetValidException;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
-import java.util.Base64;
 import java.util.Iterator;
 import java.util.List;
 
 import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolverException;
 import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolverSpi;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 
 /**
  * This {@link StorageResolverSpi} makes all raw (binary) {@link X509Certificate}s
@@ -207,7 +207,7 @@
 
             System.out.println();
             System.out.println("Base64(SKI())=                 \""
-                               + Base64.getMimeEncoder().encodeToString(ski) + "\"");
+                               + XMLUtils.encodeToString(ski) + "\"");
             System.out.println("cert.getSerialNumber()=        \""
                                + cert.getSerialNumber().toString() + "\"");
             System.out.println("cert.getSubjectX500Principal().getName()= \""
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml	Tue May 07 11:52:28 2019 -0700
@@ -643,6 +643,8 @@
                 DESCRIPTION="Uses an X509 SubjectName to retrieve a certificate from the storages" />
       <Resolver JAVACLASS="com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509IssuerSerialResolver"
                 DESCRIPTION="Uses an X509 IssuerName and IssuerSerial to retrieve a certificate from the storages" />
+      <Resolver JAVACLASS="com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.ECKeyValueResolver"
+                DESCRIPTION="Can extract EC public keys" />
    </KeyResolver>
  
    <PrefixMappings>
@@ -665,5 +667,7 @@
                      prefix="ec" />
       <PrefixMapping namespace="http://www.nue.et-inf.uni-siegen.de/~geuer-pollmann/#xpathFilter"
                      prefix="xx" />
+       <PrefixMapping namespace="http://www.w3.org/2009/xmldsig11#"
+                     prefix="dsig11" />
    </PrefixMappings>
 </Configuration>
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java	Tue May 07 11:52:28 2019 -0700
@@ -23,7 +23,10 @@
 package com.sun.org.apache.xml.internal.security.signature;
 
 import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -56,19 +59,24 @@
 public class Manifest extends SignatureElementProxy {
 
     /**
-     * The maximum number of references per Manifest, if secure validation is enabled.
+     * The default maximum number of references per Manifest, if secure validation is enabled.
      */
     public static final int MAXIMUM_REFERENCE_COUNT = 30;
 
     private static final com.sun.org.slf4j.internal.Logger LOG =
         com.sun.org.slf4j.internal.LoggerFactory.getLogger(Manifest.class);
 
+    private static Integer referenceCount =
+        AccessController.doPrivileged(
+            (PrivilegedAction<Integer>) () -> Integer.parseInt(System.getProperty("com.sun.org.apache.xml.internal.security.maxReferences",
+                                                                Integer.toString(MAXIMUM_REFERENCE_COUNT))));
+
     /** Field references */
     private List<Reference> references;
     private Element[] referencesEl;
 
     /** Field verificationResults[] */
-    private boolean[] verificationResults;
+    private List<VerifiedReference> verificationResults;
 
     /** Field resolverProperties */
     private Map<String, String> resolverProperties;
@@ -135,8 +143,8 @@
                                    I18n.translate("xml.WrongContent", exArgs));
         }
 
-        if (secureValidation && le > MAXIMUM_REFERENCE_COUNT) {
-            Object exArgs[] = { le, MAXIMUM_REFERENCE_COUNT };
+        if (secureValidation && le > referenceCount) {
+            Object exArgs[] = { le, referenceCount };
 
             throw new XMLSecurityException("signature.tooManyReferences", exArgs);
         }
@@ -317,13 +325,13 @@
         if (referencesEl.length == 0) {
             throw new XMLSecurityException("empty", new Object[]{"References are empty"});
         }
-        if (secureValidation && referencesEl.length > MAXIMUM_REFERENCE_COUNT) {
-            Object exArgs[] = { referencesEl.length, MAXIMUM_REFERENCE_COUNT };
+        if (secureValidation && referencesEl.length > referenceCount) {
+            Object exArgs[] = { referencesEl.length, referenceCount };
 
             throw new XMLSecurityException("signature.tooManyReferences", exArgs);
         }
 
-        this.verificationResults = new boolean[referencesEl.length];
+        this.verificationResults = new ArrayList<>(referencesEl.length);
         boolean verify = true;
         for (int i = 0; i < this.referencesEl.length; i++) {
             Reference currentRef =
@@ -335,13 +343,13 @@
             try {
                 boolean currentRefVerified = currentRef.verify();
 
-                this.setVerificationResult(i, currentRefVerified);
-
                 if (!currentRefVerified) {
                     verify = false;
                 }
                 LOG.debug("The Reference has Type {}", currentRef.getType());
 
+                List<VerifiedReference> manifestReferences = Collections.emptyList();
+
                 // was verification successful till now and do we want to verify the Manifest?
                 if (verify && followManifests && currentRef.typeIsReferenceToManifest()) {
                     LOG.debug("We have to follow a nested Manifest");
@@ -393,6 +401,8 @@
                         } else {
                             LOG.debug("The nested Manifest was valid (good)");
                         }
+
+                        manifestReferences = referencedManifest.getVerificationResults();
                     } catch (IOException ex) {
                         throw new ReferenceNotInitializedException(ex);
                     } catch (ParserConfigurationException ex) {
@@ -401,6 +411,8 @@
                         throw new ReferenceNotInitializedException(ex);
                     }
                 }
+
+                verificationResults.add(new VerifiedReference(currentRefVerified, currentRef.getURI(), manifestReferences));
             } catch (ReferenceNotInitializedException ex) {
                 Object exArgs[] = { currentRef.getURI() };
 
@@ -414,20 +426,6 @@
     }
 
     /**
-     * Method setVerificationResult
-     *
-     * @param index
-     * @param verify
-     */
-    private void setVerificationResult(int index, boolean verify) {
-        if (this.verificationResults == null) {
-            this.verificationResults = new boolean[this.getLength()];
-        }
-
-        this.verificationResults[index] = verify;
-    }
-
-    /**
      * After verifying a {@link Manifest} or a {@link SignedInfo} using the
      * {@link Manifest#verifyReferences()} or {@link SignedInfo#verify()} methods,
      * the individual results can be retrieved with this method.
@@ -455,14 +453,24 @@
             }
         }
 
-        return this.verificationResults[index];
+        return ((ArrayList<VerifiedReference>)verificationResults).get(index).isValid();
+    }
+
+    /**
+     * Get the list of verification result objects
+     */
+    public List<VerifiedReference> getVerificationResults() {
+        if (verificationResults == null) {
+            return Collections.emptyList();
+        }
+        return Collections.unmodifiableList(verificationResults);
     }
 
     /**
      * Adds Resource Resolver for retrieving resources at specified {@code URI} attribute
      * in {@code reference} element
      *
-     * @param resolver {@link ResourceResolver} can provide the implemenatin subclass of
+     * @param resolver {@link ResourceResolver} can provide the implementation subclass of
      * {@link ResourceResolverSpi} for retrieving resource.
      */
     public void addResourceResolver(ResourceResolver resolver) {
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Reference.java	Tue May 07 11:52:28 2019 -0700
@@ -26,7 +26,6 @@
 import java.io.OutputStream;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.Base64;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
@@ -396,7 +395,7 @@
             n = n.getNextSibling();
         }
 
-        String base64codedValue = Base64.getMimeEncoder().encodeToString(digestValue);
+        String base64codedValue = XMLUtils.encodeToString(digestValue);
         Text t = createText(base64codedValue);
 
         digestValueElement.appendChild(t);
@@ -723,12 +722,17 @@
             return getPreCalculatedDigest(input);
         }
 
+        cacheDereferencedElement(input);
+
         MessageDigestAlgorithm mda = this.getMessageDigestAlgorithm();
         mda.reset();
 
         try (DigesterOutputStream diOs = new DigesterOutputStream(mda);
             OutputStream os = new UnsyncBufferedOutputStream(diOs)) {
-            XMLSignatureInput output = this.dereferenceURIandPerformTransforms(os);
+
+            XMLSignatureInput output = this.getContentsAfterTransformation(input, os);
+            this.transformsOutput = output;
+
             // if signing and c14n11 property == true explicitly add
             // C14N11 transform if needed
             if (Reference.useC14N11 && !validating && !output.isOutputStreamSet()
@@ -772,7 +776,7 @@
             throws ReferenceNotInitializedException {
         LOG.debug("Verifying element with pre-calculated digest");
         String preCalculatedDigest = input.getPreCalculatedDigest();
-        return Base64.getMimeDecoder().decode(preCalculatedDigest);
+        return XMLUtils.decode(preCalculatedDigest);
     }
 
     /**
@@ -789,8 +793,8 @@
                 "signature.Verification.NoSignatureElement", exArgs
             );
         }
-        String content = XMLUtils.getFullTextChildrenFromElement(digestValueElement);
-        return Base64.getMimeDecoder().decode(content);
+        String content = XMLUtils.getFullTextChildrenFromNode(digestValueElement);
+        return XMLUtils.decode(content);
     }
 
 
@@ -809,8 +813,8 @@
 
         if (!equal) {
             LOG.warn("Verification failed for URI \"" + this.getURI() + "\"");
-            LOG.warn("Expected Digest: " + Base64.getMimeEncoder().encodeToString(elemDig));
-            LOG.warn("Actual Digest: " + Base64.getMimeEncoder().encodeToString(calcDig));
+            LOG.warn("Expected Digest: " + XMLUtils.encodeToString(elemDig));
+            LOG.warn("Actual Digest: " + XMLUtils.encodeToString(calcDig));
         } else {
             LOG.debug("Verification successful for URI \"{}\"", this.getURI());
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/VerifiedReference.java	Tue May 07 11:52:28 2019 -0700
@@ -0,0 +1,64 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.sun.org.apache.xml.internal.security.signature;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Holds the result of a Reference validation.
+ */
+public class VerifiedReference {
+
+    private final boolean valid;
+    private final String uri;
+    private final List<VerifiedReference> manifestReferences;
+
+    /**
+     * @param valid Whether this Reference was successfully validated or not
+     * @param uri The URI of this Reference
+     * @param manifestReferences If this reference is a reference to a Manifest, this holds the list
+     * of verified referenes associated with this Manifest
+     */
+    public VerifiedReference(boolean valid, String uri, List<VerifiedReference> manifestReferences) {
+        this.valid = valid;
+        this.uri = uri;
+        if (manifestReferences != null) {
+            this.manifestReferences = manifestReferences;
+        } else {
+            this.manifestReferences = Collections.emptyList();
+        }
+    }
+
+    public boolean isValid() {
+        return valid;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public List<VerifiedReference> getManifestReferences() {
+        return Collections.unmodifiableList(manifestReferences);
+    }
+}
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java	Tue May 07 11:52:28 2019 -0700
@@ -27,7 +27,6 @@
 import java.security.Key;
 import java.security.PublicKey;
 import java.security.cert.X509Certificate;
-import java.util.Base64;
 
 import javax.crypto.SecretKey;
 
@@ -504,8 +503,8 @@
      * @throws XMLSignatureException If there is no content
      */
     public byte[] getSignatureValue() throws XMLSignatureException {
-        String content = XMLUtils.getFullTextChildrenFromElement(signatureValueElement);
-        return Base64.getMimeDecoder().decode(content);
+        String content = XMLUtils.getFullTextChildrenFromNode(signatureValueElement);
+        return XMLUtils.decode(content);
     }
 
     /**
@@ -520,7 +519,7 @@
             signatureValueElement.removeChild(signatureValueElement.getFirstChild());
         }
 
-        String base64codedValue = Base64.getMimeEncoder().encodeToString(bytes);
+        String base64codedValue = XMLUtils.encodeToString(bytes);
 
         if (base64codedValue.length() > 76 && !XMLUtils.ignoreLineBreaks()) {
             base64codedValue = "\n" + base64codedValue + "\n";
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformBase64Decode.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformBase64Decode.java	Tue May 07 11:52:28 2019 -0700
@@ -24,7 +24,6 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.Base64;
 
 import javax.xml.parsers.ParserConfigurationException;
 
@@ -109,12 +108,12 @@
             StringBuilder sb = new StringBuilder();
             traverseElement((Element)el, sb);
             if (os == null) {
-                byte[] decodedBytes = Base64.getMimeDecoder().decode(sb.toString());
+                byte[] decodedBytes = XMLUtils.decode(sb.toString());
                 XMLSignatureInput output = new XMLSignatureInput(decodedBytes);
                 output.setSecureValidation(secureValidation);
                 return output;
             }
-            byte[] bytes = Base64.getMimeDecoder().decode(sb.toString());
+            byte[] bytes = XMLUtils.decode(sb.toString());
             os.write(bytes);
             XMLSignatureInput output = new XMLSignatureInput((byte[])null);
             output.setSecureValidation(secureValidation);
@@ -125,17 +124,17 @@
         if (input.isOctetStream() || input.isNodeSet()) {
             if (os == null) {
                 byte[] base64Bytes = input.getBytes();
-                byte[] decodedBytes = Base64.getMimeDecoder().decode(base64Bytes);
+                byte[] decodedBytes = XMLUtils.decode(base64Bytes);
                 XMLSignatureInput output = new XMLSignatureInput(decodedBytes);
                 output.setSecureValidation(secureValidation);
                 return output;
             }
             if (input.isByteArray() || input.isNodeSet()) {
-                byte[] bytes = Base64.getMimeDecoder().decode(input.getBytes());
+                byte[] bytes = XMLUtils.decode(input.getBytes());
                 os.write(bytes);
             } else {
                 byte[] inputBytes = JavaUtils.getBytesFromStream(input.getOctetStreamReal());
-                byte[] bytes = Base64.getMimeDecoder().decode(inputBytes);
+                byte[] bytes = XMLUtils.decode(inputBytes);
                 os.write(bytes);
             }
             XMLSignatureInput output = new XMLSignatureInput((byte[])null);
@@ -153,7 +152,7 @@
             Element rootNode = doc.getDocumentElement();
             StringBuilder sb = new StringBuilder();
             traverseElement(rootNode, sb);
-            byte[] decodedBytes = Base64.getMimeDecoder().decode(sb.toString());
+            byte[] decodedBytes = XMLUtils.decode(sb.toString());
             XMLSignatureInput output = new XMLSignatureInput(decodedBytes);
             output.setSecureValidation(secureValidation);
             return output;
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXSLT.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXSLT.java	Tue May 07 11:52:28 2019 -0700
@@ -84,7 +84,10 @@
 
             Element xsltElement =
                 XMLUtils.selectNode(transformElement.getFirstChild(), XSLTSpecNS, "stylesheet", 0);
-
+            if (xsltElement == null) {
+                xsltElement =
+                    XMLUtils.selectNode(transformElement.getFirstChild(), XSLTSpecNS, "transform", 0);
+            }
             if (xsltElement == null) {
                 Object exArgs[] = { "xslt:stylesheet", "Transform" };
 
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPathFilterCHGPContainer.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/params/XPathFilterCHGPContainer.java	Tue May 07 11:52:28 2019 -0700
@@ -30,6 +30,7 @@
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
+import org.w3c.dom.Text;
 
 /**
  * Implements the parameters for a custom Transform which has a better performance
@@ -204,7 +205,7 @@
                 getElement().getFirstChild(), this.getBaseNamespace(), type, 0
             );
 
-        return XMLUtils.getFullTextChildrenFromElement(xElem);
+        return XMLUtils.getFullTextChildrenFromNode(xElem);
     }
 
     /**
@@ -258,11 +259,23 @@
             return null;
         }
 
-        return XMLUtils.selectNodeText(
+        return selectNodeText(
             getFirstChild(), this.getBaseNamespace(), type, 0
         );
     }
 
+    private static Text selectNodeText(Node sibling, String uri, String nodeName, int number) {
+        Node n = XMLUtils.selectNode(sibling, uri, nodeName, number);
+        if (n == null) {
+            return null;
+        }
+        n = n.getFirstChild();
+        while (n != null && n.getNodeType() != Node.TEXT_NODE) {
+            n = n.getNextSibling();
+        }
+        return (Text)n;
+    }
+
     /**
      * Method getHereContextNodeIncludeButSearch
      *
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Constants.java	Tue May 07 11:52:28 2019 -0700
@@ -210,6 +210,9 @@
     /** Tag of Element J **/
     public static final String _TAG_J = "J";
 
+    /** Tag of Element ECKeyValue **/
+    public static final String _TAG_ECKEYVALUE = "ECKeyValue";
+
     /** Tag of Element Seed **/
     public static final String _TAG_SEED = "Seed";
 
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java	Tue May 07 11:52:28 2019 -0700
@@ -24,7 +24,6 @@
 
 import java.math.BigInteger;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.Base64;
 import java.util.Map;
 
 import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException;
@@ -267,7 +266,7 @@
             Element e = XMLUtils.createElementInSignatureSpace(getDocument(), localname);
 
             byte[] bytes = XMLUtils.getBytes(bi, bi.bitLength());
-            String encodedInt = Base64.getMimeEncoder().encodeToString(bytes);
+            String encodedInt = XMLUtils.encodeToString(bytes);
 
             Document doc = e.getOwnerDocument();
             Text text = doc.createTextNode(encodedInt);
@@ -292,7 +291,7 @@
     public void addBase64Element(byte[] bytes, String localname) {
         if (bytes != null) {
             Element el = XMLUtils.createElementInSignatureSpace(getDocument(), localname);
-            Text text = getDocument().createTextNode(Base64.getMimeEncoder().encodeToString(bytes));
+            Text text = getDocument().createTextNode(XMLUtils.encodeToString(bytes));
 
             el.appendChild(text);
 
@@ -326,8 +325,8 @@
     public void addBase64Text(byte[] bytes) {
         if (bytes != null) {
             Text t = XMLUtils.ignoreLineBreaks()
-                ? createText(Base64.getMimeEncoder().encodeToString(bytes))
-                : createText("\n" + Base64.getMimeEncoder().encodeToString(bytes) + "\n");
+                ? createText(XMLUtils.encodeToString(bytes))
+                : createText("\n" + XMLUtils.encodeToString(bytes) + "\n");
             appendSelf(t);
         }
     }
@@ -367,11 +366,11 @@
     public BigInteger getBigIntegerFromChildElement(
         String localname, String namespace
     ) {
-        return new BigInteger(1, Base64.getMimeDecoder().decode(
-            XMLUtils.selectNodeText(
-                getFirstChild(), namespace, localname, 0
-            ).getNodeValue()
-        ));
+        Node n = XMLUtils.selectNode(getFirstChild(), namespace, localname, 0);
+        if (n != null) {
+            return new BigInteger(1, XMLUtils.decode(XMLUtils.getFullTextChildrenFromNode(n)));
+        }
+        return null;
     }
 
     /**
@@ -396,7 +395,7 @@
      * @throws XMLSecurityException
      */
     public byte[] getBytesFromTextChild() throws XMLSecurityException {
-        return Base64.getMimeDecoder().decode(getTextFromTextChild());
+        return XMLUtils.decode(getTextFromTextChild());
     }
 
     /**
@@ -406,7 +405,7 @@
      *    element
      */
     public String getTextFromTextChild() {
-        return XMLUtils.getFullTextChildrenFromElement(getElement());
+        return XMLUtils.getFullTextChildrenFromNode(getElement());
     }
 
     /**
@@ -498,8 +497,9 @@
 
         if (Constants.SignatureSpecNS.equals(namespace)) {
             XMLUtils.setDsPrefix(prefix);
-        }
-        if (EncryptionConstants.EncryptionSpecNS.equals(namespace)) {
+        } else if (Constants.SignatureSpec11NS.equals(namespace)) {
+            XMLUtils.setDs11Prefix(prefix);
+        } else if (EncryptionConstants.EncryptionSpecNS.equals(namespace)) {
             XMLUtils.setXencPrefix(prefix);
         }
         prefixMappings.put(namespace, prefix);
@@ -519,6 +519,7 @@
         setNamespacePrefix(
             "http://www.nue.et-inf.uni-siegen.de/~geuer-pollmann/#xpathFilter", "xx"
         );
+        setNamespacePrefix("http://www.w3.org/2009/xmldsig11#", "dsig11");
     }
 
     /**
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Signature11ElementProxy.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/Signature11ElementProxy.java	Tue May 07 11:52:28 2019 -0700
@@ -47,6 +47,13 @@
 
         setDocument(doc);
         setElement(XMLUtils.createElementInSignature11Space(doc, this.getBaseLocalName()));
+
+        String prefix = ElementProxy.getDefaultPrefix(getBaseNamespace());
+        if (prefix == null || prefix.length() == 0) {
+            getElement().setAttributeNS(Constants.NamespaceSpecNS, "xmlns", getBaseNamespace());
+        } else {
+            getElement().setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + prefix, getBaseNamespace());
+        }
     }
 
     /**
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java	Tue May 07 11:52:28 2019 -0700
@@ -254,16 +254,21 @@
         }
     }
 
+    @Deprecated
+    public static String getFullTextChildrenFromElement(Element element) {
+        return getFullTextChildrenFromNode(element);
+    }
+
     /**
-     * Method getFullTextChildrenFromElement
+     * Method getFullTextChildrenFromNode
      *
-     * @param element
+     * @param node
      * @return the string of children
      */
-    public static String getFullTextChildrenFromElement(Element element) {
+    public static String getFullTextChildrenFromNode(Node node) {
         StringBuilder sb = new StringBuilder();
 
-        Node child = element.getFirstChild();
+        Node child = node.getFirstChild();
         while (child != null) {
             if (child.getNodeType() == Node.TEXT_NODE) {
                 sb.append(((Text)child).getData());
@@ -682,7 +687,7 @@
         while (sibling != null) {
             if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri)
                 && sibling.getLocalName().equals(nodeName)) {
-                if (number == 0){
+                if (number == 0) {
                     return (Element)sibling;
                 }
                 number--;
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java	Tue May 07 11:52:28 2019 -0700
@@ -97,7 +97,7 @@
 
                 LOG.debug("check resolvability by class {}", resolverTmp.getClass().getName());
 
-                if (resolverTmp != null && resolverTmp.canResolve(context)) {
+                if (resolverTmp.canResolve(context)) {
                     // Check to see whether the Resolver is allowed
                     if (context.secureValidation
                         && (resolverTmp.resolverSpi instanceof ResolverLocalFilesystem
--- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/implementations/ResolverDirectHTTP.java	Tue May 07 11:52:28 2019 -0700
@@ -33,9 +33,9 @@
 import java.net.URL;
 import java.net.URLConnection;
 import java.nio.charset.StandardCharsets;
-import java.util.Base64;
 
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
+import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverContext;
 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverException;
 import com.sun.org.apache.xml.internal.security.utils.resolver.ResourceResolverSpi;
@@ -57,7 +57,7 @@
  * </PRE>
  *
  * @see <A HREF="http://www.javaworld.com/javaworld/javatips/jw-javatip42_p.html">Java Tip 42: Write Java apps that work with proxy-based firewalls</A>
- * @see <A HREF="http://docs.oracle.com/javase/1.4.2/docs/guide/net/properties.html">SUN J2SE docs for network properties</A>
+ * @see <A HREF="https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html">JDK docs for network properties</A>
  * @see <A HREF="http://metalab.unc.edu/javafaq/javafaq.html#proxy">The JAVA FAQ Question 9.5: How do I make Java work with a proxy server?</A>
  */
 public class ResolverDirectHTTP extends ResourceResolverSpi {
@@ -122,7 +122,7 @@
                     urlConnection = openConnection(url);
 
                     String password = user + ":" + pass;
-                    String encodedPassword = Base64.getMimeEncoder().encodeToString(password.getBytes(StandardCharsets.ISO_8859_1));
+                    String encodedPassword = XMLUtils.encodeToString(password.getBytes(StandardCharsets.ISO_8859_1));
 
                     // set authentication property in the http header
                     urlConnection.setRequestProperty("Authorization",
@@ -187,7 +187,7 @@
 
             if (proxyUser != null && proxyPass != null) {
                 String password = proxyUser + ":" + proxyPass;
-                String authString = "Basic " + Base64.getMimeEncoder().encodeToString(password.getBytes(StandardCharsets.ISO_8859_1));
+                String authString = "Basic " + XMLUtils.encodeToString(password.getBytes(StandardCharsets.ISO_8859_1));
 
                 urlConnection.setRequestProperty("Proxy-Authorization", authString);
             }
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheCanonicalizer.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: ApacheCanonicalizer.java 1785016 2017-03-01 18:23:48Z coheigea $
+ * $Id: ApacheCanonicalizer.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheOctetStreamData.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheOctetStreamData.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: ApacheOctetStreamData.java 1667527 2015-03-18 12:54:20Z mullan $
+ * $Id: ApacheOctetStreamData.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheTransform.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: ApacheTransform.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: ApacheTransform.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalXMLC14NMethod.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCanonicalXMLC14NMethod.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMCanonicalXMLC14NMethod.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMCanonicalXMLC14NMethod.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCryptoBinary.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMCryptoBinary.java	Tue May 07 11:52:28 2019 -0700
@@ -1,3 +1,7 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
@@ -17,7 +21,7 @@
  * under the License.
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * $Id$
@@ -33,16 +37,16 @@
 import org.w3c.dom.Text;
 
 /**
- * A DOM-based representation of the XML <code>CryptoBinary</code> simple type
+ * A DOM-based representation of the XML {@code CryptoBinary} simple type
  * as defined in the W3C specification for XML-Signature Syntax and Processing.
  * The XML Schema Definition is defined as:
  *
- * <xmp>
+ * <pre>{@code
  * <simpleType name="CryptoBinary">
  *   <restriction base = "base64Binary">
  *   </restriction>
  * </simpleType>
- * </xmp>
+ * }</pre>
  *
  * @author Sean Mullan
  */
@@ -52,11 +56,11 @@
     private final String value;
 
     /**
-     * Create a <code>DOMCryptoBinary</code> instance from the specified
-     * <code>BigInteger</code>
+     * Create a {@code DOMCryptoBinary} instance from the specified
+     * {@code BigInteger}
      *
      * @param bigNum the arbitrary-length integer
-     * @throws NullPointerException if <code>bigNum</code> is <code>null</code>
+     * @throws NullPointerException if {@code bigNum} is {@code null}
      */
     public DOMCryptoBinary(BigInteger bigNum) {
         if (bigNum == null) {
@@ -69,7 +73,7 @@
     }
 
     /**
-     * Creates a <code>DOMCryptoBinary</code> from a node.
+     * Creates a {@code DOMCryptoBinary} from a node.
      *
      * @param cbNode a CryptoBinary text node
      * @throws MarshalException if value cannot be decoded (invalid format)
@@ -84,9 +88,9 @@
     }
 
     /**
-     * Returns the <code>BigInteger</code> that this object contains.
+     * Returns the {@code BigInteger} that this object contains.
      *
-     * @return the <code>BigInteger</code> that this object contains
+     * @return the {@code BigInteger} that this object contains
      */
     public BigInteger getBigNum() {
         return bigNum;
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMDigestMethod.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMDigestMethod.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMDigestMethod.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMDigestMethod.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMEnvelopedTransform.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMEnvelopedTransform.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMEnvelopedTransform.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMEnvelopedTransform.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMExcC14NMethod.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMExcC14NMethod.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMExcC14NMethod.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMExcC14NMethod.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMHMACSignatureMethod.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMHMACSignatureMethod.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfo.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfo.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMKeyInfo.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMKeyInfo.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyInfoFactory.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMKeyInfoFactory.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMKeyInfoFactory.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyName.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyName.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMKeyName.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMKeyName.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMKeyValue.java	Tue May 07 11:52:28 2019 -0700
@@ -21,18 +21,13 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMKeyValue.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMKeyValue.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
-import javax.xml.crypto.*;
-import javax.xml.crypto.dom.DOMCryptoContext;
-import javax.xml.crypto.dsig.*;
-import javax.xml.crypto.dsig.keyinfo.KeyValue;
-
 import java.io.IOException;
 import java.math.BigInteger;
 import java.security.KeyException;
@@ -55,6 +50,11 @@
 import java.security.spec.RSAPublicKeySpec;
 import java.util.Arrays;
 
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.dom.DOMCryptoContext;
+import javax.xml.crypto.dsig.XMLSignature;
+import javax.xml.crypto.dsig.keyinfo.KeyValue;
+
 import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -500,7 +500,7 @@
                 throw new MarshalException("Invalid ECParameterSpec");
             }
             DOMUtils.setAttribute(namedCurveElem, "URI", "urn:oid:" + oid);
-            String qname = (prefix == null || prefix.length() == 0)
+            String qname = prefix == null || prefix.length() == 0
                        ? "xmlns" : "xmlns:" + prefix;
             namedCurveElem.setAttributeNS("http://www.w3.org/2000/xmlns/",
                                           qname, XMLDSIG_11_XMLNS);
@@ -554,7 +554,7 @@
             ECPoint ecPoint = null;
 
             try {
-                String content = XMLUtils.getFullTextChildrenFromElement(curElem);
+                String content = XMLUtils.getFullTextChildrenFromNode(curElem);
                 ecPoint = decodePoint(XMLUtils.decode(content),
                                       ecParams.getCurve());
             } catch (IOException ioe) {
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMManifest.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMManifest.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMManifest.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMPGPData.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMPGPData.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMPGPData.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMPGPData.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
@@ -56,7 +56,7 @@
      * and optional list of external elements.
      *
      * @param keyPacket a PGP Key Material Packet as defined in section 5.5 of
-     *    <a href="http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The
+     *    <a href="https://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The
      *    array is cloned to prevent subsequent modification.
      * @param other a list of {@link XMLStructure}s representing elements from
      *    an external namespace. The list is defensively copied to prevent
@@ -94,10 +94,10 @@
      * optional key packet and list of external elements.
      *
      * @param keyId a PGP public key id as defined in section 11.2 of
-     *    <a href="http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The
+     *    <a href="https://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a>. The
      *    array is cloned to prevent subsequent modification.
      * @param keyPacket a PGP Key Material Packet as defined in section 5.5 of
-     *    <a href="http://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a> (may
+     *    <a href="https://www.ietf.org/rfc/rfc2440.txt">RFC 2440</a> (may
      *    be {@code null}). The array is cloned to prevent subsequent
      *    modification.
      * @param other a list of {@link XMLStructure}s representing elements from
@@ -157,10 +157,10 @@
                 String localName = childElem.getLocalName();
                 String namespace = childElem.getNamespaceURI();
                 if ("PGPKeyID".equals(localName) && XMLSignature.XMLNS.equals(namespace)) {
-                    String content = XMLUtils.getFullTextChildrenFromElement(childElem);
+                    String content = XMLUtils.getFullTextChildrenFromNode(childElem);
                     pgpKeyId = XMLUtils.decode(content);
                 } else if ("PGPKeyPacket".equals(localName) && XMLSignature.XMLNS.equals(namespace)) {
-                    String content = XMLUtils.getFullTextChildrenFromElement(childElem);
+                    String content = XMLUtils.getFullTextChildrenFromNode(childElem);
                     pgpKeyPacket = XMLUtils.decode(content);
                 } else {
                     other.add
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMReference.java	Tue May 07 11:52:28 2019 -0700
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * ===========================================================================
@@ -31,7 +31,7 @@
  * ===========================================================================
  */
 /*
- * $Id: DOMReference.java 1803518 2017-07-31 11:02:52Z coheigea $
+ * $Id: DOMReference.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
@@ -56,7 +56,6 @@
 import org.jcp.xml.dsig.internal.DigesterOutputStream;
 import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
 import com.sun.org.apache.xml.internal.security.utils.UnsyncBufferedOutputStream;
-import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
 
 /**
  * DOM-based implementation of Reference.
@@ -244,7 +243,7 @@
 
         // unmarshal DigestValue
         Element dvElem = DOMUtils.getNextSiblingElement(dmElem, "DigestValue", XMLSignature.XMLNS);
-        String content = XMLUtils.getFullTextChildrenFromElement(dvElem);
+        String content = XMLUtils.getFullTextChildrenFromNode(dvElem);
         this.digestValue = XMLUtils.decode(content);
 
         // check for extra elements
@@ -311,6 +310,7 @@
 
         refElem = DOMUtils.createElement(ownerDoc, "Reference",
                                          XMLSignature.XMLNS, dsPrefix);
+
         // set attributes
         DOMUtils.setAttributeID(refElem, "Id", id);
         DOMUtils.setAttribute(refElem, "URI", uri);
@@ -341,7 +341,6 @@
         if (digestValue != null) {
             digestValueElem.appendChild
                 (ownerDoc.createTextNode(XMLUtils.encodeToString(digestValue)));
-
         }
         refElem.appendChild(digestValueElem);
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMRetrievalMethod.java	Tue May 07 11:52:28 2019 -0700
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * ===========================================================================
@@ -31,7 +31,7 @@
  * ===========================================================================
  */
 /*
- * $Id: DOMRetrievalMethod.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMRetrievalMethod.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMSignatureMethod.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMSignatureMethod.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperties.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperties.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMSignatureProperties.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMSignatureProperties.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperty.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureProperty.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMSignatureProperty.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMSignatureProperty.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignedInfo.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMSignedInfo.java 1820179 2018-01-04 19:09:52Z mullan $
+ * $Id: DOMSignedInfo.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMStructure.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMStructure.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMStructure.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMStructure.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMTransform.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMTransform.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMTransform.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMURIDereferencer.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMURIDereferencer.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMURIDereferencer.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMUtils.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMUtils.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMUtils.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMUtils.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
@@ -92,7 +92,7 @@
     public static Element createElement(Document doc, String tag,
                                         String nsURI, String prefix)
     {
-        String qName = (prefix == null || prefix.length() == 0)
+        String qName = prefix == null || prefix.length() == 0
                        ? tag : prefix + ":" + tag;
         return doc.createElementNS(nsURI, qName);
     }
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509Data.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509Data.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMX509Data.java 1789702 2017-03-31 15:15:04Z coheigea $
+ * $Id: DOMX509Data.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
@@ -33,12 +33,13 @@
 import java.security.cert.*;
 import java.util.*;
 
-import javax.xml.crypto.*;
+import javax.security.auth.x500.X500Principal;
+import javax.xml.crypto.MarshalException;
+import javax.xml.crypto.XMLStructure;
 import javax.xml.crypto.dom.DOMCryptoContext;
-import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dsig.XMLSignature;
 import javax.xml.crypto.dsig.keyinfo.X509Data;
 import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial;
-import javax.security.auth.x500.X500Principal;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -115,7 +116,7 @@
                 } else if ("X509SubjectName".equals(localName) && XMLSignature.XMLNS.equals(namespace)) {
                     newContent.add(childElem.getFirstChild().getNodeValue());
                 } else if ("X509SKI".equals(localName) && XMLSignature.XMLNS.equals(namespace)) {
-                    String content = XMLUtils.getFullTextChildrenFromElement(childElem);
+                    String content = XMLUtils.getFullTextChildrenFromNode(childElem);
                     newContent.add(XMLUtils.decode(content));
                 } else if ("X509CRL".equals(localName) && XMLSignature.XMLNS.equals(namespace)) {
                     newContent.add(unmarshalX509CRL(childElem));
@@ -132,6 +133,7 @@
         return content;
     }
 
+    @Override
     public void marshal(Node parent, String dsPrefix, DOMCryptoContext context)
         throws MarshalException
     {
@@ -241,7 +243,7 @@
             if (cf == null) {
                 cf = CertificateFactory.getInstance("X.509");
             }
-            String content = XMLUtils.getFullTextChildrenFromElement(elem);
+            String content = XMLUtils.getFullTextChildrenFromNode(elem);
             return new ByteArrayInputStream(XMLUtils.decode(content));
         } catch (CertificateException e) {
             throw new MarshalException("Cannot create CertificateFactory", e);
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509IssuerSerial.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMX509IssuerSerial.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMX509IssuerSerial.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMX509IssuerSerial.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLObject.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLObject.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMXMLObject.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMXMLObject.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignature.java	Tue May 07 11:52:28 2019 -0700
@@ -21,7 +21,7 @@
  * under the License.
  */
 /*
- * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * ===========================================================================
@@ -31,7 +31,7 @@
  * ===========================================================================
  */
 /*
- * $Id: DOMXMLSignature.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMXMLSignature.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
@@ -508,7 +508,7 @@
             throws MarshalException
         {
             // base64 decode signatureValue
-            String content = XMLUtils.getFullTextChildrenFromElement(sigValueElem);
+            String content = XMLUtils.getFullTextChildrenFromNode(sigValueElem);
             value = XMLUtils.decode(content);
 
             Attr attr = sigValueElem.getAttributeNodeNS(null, "Id");
@@ -612,6 +612,7 @@
                             DOMCryptoContext context)
             throws MarshalException
         {
+            // create SignatureValue element
             sigValueElem = DOMUtils.createElement(ownerDoc, "SignatureValue",
                                                   XMLSignature.XMLNS, dsPrefix);
             if (valueBase64 != null) {
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMXMLSignatureFactory.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMXMLSignatureFactory.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
@@ -255,8 +255,6 @@
             return new DOMSignatureMethod.SHA384withRSA(params);
         } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA512)) {
             return new DOMSignatureMethod.SHA512withRSA(params);
-        } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA512)) {
-            return new DOMSignatureMethod.SHA512withRSA(params);
         } else if (algorithm.equals(DOMSignatureMethod.RSA_RIPEMD160)) {
             return new DOMSignatureMethod.RIPEMD160withRSA(params);
         } else if (algorithm.equals(DOMSignatureMethod.RSA_SHA1_MGF1)) {
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java	Tue May 07 11:52:28 2019 -0700
@@ -28,10 +28,10 @@
  * ===========================================================================
  */
 /*
- * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMXPathFilter2Transform.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMXPathFilter2Transform.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathTransform.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXPathTransform.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMXPathTransform.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMXPathTransform.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXSLTTransform.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXSLTTransform.java	Tue May 07 11:52:28 2019 -0700
@@ -21,10 +21,10 @@
  * under the License.
  */
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: DOMXSLTTransform.java 1788465 2017-03-24 15:10:51Z coheigea $
+ * $Id: DOMXSLTTransform.java 1854026 2019-02-21 09:30:01Z coheigea $
  */
 package org.jcp.xml.dsig.internal.dom;
 
--- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java	Tue May 07 11:52:28 2019 -0700
@@ -28,10 +28,10 @@
  * ===========================================================================
  */
 /*
- * Portions copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Portions copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
- * $Id: XMLDSigRI.java 1804972 2017-08-14 09:59:23Z coheigea $
+ * $Id: XMLDSigRI.java 1833618 2018-06-15 17:36:20Z mullan $
  */
 package org.jcp.xml.dsig.internal.dom;
 
@@ -123,7 +123,7 @@
                     } else if (algo.equals(Transform.XSLT)) {
                         return new DOMXSLTTransform();
                     }
-                 }
+                }
             } catch (Exception ex) {
                 throw new NoSuchAlgorithmException("Error constructing " +
                     type + " for " + algo + " using XMLDSig", ex);
--- a/src/java.xml.crypto/share/legal/santuario.md	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml.crypto/share/legal/santuario.md	Tue May 07 11:52:28 2019 -0700
@@ -1,10 +1,10 @@
-## Apache Santuario v2.1.1
+## Apache Santuario v2.1.3
 
 ### Apache Santuario Notice
 <pre>
 
   Apache Santuario - XML Security for Java
-  Copyright 1999-2018 The Apache Software Foundation
+  Copyright 1999-2019 The Apache Software Foundation
 
   This product includes software developed at
   The Apache Software Foundation (http://www.apache.org/).
--- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/NodeSortRecord.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -20,20 +20,17 @@
 
 package com.sun.org.apache.xalan.internal.xsltc.dom;
 
-import com.sun.org.apache.xalan.internal.utils.ObjectFactory;
-import com.sun.org.apache.xalan.internal.xsltc.CollatorFactory;
 import com.sun.org.apache.xalan.internal.xsltc.DOM;
 import com.sun.org.apache.xalan.internal.xsltc.TransletException;
 import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
 import com.sun.org.apache.xml.internal.utils.StringComparable;
 import java.text.Collator;
 import java.util.Locale;
-import jdk.xml.internal.SecuritySupport;
 
 /**
  * Base class for sort records containing application specific sort keys
  *
- * @LastModified: Oct 2017
+ * @LastModified: May 2019
  */
 public abstract class NodeSortRecord {
     public static final int COMPARE_STRING     = 0;
@@ -68,8 +65,6 @@
     @Deprecated
     protected Locale _locale;
 
-    protected CollatorFactory _collatorFactory;
-
     protected SortSettings _settings;
 
     private DOM    _dom = null;
@@ -109,33 +104,8 @@
         int levels = settings.getSortOrders().length;
         _values = new Object[levels];
 
-        String colFactClassname = null;
-        try {
-            // -- W. Eliot Kimber (eliot@isogen.com)
-            colFactClassname =
-                SecuritySupport.getSystemProperty("com.sun.org.apache.xalan.internal.xsltc.COLLATOR_FACTORY");
-        }
-        catch (SecurityException e) {
-            // If we can't read the propery, just use default collator
-        }
-
-        if (colFactClassname != null) {
-            try {
-                Object candObj = ObjectFactory.findProviderClass(colFactClassname, true);
-                _collatorFactory = (CollatorFactory)candObj;
-            } catch (ClassNotFoundException e) {
-                throw new TransletException(e);
-            }
-            Locale[] locales = settings.getLocales();
-            _collators = new Collator[levels];
-            for (int i = 0; i < levels; i++){
-                _collators[i] = _collatorFactory.getCollator(locales[i]);
-            }
-            _collator = _collators[0];
-        } else {
-            _collators = settings.getCollators();
-            _collator = _collators[0];
-        }
+        _collators = settings.getCollators();
+        _collator = _collators[0];
     }
 
     /**
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -566,7 +566,7 @@
                 Assert.checkNonNull(jarFSProvider, "should have been caught before!");
                 this.fileSystem = jarFSProvider.newFileSystem(archivePath, env);
             } else {
-                this.fileSystem = FileSystems.newFileSystem(archivePath, null);
+                this.fileSystem = FileSystems.newFileSystem(archivePath, (ClassLoader)null);
             }
             packages = new HashMap<>();
             for (Path root : fileSystem.getRootDirectories()) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -379,7 +379,7 @@
                         /* Not a recognized extension; open it to see if
                          it looks like a valid zip file. */
                         try {
-                            FileSystems.newFileSystem(file, null).close();
+                            FileSystems.newFileSystem(file, (ClassLoader)null).close();
                             if (warn) {
                                 log.warning(Lint.LintCategory.PATH,
                                             Warnings.UnexpectedArchiveFile(file));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Tue May 07 11:52:28 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -113,7 +113,7 @@
         SUPPORTED_JAVA_PLATFORM_VERSIONS = new TreeSet<>(NUMERICAL_COMPARATOR);
         Path ctSymFile = findCtSym();
         if (Files.exists(ctSymFile)) {
-            try (FileSystem fs = FileSystems.newFileSystem(ctSymFile, null);
+            try (FileSystem fs = FileSystems.newFileSystem(ctSymFile, (ClassLoader)null);
                  DirectoryStream<Path> dir =
                          Files.newDirectoryStream(fs.getRootDirectories().iterator().next())) {
                 for (Path section : dir) {
@@ -252,7 +252,7 @@
                 try {
                     FileSystem fs = ctSym2FileSystem.get(file);
                     if (fs == null) {
-                        ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, null));
+                        ctSym2FileSystem.put(file, fs = FileSystems.newFileSystem(file, (ClassLoader)null));
                     }
 
                     Path root = fs.getRootDirectories().iterator().next();
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Tue May 07 11:52:28 2019 -0700
@@ -612,10 +612,15 @@
      * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's
      * log stream.
      *
+     * @param flush specifies if the log stream should be flushed after writing
+     * @param canThrow specifies if an error in the {@code bytes}, {@code offset} or {@code length}
+     *            arguments should result in an exception or a negative return value
+     * @return 0 on success, -1 if {@code bytes == null && !canThrow}, -2 if {@code !canThrow} and
+     *         copying would cause access of data outside array bounds
      * @throws NullPointerException if {@code bytes == null}
      * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds
      */
-    native void writeDebugOutput(byte[] bytes, int offset, int length);
+    native int writeDebugOutput(byte[] bytes, int offset, int length, boolean flush, boolean canThrow);
 
     /**
      * Flush HotSpot's log stream.
@@ -947,4 +952,18 @@
      */
     native boolean addFailedSpeculation(long failedSpeculationsAddress, byte[] speculation);
 
+    /**
+     * @see HotSpotJVMCIRuntime#isCurrentThreadAttached()
+     */
+    native boolean isCurrentThreadAttached();
+
+    /**
+     * @see HotSpotJVMCIRuntime#attachCurrentThread
+     */
+    native boolean attachCurrentThread(boolean asDaemon);
+
+    /**
+     * @see HotSpotJVMCIRuntime#detachCurrentThread()
+     */
+    native void detachCurrentThread();
 }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Fri May 03 17:06:42 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java	Tue May 07 11:52:28 2019 -0700
@@ -46,7 +46,6 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.ServiceLoader;
-import java.util.TreeMap;
 import java.util.function.Predicate;
 
 import jdk.internal.misc.Unsafe;
@@ -180,8 +179,8 @@
 
                         // Can only do eager initialization of the JVMCI compiler
                         // once the singleton instance is available.
-                        if (instance.config.getFlag("EagerJVMCI", Boolean.class)) {
-                            instance.getCompiler();
+                        if (result.config.getFlag("EagerJVMCI", Boolean.class)) {
+                            result.getCompiler();
                         }
                     }
                     // Ensures JVMCIRuntime::_HotSpotJVMCIRuntime_instance is
@@ -384,7 +383,25 @@
     /**
      * Cache for speeding up {@link #fromClass(Class)}.
      */
-    @NativeImageReinitialize private volatile ClassValue<WeakReference<HotSpotResolvedJavaType>> resolvedJavaType;
+    @NativeImageReinitialize private volatile ClassValue<WeakReferenceHolder<HotSpotResolvedJavaType>> resolvedJavaType;
+
+    /**
+     * To avoid calling ClassValue.remove to refresh the weak reference, which
+     * under certain circumstances can lead to an infinite loop, we use a
+     * permanent holder with a mutable field that we refresh.
+     */
+    private static class WeakReferenceHolder<T> {
+        private volatile WeakReference<T> ref;
+        WeakReferenceHolder(T value) {
+            set(value);
+        }
+        void set(T value) {
+            ref = new WeakReference<T>(value);
+        }
+        T get() {
+            return ref.get();
+        }
+    };
 
     @NativeImageReinitialize private HashMap<Long, WeakReference<ResolvedJavaType>> resolvedJavaTypes;
 
@@ -464,7 +481,7 @@
         }
 
         if (Option.PrintConfig.getBoolean()) {
-            printConfig(configStore, compilerToVm);
+            configStore.printConfig();
         }
     }
 
@@ -486,27 +503,25 @@
         if (resolvedJavaType == null) {
             synchronized (this) {
                 if (resolvedJavaType == null) {
-                    resolvedJavaType = new ClassValue<WeakReference<HotSpotResolvedJavaType>>() {
+                    resolvedJavaType = new ClassValue<WeakReferenceHolder<HotSpotResolvedJavaType>>() {
                         @Override
-                        protected WeakReference<HotSpotResolvedJavaType> computeValue(Class<?> type) {
-                            return new WeakReference<>(createClass(type));
+                        protected WeakReferenceHolder<HotSpotResolvedJavaType> computeValue(Class<?> type) {
+                            return new WeakReferenceHolder<>(createClass(type));
                         }
                     };
                 }
             }
         }
-        HotSpotResolvedJavaType javaType = null;
-        while (javaType == null) {
-            WeakReference<HotSpotResolvedJavaType> type = resolvedJavaType.get(javaClass);
-            javaType = type.get();
-            if (javaType == null) {
-                /*
-                 * If the referent has become null, clear out the current value and let computeValue
-                 * above create a new value. Reload the value in a loop because in theory the
-                 * WeakReference referent can be reclaimed at any point.
-                 */
-                resolvedJavaType.remove(javaClass);
-            }
+
+        WeakReferenceHolder<HotSpotResolvedJavaType> ref = resolvedJavaType.get(javaClass);
+        HotSpotResolvedJavaType javaType = ref.get();
+        if (javaType == null) {
+            /*
+             * If the referent has become null, create a new value and
+             * update cached weak reference.
+             */
+            javaType = createClass(javaClass);
+            ref.set(javaType);
         }
         return javaType;
     }
@@ -727,39 +742,21 @@
         }
     }
 
-    @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
-    private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
-        String line = String.format(format, args);
-        byte[] lineBytes = line.getBytes();
-        vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
-        vm.flushDebugOutput();
-    }
-
-    private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
-        TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
-        for (VMField field : fields.values()) {
-            if (!field.isStatic()) {
-                printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
-            } else {
-                String value = field.value == null ? "null" : field.value instanceof Boolean ? field.value.toString() : String.format("%d[0x%x]", field.value, field.value);
-                printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);
-            }
-        }
-        TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
-        for (VMFlag flag : flags.values()) {
-            printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);
-        }
-        TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
-        for (Map.Entry<String, Long> e : addresses.entrySet()) {
-            printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
-        }
-        TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
-        for (Map.Entry<String, Long> e : constants.entrySet()) {
-            printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
-        }
-        for (VMIntrinsicMethod e : store.getIntrinsics()) {
-            printConfigLine(vm, "[vmconfig:intrinsic] %d = %s.%s %s%n", e.id, e.declaringClass, e.name, e.descriptor);
-        }
+    /**
+     * Writes {@code length} bytes from {@code bytes} starting at offset {@code offset} to HotSpot's
+     * log stream.
+     *
+     * @param flush specifies if the log stream should be flushed after writing
+     * @param canThrow specifies if an error in the {@code bytes}, {@code offset} or {@code length}
+     *            arguments should result in an exception or a negative return value. If
+     *            {@code false}, this call will not perform any heap allocation
+     * @return 0 on success, -1 if {@code bytes == null && !canThrow}, -2 if {@code !canThrow} and
+     *         copying would cause access of data outside array bounds
+     * @throws NullPointerException if {@code bytes == null}
+     * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds
+     */
+    public int writeDebugOutput(byte[] bytes, int offset, int length, boolean flush, boolean canThrow) {
+        return compilerToVm.writeDebugOutput(bytes, offset, length, flush, canThrow);
     }
 
     /**
@@ -777,7 +774,7 @@
                 } else if (len == 0) {
                     return;
                 }
-                compilerToVm.writeDebugOutput(b, off, len);
+                compilerToVm.writeDebugOutput(b, off, len, false, true);
             }
 
             @Override
@@ -907,11 +904,13 @@
      *         the Java VM in the JVMCI shared library, and the remaining values are the first 3
      *         pointers in the Invocation API function table (i.e., {@code JNIInvokeInterface})
      * @throws NullPointerException if {@code clazz == null}
-     * @throws IllegalArgumentException if the current execution context is the JVMCI shared library
-     *             or if {@code clazz} is {@link Class#isPrimitive()}
-     * @throws UnsatisfiedLinkError if the JVMCI shared library is not available, a native method in
-     *             {@code clazz} is already linked or the JVMCI shared library does not contain a
-     *             JNI-compatible symbol for a native method in {@code clazz}
+     * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
+     *             {@code -XX:-UseJVMCINativeLibrary})
+     * @throws IllegalStateException if the current execution context is the JVMCI shared library
+     * @throws IllegalArgumentException if {@code clazz} is {@link Class#isPrimitive()}
+     * @throws UnsatisfiedLinkError if there's a problem linking a native method in {@code clazz}
+     *             (no matching JNI symbol or the native method is already linked to a different
+     *             address)
      */
     public long[] registerNativeMethods(Class<?> clazz) {
         return compilerToVm.registerNativeMethods(clazz);
@@ -935,6 +934,8 @@
      *
      * @param obj an object for which an equivalent instance in the peer runtime is requested
      * @return a JNI global reference to the mirror of {@code obj} in the peer runtime
+     * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
+     *             {@code -XX:-UseJVMCINativeLibrary})
      * @throws IllegalArgumentException if {@code obj} is not of a translatable type
      *
      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
@@ -950,7 +951,9 @@
      *
      * @param handle a JNI global reference to an object in the current runtime
      * @return the object referred to by {@code handle}
-     * @throws ClassCastException if the returned object cannot be case to {@code type}
+     * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
+     *             {@code -XX:-UseJVMCINativeLibrary})
+     * @throws ClassCastException if the returned object cannot be cast to {@code type}
      *
      * @see "https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#global_and_local_references"
      *
@@ -960,6 +963,44 @@
     }
 
     /**
+     * Determines if the current thread is attached to the peer runtime.
+     *
+     * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
+     *             {@code -XX:-UseJVMCINativeLibrary})
+     * @throws IllegalStateException if the peer runtime has not been initialized
+     */
+    public boolean isCurrentThreadAttached() {
+        return compilerToVm.isCurrentThreadAttached();
+    }
+
+    /**
+     * Ensures the current thread is attached to the peer runtime.
+     *
+     * @param asDaemon if the thread is not yet attached, should it be attached as a daemon
+     * @return {@code true} if this call attached the current thread, {@code false} if the current
+     *         thread was already attached
+     * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
+     *             {@code -XX:-UseJVMCINativeLibrary})
+     * @throws IllegalStateException if the peer runtime has not been initialized or there is an
+     *             error while trying to attach the thread
+     */
+    public boolean attachCurrentThread(boolean asDaemon) {
+        return compilerToVm.attachCurrentThread(asDaemon);
+    }
+
+    /**
+     * Detaches the current thread from the peer runtime.
+     *
+     * @throws UnsupportedOperationException if the JVMCI shared library is not enabled (i.e.
+     *             {@code -XX:-UseJVMCINativeLibrary})
+     * @throws IllegalStateException if the peer runtime has not been initialized or if the current
+     *             thread is not attached or if there is an error while trying to detach the thread
+     */
+    public void detachCurrentThread() {
+