Merge
authorvlivanov
Mon, 15 Feb 2016 18:42:45 +0000
changeset 36076 ef2c34c80771
parent 36072 2e822f451746 (current diff)
parent 36075 e1685e30beca (diff)
child 36077 fa6d92de1c70
Merge
--- a/hotspot/src/share/vm/code/codeBlob.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/code/codeBlob.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -291,6 +291,9 @@
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = new (size) MethodHandlesAdapterBlob(size);
+    if (blob == NULL) {
+      vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "CodeCache: no room for method handle adapter blob");
+    }
   }
   // Track memory usage statistic after releasing CodeCache_lock
   MemoryService::track_code_cache_memory_usage();
--- a/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/gc/shared/memset_with_concurrent_readers.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -34,7 +34,7 @@
 #if INCLUDE_ALL_GCS
 
 // Unit test
-#ifdef ASSERT
+#ifndef PRODUCT
 
 static unsigned line_byte(const char* line, size_t i) {
   return unsigned(line[i]) & 0xFF;
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -825,10 +825,12 @@
         input_not_const = false;
         const TypeOopPtr* oop_ptr = receiver->bottom_type()->is_oopptr();
         ciMethod* target = oop_ptr->const_oop()->as_method_handle()->get_vmtarget();
-        guarantee(!target->is_method_handle_intrinsic(), "should not happen");  // XXX remove
         const int vtable_index = Method::invalid_vtable_index;
-        CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true);
-        assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
+        CallGenerator* cg = C->call_generator(target, vtable_index,
+                                              false /* call_does_dispatch */,
+                                              jvms,
+                                              true /* allow_inline */,
+                                              PROB_ALWAYS);
         return cg;
       } else {
         const char* msg = "receiver not constant";
@@ -899,13 +901,15 @@
           target = C->optimize_virtual_call(caller, jvms->bci(), klass, klass,
                                             target, receiver_type, is_virtual,
                                             call_does_dispatch, vtable_index, // out-parameters
-                                            /*check_access=*/false);
+                                            false /* check_access */);
           // We lack profiling at this call but type speculation may
           // provide us with a type
           speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL;
         }
-        CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, /*allow_inline=*/true, PROB_ALWAYS, speculative_receiver_type, true, true);
-        assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
+        CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms,
+                                              true /* allow_inline */,
+                                              PROB_ALWAYS,
+                                              speculative_receiver_type);
         return cg;
       } else {
         const char* msg = "member_name not constant";
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -63,30 +63,21 @@
 bool MethodHandles::_enabled = false; // set true after successful native linkage
 MethodHandlesAdapterBlob* MethodHandles::_adapter_code = NULL;
 
-
 /**
  * Generates method handle adapters. Returns 'false' if memory allocation
  * failed and true otherwise.
  */
-bool MethodHandles::generate_adapters() {
-  if (SystemDictionary::MethodHandle_klass() == NULL) {
-    return true;
-  }
-
+void MethodHandles::generate_adapters() {
+  assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present");
   assert(_adapter_code == NULL, "generate only once");
 
   ResourceMark rm;
   TraceTime timer("MethodHandles adapters generation", TraceStartupTime);
   _adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size);
-  if (_adapter_code == NULL) {
-     return false;
-  }
-
   CodeBuffer code(_adapter_code);
   MethodHandlesAdapterGenerator g(&code);
   g.generate();
   code.log_section_sizes("MethodHandlesAdapterBlob");
-  return true;
 }
 
 //------------------------------------------------------------------------------
@@ -1436,53 +1427,31 @@
 };
 
 /**
- * Helper method to register native methods.
- */
-static bool register_natives(JNIEnv* env, jclass clazz, const JNINativeMethod* methods, jint nMethods) {
-  int status = env->RegisterNatives(clazz, methods, nMethods);
-  if (status != JNI_OK || env->ExceptionOccurred()) {
-    warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
-    env->ExceptionClear();
-    return false;
-  }
-  return true;
-}
-
-/**
  * This one function is exported, used by NativeLookup.
  */
 JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
   assert(!MethodHandles::enabled(), "must not be enabled");
-  bool enable_MH = true;
+  assert(SystemDictionary::MethodHandle_klass() != NULL, "should be present");
 
-  jclass MH_class = NULL;
-  if (SystemDictionary::MethodHandle_klass() == NULL) {
-    enable_MH = false;
-  } else {
-    oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror();
-    MH_class = (jclass) JNIHandles::make_local(env, mirror);
-  }
+  oop mirror = SystemDictionary::MethodHandle_klass()->java_mirror();
+  jclass MH_class = (jclass) JNIHandles::make_local(env, mirror);
 
-  if (enable_MH) {
+  {
     ThreadToNativeFromVM ttnfv(thread);
 
-    if (enable_MH) {
-      enable_MH = register_natives(env, MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod));
-    }
-    if (enable_MH) {
-      enable_MH = register_natives(env, MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
-    }
+    int status = env->RegisterNatives(MHN_class, MHN_methods, sizeof(MHN_methods)/sizeof(JNINativeMethod));
+    guarantee(status == JNI_OK && !env->ExceptionOccurred(),
+              "register java.lang.invoke.MethodHandleNative natives");
+
+    status = env->RegisterNatives(MH_class, MH_methods, sizeof(MH_methods)/sizeof(JNINativeMethod));
+    guarantee(status == JNI_OK && !env->ExceptionOccurred(),
+              "register java.lang.invoke.MethodHandle natives");
   }
 
   if (TraceInvokeDynamic) {
     tty->print_cr("MethodHandle support loaded (using LambdaForms)");
   }
 
-  if (enable_MH) {
-    if (MethodHandles::generate_adapters() == false) {
-      THROW_MSG(vmSymbols::java_lang_VirtualMachineError(), "Out of space in CodeCache for method handle adapters");
-    }
-    MethodHandles::set_enabled(true);
-  }
+  MethodHandles::set_enabled(true);
 }
 JVM_END
--- a/hotspot/src/share/vm/prims/methodHandles.hpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/prims/methodHandles.hpp	Mon Feb 15 18:42:45 2016 +0000
@@ -81,7 +81,7 @@
   static void flush_dependent_nmethods(Handle call_site, Handle target);
 
   // Generate MethodHandles adapters.
-  static bool generate_adapters();
+  static void generate_adapters();
 
   // Called from MethodHandlesAdapterGenerator.
   static address generate_method_handle_interpreter_entry(MacroAssembler* _masm, vmIntrinsics::ID iid);
--- a/hotspot/src/share/vm/runtime/init.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/runtime/init.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -145,6 +145,7 @@
   }
   javaClasses_init();   // must happen after vtable initialization
   stubRoutines_init2(); // note: StubRoutines need 2-phase init
+  MethodHandles::generate_adapters();
   CodeCacheExtensions::complete_step(CodeCacheExtensionsSteps::StubRoutines2);
 
 #if INCLUDE_NMT
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -37,7 +37,7 @@
 
 StubCodeDesc* StubCodeDesc::_list = NULL;
 int           StubCodeDesc::_count = 0;
-
+bool          StubCodeDesc::_frozen = false;
 
 StubCodeDesc* StubCodeDesc::desc_for(address pc) {
   StubCodeDesc* p = _list;
@@ -46,20 +46,23 @@
   return p;
 }
 
-
 StubCodeDesc* StubCodeDesc::desc_for_index(int index) {
   StubCodeDesc* p = _list;
   while (p != NULL && p->index() != index) p = p->_next;
   return p;
 }
 
-
 const char* StubCodeDesc::name_for(address pc) {
   StubCodeDesc* p = desc_for(pc);
   return p == NULL ? NULL : p->name();
 }
 
 
+void StubCodeDesc::freeze() {
+  assert(!_frozen, "repeated freeze operation");
+  _frozen = true;
+}
+
 void StubCodeDesc::print_on(outputStream* st) const {
   st->print("%s", group());
   st->print("::");
@@ -110,12 +113,10 @@
   }
 }
 
-
 void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
   // default implementation - do nothing
 }
 
-
 void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) {
   // default implementation - record the cdesc
   if (_first_stub == NULL)  _first_stub = cdesc;
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp	Mon Feb 15 18:42:45 2016 +0000
@@ -28,7 +28,7 @@
 #include "asm/assembler.hpp"
 #include "memory/allocation.hpp"
 
-// All the basic framework for stubcode generation/debugging/printing.
+// All the basic framework for stub code generation/debugging/printing.
 
 
 // A StubCodeDesc describes a piece of generated code (usually stubs).
@@ -37,9 +37,10 @@
 // this may have to change if searching becomes too slow.
 
 class StubCodeDesc: public CHeapObj<mtCode> {
- protected:
+ private:
   static StubCodeDesc* _list;                  // the list of all descriptors
   static int           _count;                 // length of list
+  static bool          _frozen;                // determines whether _list modifications are allowed
 
   StubCodeDesc*        _next;                  // the next element in the linked list
   const char*          _group;                 // the group to which the stub code belongs
@@ -68,6 +69,7 @@
   static const char*   name_for(address pc);     // returns the name of the code containing pc or NULL
 
   StubCodeDesc(const char* group, const char* name, address begin, address end = NULL) {
+    assert(!_frozen, "no modifications allowed");
     assert(name != NULL, "no name specified");
     _next           = _list;
     _group          = group;
@@ -78,6 +80,8 @@
     _list           = this;
   };
 
+  static void freeze();
+
   const char* group() const                      { return _group; }
   const char* name() const                       { return _name; }
   int         index() const                      { return _index; }
@@ -117,7 +121,7 @@
 // later via an address pointing into it.
 
 class StubCodeMark: public StackObj {
- protected:
+ private:
   StubCodeGenerator* _cgen;
   StubCodeDesc*      _cdesc;
 
--- a/hotspot/src/share/vm/runtime/thread.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -3600,6 +3600,9 @@
     vm_exit_during_initialization("Failed to initialize tracing backend");
   }
 
+  // No more stub generation allowed after that point.
+  StubCodeDesc::freeze();
+
   // Set flag that basic initialization has completed. Used by exceptions and various
   // debug stuff, that does not work until all basic classes have been initialized.
   set_init_completed();
--- a/hotspot/src/share/vm/utilities/quickSort.cpp	Mon Feb 15 15:15:56 2016 +0100
+++ b/hotspot/src/share/vm/utilities/quickSort.cpp	Mon Feb 15 18:42:45 2016 +0000
@@ -44,6 +44,31 @@
   }
   return 1;
 }
+
+static void print_array(const char* prefix, int* array, int length) {
+  tty->print("%s:", prefix);
+  for (int i = 0; i < length; i++) {
+    tty->print(" %d", array[i]);
+  }
+  tty->cr();
+}
+
+static bool compare_arrays(int* actual, int* expected, int length) {
+  for (int i = 0; i < length; i++) {
+    if (actual[i] != expected[i]) {
+      print_array("Sorted array  ", actual, length);
+      print_array("Expected array", expected, length);
+      return false;
+    }
+  }
+  return true;
+}
+
+template <class C>
+static bool sort_and_compare(int* arrayToSort, int* expectedResult, int length, C comparator, bool idempotent = false) {
+  QuickSort::sort<int, C>(arrayToSort, length, comparator, idempotent);
+  return compare_arrays(arrayToSort, expectedResult, length);
+}
 #endif // ASSERT
 
 static int test_even_odd_comparator(int a, int b) {
@@ -72,31 +97,6 @@
   }
 }
 
-static void print_array(const char* prefix, int* array, int length) {
-  tty->print("%s:", prefix);
-  for (int i = 0; i < length; i++) {
-    tty->print(" %d", array[i]);
-  }
-  tty->cr();
-}
-
-static bool compare_arrays(int* actual, int* expected, int length) {
-  for (int i = 0; i < length; i++) {
-    if (actual[i] != expected[i]) {
-      print_array("Sorted array  ", actual, length);
-      print_array("Expected array", expected, length);
-      return false;
-    }
-  }
-  return true;
-}
-
-template <class C>
-static bool sort_and_compare(int* arrayToSort, int* expectedResult, int length, C comparator, bool idempotent = false) {
-  QuickSort::sort<int, C>(arrayToSort, length, comparator, idempotent);
-  return compare_arrays(arrayToSort, expectedResult, length);
-}
-
 void QuickSort_test() {
   {
     int* test_array = NULL;