8199620: Support for JNI object pinning
authorrkennke
Tue, 20 Mar 2018 15:59:36 +0100
changeset 49466 6ce398fe53fd
parent 49465 4881673579b7
child 49467 74db2b7cec75
8199620: Support for JNI object pinning Reviewed-by: pliden, tschatzl, eosterlund
src/hotspot/share/gc/shared/collectedHeap.cpp
src/hotspot/share/gc/shared/collectedHeap.hpp
src/hotspot/share/prims/jni.cpp
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp	Fri Mar 16 19:13:13 2018 +0100
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp	Tue Mar 20 15:59:36 2018 +0100
@@ -585,3 +585,12 @@
 void CollectedHeap::post_initialize() {
   initialize_serviceability();
 }
+
+oop CollectedHeap::pin_object(JavaThread* thread, oop o) {
+  GCLocker::lock_critical(thread);
+  return o;
+}
+
+void CollectedHeap::unpin_object(JavaThread* thread, oop o) {
+  GCLocker::unlock_critical(thread);
+}
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Fri Mar 16 19:13:13 2018 +0100
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Mar 20 15:59:36 2018 +0100
@@ -588,6 +588,15 @@
   // perform cleanup tasks serially in the VMThread.
   virtual WorkGang* get_safepoint_workers() { return NULL; }
 
+  // Support for object pinning. This is used by JNI's Get*Critical() and
+  // Release*Critical() family of functions. A GC may either use the GCLocker
+  // protocol to ensure no critical arrays are in-use when entering
+  // a GC pause, or it can implement pinning, which must guarantee that
+  // the object does not move while pinned.
+  virtual oop pin_object(JavaThread* thread, oop o);
+
+  virtual void unpin_object(JavaThread* thread, oop o);
+
   // Non product verification and debugging.
 #ifndef PRODUCT
   // Support for PromotionFailureALot.  Return true if it's time to cause a
--- a/src/hotspot/share/prims/jni.cpp	Fri Mar 16 19:13:13 2018 +0100
+++ b/src/hotspot/share/prims/jni.cpp	Tue Mar 20 15:59:36 2018 +0100
@@ -36,7 +36,6 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
-#include "gc/shared/gcLocker.inline.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
@@ -3149,11 +3148,11 @@
 JNI_ENTRY(void*, jni_GetPrimitiveArrayCritical(JNIEnv *env, jarray array, jboolean *isCopy))
   JNIWrapper("GetPrimitiveArrayCritical");
  HOTSPOT_JNI_GETPRIMITIVEARRAYCRITICAL_ENTRY(env, array, (uintptr_t *) isCopy);
-  GCLocker::lock_critical(thread);
   if (isCopy != NULL) {
     *isCopy = JNI_FALSE;
   }
   oop a = JNIHandles::resolve_non_null(array);
+  a = Universe::heap()->pin_object(thread, a);
   assert(a->is_array(), "just checking");
   BasicType type;
   if (a->is_objArray()) {
@@ -3170,8 +3169,8 @@
 JNI_ENTRY(void, jni_ReleasePrimitiveArrayCritical(JNIEnv *env, jarray array, void *carray, jint mode))
   JNIWrapper("ReleasePrimitiveArrayCritical");
   HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_ENTRY(env, array, carray, mode);
-  // The array, carray and mode arguments are ignored
-  GCLocker::unlock_critical(thread);
+  oop a = JNIHandles::resolve_non_null(array);
+  Universe::heap()->unpin_object(thread, a);
 HOTSPOT_JNI_RELEASEPRIMITIVEARRAYCRITICAL_RETURN();
 JNI_END
 
@@ -3179,8 +3178,8 @@
 JNI_ENTRY(const jchar*, jni_GetStringCritical(JNIEnv *env, jstring string, jboolean *isCopy))
   JNIWrapper("GetStringCritical");
   HOTSPOT_JNI_GETSTRINGCRITICAL_ENTRY(env, string, (uintptr_t *) isCopy);
-  GCLocker::lock_critical(thread);
   oop s = JNIHandles::resolve_non_null(string);
+  s = Universe::heap()->pin_object(thread, s);
   typeArrayOop s_value = java_lang_String::value(s);
   bool is_latin1 = java_lang_String::is_latin1(s);
   if (isCopy != NULL) {
@@ -3217,7 +3216,7 @@
     // This assumes that ReleaseStringCritical bookends GetStringCritical.
     FREE_C_HEAP_ARRAY(jchar, chars);
   }
-  GCLocker::unlock_critical(thread);
+  Universe::heap()->unpin_object(thread, s);
 HOTSPOT_JNI_RELEASESTRINGCRITICAL_RETURN();
 JNI_END