src/share/vm/prims/unsafe.cpp

Print this page
rev 2242 : [mq]: reflection-unsafe-read-barrier

@@ -191,11 +191,40 @@
 // The xxx140 variants for backward compatibility do not allow a full-width offset.
 UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset))
   UnsafeWrapper("Unsafe_GetObject");
   if (obj == NULL)  THROW_0(vmSymbols::java_lang_NullPointerException());
   GET_OOP_FIELD(obj, offset, v)
-  return JNIHandles::make_local(env, v);
+  jobject ret = JNIHandles::make_local(env, v);
+#ifndef SERIALGC
+  // We could be accessing the the referent field in a reference
+  // object. If G1 is enabled then we need to register the
+  // referent with the SATB barrier.
+  if (UseG1GC) {
+    bool needs_barrier = false;
+    oop o = JNIHandles::resolve_non_null(obj);
+
+    if (offset == java_lang_ref_Reference::referent_offset) {
+      klassOop k = o->klass();
+      if (instanceKlass::cast(k)->reference_type() != REF_NONE) {
+        assert(instanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity");
+        needs_barrier = true;
+      }
+    }
+    
+    if (needs_barrier) {
+      BarrierSet* bs = Universe::heap()->barrier_set();
+      if (UseCompressedOops) {
+        bs->write_ref_field_pre((narrowOop*)index_oop_from_field_offset_long(o, offset), 
+                                JNIHandles::resolve(ret));
+      } else { 
+        bs->write_ref_field_pre((oop*)index_oop_from_field_offset_long(o, offset),
+                                JNIHandles::resolve(ret));
+      }
+    }
+  }
+#endif // SERIALGC
+  return ret;
 UNSAFE_END
 
 UNSAFE_ENTRY(void, Unsafe_SetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jobject x_h))
   UnsafeWrapper("Unsafe_SetObject");
   if (obj == NULL)  THROW(vmSymbols::java_lang_NullPointerException());

@@ -223,12 +252,42 @@
 // The normal variants allow a null base pointer with an arbitrary address.
 // But if the base pointer is non-null, the offset should make some sense.
 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
 UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
   UnsafeWrapper("Unsafe_GetObject");
+  tty->print_cr("####### Unsafe_GetObject: offset = " INTX_FORMAT, offset);
   GET_OOP_FIELD(obj, offset, v)
-  return JNIHandles::make_local(env, v);
+  jobject ret = JNIHandles::make_local(env, v);
+#ifndef SERIALGC
+  // We could be accessing the referent field in a reference
+  // object. If G1 is enabled then we need to register the
+  // referent with the SATB barrier.
+  if (UseG1GC) {
+    bool needs_barrier = false;
+    oop o = JNIHandles::resolve(obj);
+
+    if (offset == java_lang_ref_Reference::referent_offset && o != NULL) {
+      klassOop k = o->klass();
+      if (instanceKlass::cast(k)->reference_type() != REF_NONE) {
+        assert(instanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity");        tty->print_cr("####### Unsafe_GetObject: need a G1 barrier");
+        needs_barrier = true;
+      }
+    }
+    
+    if (needs_barrier) {
+      BarrierSet* bs = Universe::heap()->barrier_set();
+      if (UseCompressedOops) {
+        bs->write_ref_field_pre((narrowOop*)index_oop_from_field_offset_long(o, offset),
+                                JNIHandles::resolve(ret));
+      } else { 
+        bs->write_ref_field_pre((oop*)index_oop_from_field_offset_long(o, offset),
+                                JNIHandles::resolve(ret));
+      }
+    }
+  }
+#endif // SERIALGC
+  return ret;
 UNSAFE_END
 
 UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
   UnsafeWrapper("Unsafe_SetObject");
   oop x = JNIHandles::resolve(x_h);