< prev index next >

src/share/vm/prims/unsafe.cpp

Print this page

        

@@ -27,10 +27,11 @@
 #include "memory/allocation.inline.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/jni.h"
 #include "prims/jvm.h"
+#include "prims/unsafe.hpp"
 #include "runtime/atomic.inline.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/reflection.hpp"

@@ -38,10 +39,11 @@
 #include "services/threadService.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/macros.hpp"
+#include "code/dependencies.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
 #endif // INCLUDE_ALL_GCS
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC

@@ -72,11 +74,10 @@
 
 #define UNSAFE_END JVM_END
 
 #define UnsafeWrapper(arg) /*nothing, for the present*/
 
-
 inline void* addr_from_java(jlong addr) {
   // This assert fails in a variety of ways on 32-bit systems.
   // It is impossible to predict whether native code that converts
   // pointers to longs will sign-extend or zero-extend the addresses.
   //assert(addr == (uintptr_t)addr, "must not be odd high bits");

@@ -86,39 +87,17 @@
 inline jlong addr_to_java(void* p) {
   assert(p == (void*)(uintptr_t)p, "must not be odd high bits");
   return (uintptr_t)p;
 }
 
-
-// Note: The VM's obj_field and related accessors use byte-scaled
-// ("unscaled") offsets, just as the unsafe methods do.
-
-// However, the method Unsafe.fieldOffset explicitly declines to
-// guarantee this.  The field offset values manipulated by the Java user
-// through the Unsafe API are opaque cookies that just happen to be byte
-// offsets.  We represent this state of affairs by passing the cookies
-// through conversion functions when going between the VM and the Unsafe API.
-// The conversion functions just happen to be no-ops at present.
-
-inline jlong field_offset_to_byte_offset(jlong field_offset) {
-  return field_offset;
-}
-
-inline jlong field_offset_from_byte_offset(jlong byte_offset) {
-  return byte_offset;
-}
-
-inline jint invocation_key_from_method_slot(jint slot) {
-  return slot;
-}
-
-inline jint invocation_key_to_method_slot(jint key) {
-  return key;
-}
-
 inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
-  jlong byte_offset = field_offset_to_byte_offset(field_offset);
+  jlong byte_offset = 0;
+  if (oopDesc::is_null(p)) {
+    byte_offset = field_offset;
+  } else {
+    byte_offset = Unsafe::field_offset_to_byte_offset(field_offset);
+  }
 #ifdef ASSERT
   if (p != NULL) {
     assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");
     if (byte_offset == (jint)byte_offset) {
       void* ptr_plus_disp = (address)p + byte_offset;

@@ -133,33 +112,31 @@
     return (address)p + (jint) byte_offset;
   else
     return (address)p +        byte_offset;
 }
 
-// Externally callable versions:
-// (Use these in compiler intrinsics which emulate unsafe primitives.)
-jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
-  return field_offset;
-}
-jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
-  return byte_offset;
-}
-jint Unsafe_invocation_key_from_method_slot(jint slot) {
-  return invocation_key_from_method_slot(slot);
-}
-jint Unsafe_invocation_key_to_method_slot(jint key) {
-  return invocation_key_to_method_slot(key);
+static void check_final_field(jobject obj, jlong field_offset, TRAPS) {
+  if (TrustFinalNonStaticFields &&
+      (field_offset & Unsafe::final_mask) != 0) {
+    Handle recv(THREAD, JNIHandles::resolve(obj));
+    if (!recv.is_null()) {
+      instanceKlassHandle ctxk(THREAD, InstanceKlass::cast(recv->klass()));
+      jlong byte_offset = Unsafe::field_offset_to_byte_offset(field_offset);
+      ConstantFieldDepChange changes(recv, byte_offset);
+      Dependencies::invalidate_dependent_nmethods(ctxk, changes, THREAD);
+    }
+  }
 }
 
-
 ///// Data in the Java heap.
 
 #define GET_FIELD(obj, offset, type_name, v) \
   oop p = JNIHandles::resolve(obj); \
   type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
 
 #define SET_FIELD(obj, offset, type_name, x) \
+  check_final_field(obj, offset, THREAD); \
   oop p = JNIHandles::resolve(obj); \
   *(type_name*)index_oop_from_field_offset_long(p, offset) = x
 
 #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
   oop p = JNIHandles::resolve(obj); \

@@ -167,10 +144,11 @@
     OrderAccess::fence(); \
   } \
   volatile type_name v = OrderAccess::load_acquire((volatile type_name*)index_oop_from_field_offset_long(p, offset));
 
 #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
+  check_final_field(obj, offset, THREAD); \
   oop p = JNIHandles::resolve(obj); \
   OrderAccess::release_store_fence((volatile type_name*)index_oop_from_field_offset_long(p, offset), x);
 
 
 // Get/SetObject must be special-cased, since it works with handles.

@@ -216,10 +194,11 @@
   return ret;
 UNSAFE_END
 
 UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
   UnsafeWrapper("Unsafe_SetObject");
+  check_final_field(obj, offset, THREAD);
   oop x = JNIHandles::resolve(x_h);
   oop p = JNIHandles::resolve(obj);
   if (UseCompressedOops) {
     oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
   } else {

@@ -242,10 +221,11 @@
   return JNIHandles::make_local(env, v);
 UNSAFE_END
 
 UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
   UnsafeWrapper("Unsafe_SetObjectVolatile");
+  check_final_field(obj, offset, THREAD);
   oop x = JNIHandles::resolve(x_h);
   oop p = JNIHandles::resolve(obj);
   void* addr = index_oop_from_field_offset_long(p, offset);
   OrderAccess::release();
   if (UseCompressedOops) {

@@ -695,11 +675,12 @@
       THROW_0(vmSymbols::java_lang_IllegalArgumentException());
     }
   }
 
   int offset = InstanceKlass::cast(k)->field_offset(slot);
-  return field_offset_from_byte_offset(offset);
+  bool is_final = (modifiers & JVM_ACC_FINAL) != 0;
+  return Unsafe::field_offset_from_byte_offset(offset, is_final);
 }
 
 UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
   UnsafeWrapper("Unsafe_ObjectFieldOffset");
   return find_field_offset(field, 0, THREAD);

@@ -785,11 +766,11 @@
 
 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls))
   UnsafeWrapper("Unsafe_ArrayBaseOffset");
   int base, scale;
   getBaseAndScale(base, scale, acls, CHECK_0);
-  return field_offset_from_byte_offset(base);
+  return Unsafe::field_offset_from_byte_offset(base);
 UNSAFE_END
 
 
 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls))
   UnsafeWrapper("Unsafe_ArrayIndexScale");

@@ -807,11 +788,11 @@
   // // Code for unpacked fields:
   // if (scale < wordSize)  return 0;
 
   // The following allows for a pretty general fieldOffset cookie scheme,
   // but requires it to be linear in byte offset.
-  return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
+  return Unsafe::field_offset_from_byte_offset(scale) - Unsafe::field_offset_from_byte_offset(0);
 UNSAFE_END
 
 
 static inline void throw_new(JNIEnv *env, const char *ename) {
   char buf[100];

@@ -1197,11 +1178,10 @@
     case 1: a->double_at_put(0, (jdouble)la[0]); break;
   }
   return ret;
 UNSAFE_END
 
-
 /// JVM_RegisterUnsafeMethods
 
 #define ADR "J"
 
 #define LANG "Ljava/lang/"
< prev index next >