< prev index next >
src/share/vm/prims/unsafe.cpp
Print this page
*** 27,36 ****
--- 27,37 ----
#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,47 ****
--- 39,49 ----
#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,82 ****
#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");
--- 74,83 ----
*** 86,124 ****
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);
#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;
--- 87,103 ----
inline jlong addr_to_java(void* p) {
assert(p == (void*)(uintptr_t)p, "must not be odd high bits");
return (uintptr_t)p;
}
inline void* index_oop_from_field_offset_long(oop p, jlong 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,165 ****
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);
}
-
///// 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) \
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); \
--- 112,142 ----
return (address)p + (jint) byte_offset;
else
return (address)p + byte_offset;
}
! 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,176 ****
--- 144,154 ----
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,225 ****
--- 194,204 ----
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,251 ****
--- 221,231 ----
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,705 ****
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
}
int offset = InstanceKlass::cast(k)->field_offset(slot);
! return field_offset_from_byte_offset(offset);
}
UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
UnsafeWrapper("Unsafe_ObjectFieldOffset");
return find_field_offset(field, 0, THREAD);
--- 675,686 ----
THROW_0(vmSymbols::java_lang_IllegalArgumentException());
}
}
int offset = InstanceKlass::cast(k)->field_offset(slot);
! 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,795 ****
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);
UNSAFE_END
UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls))
UnsafeWrapper("Unsafe_ArrayIndexScale");
--- 766,776 ----
UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls))
UnsafeWrapper("Unsafe_ArrayBaseOffset");
int base, scale;
getBaseAndScale(base, scale, acls, CHECK_0);
! 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,817 ****
// // 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);
UNSAFE_END
static inline void throw_new(JNIEnv *env, const char *ename) {
char buf[100];
--- 788,798 ----
// // 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 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,1207 ****
case 1: a->double_at_put(0, (jdouble)la[0]); break;
}
return ret;
UNSAFE_END
-
/// JVM_RegisterUnsafeMethods
#define ADR "J"
#define LANG "Ljava/lang/"
--- 1178,1187 ----
< prev index next >