17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/classFileStream.hpp"
27 #include "classfile/classLoader.hpp"
28 #include "classfile/classLoadInfo.hpp"
29 #include "classfile/javaClasses.inline.hpp"
30 #include "classfile/systemDictionary.hpp"
31 #include "classfile/vmSymbols.hpp"
32 #include "jfr/jfrEvents.hpp"
33 #include "jni.h"
34 #include "jvm.h"
35 #include "memory/allocation.inline.hpp"
36 #include "memory/resourceArea.hpp"
37 #include "oops/access.inline.hpp"
38 #include "oops/fieldStreams.inline.hpp"
39 #include "oops/instanceKlass.inline.hpp"
40 #include "oops/klass.inline.hpp"
41 #include "oops/objArrayOop.inline.hpp"
42 #include "oops/oop.inline.hpp"
43 #include "oops/typeArrayOop.inline.hpp"
44 #include "prims/jvmtiExport.hpp"
45 #include "prims/unsafe.hpp"
46 #include "runtime/globals.hpp"
47 #include "runtime/handles.inline.hpp"
48 #include "runtime/interfaceSupport.inline.hpp"
49 #include "runtime/javaThread.inline.hpp"
50 #include "runtime/jniHandles.inline.hpp"
51 #include "runtime/orderAccess.hpp"
52 #include "runtime/reflection.hpp"
53 #include "runtime/sharedRuntime.hpp"
54 #include "runtime/stubRoutines.hpp"
55 #include "runtime/threadSMR.hpp"
56 #include "runtime/vmOperations.hpp"
57 #include "runtime/vm_version.hpp"
58 #include "services/threadService.hpp"
59 #include "utilities/align.hpp"
60 #include "utilities/copy.hpp"
61 #include "utilities/dtrace.hpp"
62 #include "utilities/macros.hpp"
63
64 /**
65 * Implementation of the jdk.internal.misc.Unsafe class
132 static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
133 assert_field_offset_sane(p, field_offset);
134 jlong byte_offset = field_offset_to_byte_offset(field_offset);
135
136 if (sizeof(char*) == sizeof(jint)) { // (this constant folds!)
137 return cast_from_oop<address>(p) + (jint) byte_offset;
138 } else {
139 return cast_from_oop<address>(p) + byte_offset;
140 }
141 }
142
143 // Externally callable versions:
144 // (Use these in compiler intrinsics which emulate unsafe primitives.)
145 jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
146 return field_offset;
147 }
148 jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
149 return byte_offset;
150 }
151
152
153 ///// Data read/writes on the Java heap and in native (off-heap) memory
154
155 /**
156 * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
157 */
158 class GuardUnsafeAccess {
159 JavaThread* _thread;
160
161 public:
162 GuardUnsafeAccess(JavaThread* thread) : _thread(thread) {
163 // native/off-heap access which may raise SIGBUS if accessing
164 // memory mapped file data in a region of the file which has
165 // been truncated and is now invalid.
166 _thread->set_doing_unsafe_access(true);
167 }
168
169 ~GuardUnsafeAccess() {
170 _thread->set_doing_unsafe_access(false);
171 }
172 };
208 return x;
209 }
210
211 jboolean normalize_for_read(jboolean x) {
212 return x != 0;
213 }
214
215 public:
216 MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
217 : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
218 assert_field_offset_sane(_obj, offset);
219 }
220
221 T get() {
222 GuardUnsafeAccess guard(_thread);
223 return normalize_for_read(*addr());
224 }
225
226 void put(T x) {
227 GuardUnsafeAccess guard(_thread);
228 *addr() = normalize_for_write(x);
229 }
230
231
232 T get_volatile() {
233 GuardUnsafeAccess guard(_thread);
234 volatile T ret = RawAccess<MO_SEQ_CST>::load(addr());
235 return normalize_for_read(ret);
236 }
237
238 void put_volatile(T x) {
239 GuardUnsafeAccess guard(_thread);
240 RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
241 }
242 };
243
244 // These functions allow a null base pointer with an arbitrary address.
245 // But if the base pointer is non-null, the offset should make some sense.
246 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
247 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
248 oop p = JNIHandles::resolve(obj);
249 assert_field_offset_sane(p, offset);
250 oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
251 return JNIHandles::make_local(THREAD, v);
252 } UNSAFE_END
253
254 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
255 oop x = JNIHandles::resolve(x_h);
256 oop p = JNIHandles::resolve(obj);
257 assert_field_offset_sane(p, offset);
258 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
259 } UNSAFE_END
260
261 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
262 oop p = JNIHandles::resolve(obj);
263 assert_field_offset_sane(p, offset);
264 oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
265 return JNIHandles::make_local(THREAD, v);
266 } UNSAFE_END
267
268 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
269 oop x = JNIHandles::resolve(x_h);
270 oop p = JNIHandles::resolve(obj);
271 assert_field_offset_sane(p, offset);
272 HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
273 } UNSAFE_END
274
275 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
276 oop v = *(oop*) (address) addr;
277 return JNIHandles::make_local(THREAD, v);
278 } UNSAFE_END
279
280 #define DEFINE_GETSETOOP(java_type, Type) \
573 return false;
574 }
575 UNSAFE_END
576
577 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
578 assert(clazz != nullptr, "clazz must not be null");
579
580 oop mirror = JNIHandles::resolve_non_null(clazz);
581 Klass* k = java_lang_Class::as_Klass(mirror);
582
583 if (k == nullptr || !k->is_array_klass()) {
584 THROW(vmSymbols::java_lang_InvalidClassException());
585 } else if (k->is_objArray_klass()) {
586 base = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
587 scale = heapOopSize;
588 } else if (k->is_typeArray_klass()) {
589 TypeArrayKlass* tak = TypeArrayKlass::cast(k);
590 base = tak->array_header_in_bytes();
591 assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
592 scale = (1 << tak->log2_element_size());
593 } else {
594 ShouldNotReachHere();
595 }
596 }
597
598 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
599 int base = 0, scale = 0;
600 getBaseAndScale(base, scale, clazz, CHECK_0);
601
602 return field_offset_from_byte_offset(base);
603 } UNSAFE_END
604
605
606 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
607 int base = 0, scale = 0;
608 getBaseAndScale(base, scale, clazz, CHECK_0);
609
610 // This VM packs both fields and array elements down to the byte.
611 // But watch out: If this changes, so that array references for
612 // a given primitive type (say, T_BOOLEAN) use different memory units
613 // than fields, this method MUST return zero for such arrays.
614 // For example, the VM used to store sub-word sized fields in full
615 // words in the object layout, so that accessors like getByte(Object,int)
616 // did not really do what one might expect for arrays. Therefore,
617 // this function used to report a zero scale factor, so that the user
618 // would know not to attempt to access sub-word array elements.
619 // // Code for unpacked fields:
620 // if (scale < wordSize) return 0;
621
622 // The following allows for a pretty general fieldOffset cookie scheme,
623 // but requires it to be linear in byte offset.
624 return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
625 } UNSAFE_END
626
627
628 static inline void throw_new(JNIEnv *env, const char *ename) {
629 jclass cls = env->FindClass(ename);
630 if (env->ExceptionCheck()) {
631 env->ExceptionClear();
632 tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", ename);
633 return;
634 }
635
636 env->ThrowNew(cls, nullptr);
637 }
638
639 static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
640 // Code lifted from JDK 1.3 ClassLoader.c
641
642 jbyte *body;
643 char *utfName = nullptr;
644 jclass result = 0;
645 char buf[128];
646
647 assert(data != nullptr, "Class bytes must not be null");
827
828
829 /// JVM_RegisterUnsafeMethods
830
831 #define ADR "J"
832
833 #define LANG "Ljava/lang/"
834
835 #define OBJ LANG "Object;"
836 #define CLS LANG "Class;"
837 #define FLD LANG "reflect/Field;"
838 #define THR LANG "Throwable;"
839
840 #define DC_Args LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
841 #define DAC_Args CLS "[B[" OBJ
842
843 #define CC (char*) /*cast a literal from (const char*)*/
844 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
845
846 #define DECLARE_GETPUTOOP(Type, Desc) \
847 {CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \
848 {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type)}, \
849 {CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \
850 {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type##Volatile)}
851
852
853 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
854 {CC "getReference", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetReference)},
855 {CC "putReference", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReference)},
856 {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ, FN_PTR(Unsafe_GetReferenceVolatile)},
857 {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReferenceVolatile)},
858
859 {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)},
860
861 DECLARE_GETPUTOOP(Boolean, Z),
862 DECLARE_GETPUTOOP(Byte, B),
863 DECLARE_GETPUTOOP(Short, S),
864 DECLARE_GETPUTOOP(Char, C),
865 DECLARE_GETPUTOOP(Int, I),
866 DECLARE_GETPUTOOP(Long, J),
867 DECLARE_GETPUTOOP(Float, F),
868 DECLARE_GETPUTOOP(Double, D),
869
870 {CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)},
871 {CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)},
872 {CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)},
873
874 {CC "objectFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset0)},
875 {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
876 {CC "staticFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset0)},
877 {CC "staticFieldBase0", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBase0)},
878 {CC "ensureClassInitialized0", CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized0)},
879 {CC "arrayBaseOffset0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset0)},
880 {CC "arrayIndexScale0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale0)},
881
882 {CC "defineClass0", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass0)},
883 {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)},
884 {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)},
885 {CC "compareAndSetReference",CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSetReference)},
886 {CC "compareAndSetInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSetInt)},
887 {CC "compareAndSetLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSetLong)},
888 {CC "compareAndExchangeReference", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeReference)},
889 {CC "compareAndExchangeInt", CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
890 {CC "compareAndExchangeLong", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
891
892 {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)},
893 {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)},
894
895 {CC "getLoadAverage0", CC "([DI)I", FN_PTR(Unsafe_GetLoadAverage0)},
896
897 {CC "copyMemory0", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
898 {CC "copySwapMemory0", CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
899 {CC "writeback0", CC "(" "J" ")V", FN_PTR(Unsafe_WriteBack0)},
900 {CC "writebackPreSync0", CC "()V", FN_PTR(Unsafe_WriteBackPreSync0)},
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/classFileStream.hpp"
27 #include "classfile/classLoader.hpp"
28 #include "classfile/classLoadInfo.hpp"
29 #include "classfile/javaClasses.inline.hpp"
30 #include "classfile/systemDictionary.hpp"
31 #include "classfile/vmSymbols.hpp"
32 #include "jfr/jfrEvents.hpp"
33 #include "jni.h"
34 #include "jvm.h"
35 #include "memory/allocation.inline.hpp"
36 #include "memory/resourceArea.hpp"
37 #include "logging/log.hpp"
38 #include "logging/logStream.hpp"
39 #include "oops/access.inline.hpp"
40 #include "oops/fieldStreams.inline.hpp"
41 #include "oops/flatArrayKlass.hpp"
42 #include "oops/flatArrayOop.inline.hpp"
43 #include "oops/inlineKlass.inline.hpp"
44 #include "oops/instanceKlass.inline.hpp"
45 #include "oops/klass.inline.hpp"
46 #include "oops/objArrayOop.inline.hpp"
47 #include "oops/oop.inline.hpp"
48 #include "oops/typeArrayOop.inline.hpp"
49 #include "prims/jvmtiExport.hpp"
50 #include "prims/unsafe.hpp"
51 #include "runtime/fieldDescriptor.inline.hpp"
52 #include "runtime/globals.hpp"
53 #include "runtime/handles.inline.hpp"
54 #include "runtime/interfaceSupport.inline.hpp"
55 #include "runtime/javaThread.inline.hpp"
56 #include "runtime/jniHandles.inline.hpp"
57 #include "runtime/orderAccess.hpp"
58 #include "runtime/reflection.hpp"
59 #include "runtime/sharedRuntime.hpp"
60 #include "runtime/stubRoutines.hpp"
61 #include "runtime/threadSMR.hpp"
62 #include "runtime/vmOperations.hpp"
63 #include "runtime/vm_version.hpp"
64 #include "services/threadService.hpp"
65 #include "utilities/align.hpp"
66 #include "utilities/copy.hpp"
67 #include "utilities/dtrace.hpp"
68 #include "utilities/macros.hpp"
69
70 /**
71 * Implementation of the jdk.internal.misc.Unsafe class
138 static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
139 assert_field_offset_sane(p, field_offset);
140 jlong byte_offset = field_offset_to_byte_offset(field_offset);
141
142 if (sizeof(char*) == sizeof(jint)) { // (this constant folds!)
143 return cast_from_oop<address>(p) + (jint) byte_offset;
144 } else {
145 return cast_from_oop<address>(p) + byte_offset;
146 }
147 }
148
149 // Externally callable versions:
150 // (Use these in compiler intrinsics which emulate unsafe primitives.)
151 jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
152 return field_offset;
153 }
154 jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
155 return byte_offset;
156 }
157
158 ///// Data read/writes on the Java heap and in native (off-heap) memory
159
160 /**
161 * Helper class to wrap memory accesses in JavaThread::doing_unsafe_access()
162 */
163 class GuardUnsafeAccess {
164 JavaThread* _thread;
165
166 public:
167 GuardUnsafeAccess(JavaThread* thread) : _thread(thread) {
168 // native/off-heap access which may raise SIGBUS if accessing
169 // memory mapped file data in a region of the file which has
170 // been truncated and is now invalid.
171 _thread->set_doing_unsafe_access(true);
172 }
173
174 ~GuardUnsafeAccess() {
175 _thread->set_doing_unsafe_access(false);
176 }
177 };
213 return x;
214 }
215
216 jboolean normalize_for_read(jboolean x) {
217 return x != 0;
218 }
219
220 public:
221 MemoryAccess(JavaThread* thread, jobject obj, jlong offset)
222 : _thread(thread), _obj(JNIHandles::resolve(obj)), _offset((ptrdiff_t)offset) {
223 assert_field_offset_sane(_obj, offset);
224 }
225
226 T get() {
227 GuardUnsafeAccess guard(_thread);
228 return normalize_for_read(*addr());
229 }
230
231 void put(T x) {
232 GuardUnsafeAccess guard(_thread);
233 assert(_obj == NULL || !_obj->is_inline_type() || _obj->mark().is_larval_state(), "must be an object instance or a larval inline type");
234 *addr() = normalize_for_write(x);
235 }
236
237 T get_volatile() {
238 GuardUnsafeAccess guard(_thread);
239 volatile T ret = RawAccess<MO_SEQ_CST>::load(addr());
240 return normalize_for_read(ret);
241 }
242
243 void put_volatile(T x) {
244 GuardUnsafeAccess guard(_thread);
245 RawAccess<MO_SEQ_CST>::store(addr(), normalize_for_write(x));
246 }
247 };
248
249 #ifdef ASSERT
250 /*
251 * Get the field descriptor of the field of the given object at the given offset.
252 */
253 static bool get_field_descriptor(oop p, jlong offset, fieldDescriptor* fd) {
254 bool found = false;
255 Klass* k = p->klass();
256 if (k->is_instance_klass()) {
257 InstanceKlass* ik = InstanceKlass::cast(k);
258 found = ik->find_field_from_offset((int)offset, false, fd);
259 if (!found && ik->is_mirror_instance_klass()) {
260 Klass* k2 = java_lang_Class::as_Klass(p);
261 if (k2->is_instance_klass()) {
262 ik = InstanceKlass::cast(k2);
263 found = ik->find_field_from_offset((int)offset, true, fd);
264 }
265 }
266 }
267 return found;
268 }
269 #endif // ASSERT
270
271 static void assert_and_log_unsafe_value_access(oop p, jlong offset, InlineKlass* vk) {
272 Klass* k = p->klass();
273 #ifdef ASSERT
274 if (k->is_instance_klass()) {
275 assert_field_offset_sane(p, offset);
276 fieldDescriptor fd;
277 bool found = get_field_descriptor(p, offset, &fd);
278 if (found) {
279 assert(found, "value field not found");
280 assert(fd.is_inlined(), "field not flat");
281 } else {
282 if (log_is_enabled(Trace, valuetypes)) {
283 log_trace(valuetypes)("not a field in %s at offset " UINT64_FORMAT_X,
284 p->klass()->external_name(), (uint64_t)offset);
285 }
286 }
287 } else if (k->is_flatArray_klass()) {
288 FlatArrayKlass* vak = FlatArrayKlass::cast(k);
289 int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
290 address dest = (address)((flatArrayOop)p)->value_at_addr(index, vak->layout_helper());
291 assert(dest == (cast_from_oop<address>(p) + offset), "invalid offset");
292 } else {
293 ShouldNotReachHere();
294 }
295 #endif // ASSERT
296 if (log_is_enabled(Trace, valuetypes)) {
297 if (k->is_flatArray_klass()) {
298 FlatArrayKlass* vak = FlatArrayKlass::cast(k);
299 int index = (offset - vak->array_header_in_bytes()) / vak->element_byte_size();
300 address dest = (address)((flatArrayOop)p)->value_at_addr(index, vak->layout_helper());
301 log_trace(valuetypes)("%s array type %s index %d element size %d offset " UINT64_FORMAT_X " at " INTPTR_FORMAT,
302 p->klass()->external_name(), vak->external_name(),
303 index, vak->element_byte_size(), (uint64_t)offset, p2i(dest));
304 } else {
305 log_trace(valuetypes)("%s field type %s at offset " UINT64_FORMAT_X,
306 p->klass()->external_name(), vk->external_name(), (uint64_t)offset);
307 }
308 }
309 }
310
311 // These functions allow a null base pointer with an arbitrary address.
312 // But if the base pointer is non-null, the offset should make some sense.
313 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
314 UNSAFE_ENTRY(jobject, Unsafe_GetReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
315 oop p = JNIHandles::resolve(obj);
316 assert_field_offset_sane(p, offset);
317 oop v = HeapAccess<ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
318 return JNIHandles::make_local(THREAD, v);
319 } UNSAFE_END
320
321 UNSAFE_ENTRY(void, Unsafe_PutReference(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
322 oop x = JNIHandles::resolve(x_h);
323 oop p = JNIHandles::resolve(obj);
324 assert_field_offset_sane(p, offset);
325 assert(!p->is_inline_type() || p->mark().is_larval_state(), "must be an object instance or a larval inline type");
326 HeapAccess<ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
327 } UNSAFE_END
328
329 UNSAFE_ENTRY(jlong, Unsafe_ValueHeaderSize(JNIEnv *env, jobject unsafe, jclass c)) {
330 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
331 InlineKlass* vk = InlineKlass::cast(k);
332 return vk->first_field_offset();
333 } UNSAFE_END
334
335 UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedField(JNIEnv *env, jobject unsafe, jobject o)) {
336 oop f = JNIHandles::resolve_non_null(o);
337 Klass* k = java_lang_Class::as_Klass(java_lang_reflect_Field::clazz(f));
338 int slot = java_lang_reflect_Field::slot(f);
339 return InstanceKlass::cast(k)->field_is_inlined(slot);
340 } UNSAFE_END
341
342 UNSAFE_ENTRY(jboolean, Unsafe_IsFlattenedArray(JNIEnv *env, jobject unsafe, jclass c)) {
343 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c));
344 return k->is_flatArray_klass();
345 } UNSAFE_END
346
347 UNSAFE_ENTRY(jobject, Unsafe_UninitializedDefaultValue(JNIEnv *env, jobject unsafe, jclass vc)) {
348 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));
349 InlineKlass* vk = InlineKlass::cast(k);
350 oop v = vk->default_value();
351 return JNIHandles::make_local(THREAD, v);
352 } UNSAFE_END
353
354 UNSAFE_ENTRY(jobject, Unsafe_GetValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc)) {
355 oop base = JNIHandles::resolve(obj);
356 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));
357 InlineKlass* vk = InlineKlass::cast(k);
358 assert_and_log_unsafe_value_access(base, offset, vk);
359 Handle base_h(THREAD, base);
360 oop v = vk->read_inlined_field(base_h(), offset, CHECK_NULL);
361 return JNIHandles::make_local(THREAD, v);
362 } UNSAFE_END
363
364 UNSAFE_ENTRY(void, Unsafe_PutValue(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jclass vc, jobject value)) {
365 oop base = JNIHandles::resolve(obj);
366 Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(vc));
367 InlineKlass* vk = InlineKlass::cast(k);
368 assert(!base->is_inline_type() || base->mark().is_larval_state(), "must be an object instance or a larval inline type");
369 assert_and_log_unsafe_value_access(base, offset, vk);
370 oop v = JNIHandles::resolve(value);
371 vk->write_inlined_field(base, offset, v, CHECK);
372 } UNSAFE_END
373
374 UNSAFE_ENTRY(jobject, Unsafe_MakePrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) {
375 oop v = JNIHandles::resolve_non_null(value);
376 assert(v->is_inline_type(), "must be an inline type instance");
377 Handle vh(THREAD, v);
378 InlineKlass* vk = InlineKlass::cast(v->klass());
379 instanceOop new_value = vk->allocate_instance_buffer(CHECK_NULL);
380 vk->inline_copy_oop_to_new_oop(vh(), new_value);
381 markWord mark = new_value->mark();
382 new_value->set_mark(mark.enter_larval_state());
383 return JNIHandles::make_local(THREAD, new_value);
384 } UNSAFE_END
385
386 UNSAFE_ENTRY(jobject, Unsafe_FinishPrivateBuffer(JNIEnv *env, jobject unsafe, jobject value)) {
387 oop v = JNIHandles::resolve(value);
388 assert(v->mark().is_larval_state(), "must be a larval value");
389 markWord mark = v->mark();
390 v->set_mark(mark.exit_larval_state());
391 return JNIHandles::make_local(THREAD, v);
392 } UNSAFE_END
393
394 UNSAFE_ENTRY(jobject, Unsafe_GetReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) {
395 oop p = JNIHandles::resolve(obj);
396 assert_field_offset_sane(p, offset);
397 oop v = HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_load_at(p, offset);
398 return JNIHandles::make_local(THREAD, v);
399 } UNSAFE_END
400
401 UNSAFE_ENTRY(void, Unsafe_PutReferenceVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) {
402 oop x = JNIHandles::resolve(x_h);
403 oop p = JNIHandles::resolve(obj);
404 assert_field_offset_sane(p, offset);
405 HeapAccess<MO_SEQ_CST | ON_UNKNOWN_OOP_REF>::oop_store_at(p, offset, x);
406 } UNSAFE_END
407
408 UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) {
409 oop v = *(oop*) (address) addr;
410 return JNIHandles::make_local(THREAD, v);
411 } UNSAFE_END
412
413 #define DEFINE_GETSETOOP(java_type, Type) \
706 return false;
707 }
708 UNSAFE_END
709
710 static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) {
711 assert(clazz != nullptr, "clazz must not be null");
712
713 oop mirror = JNIHandles::resolve_non_null(clazz);
714 Klass* k = java_lang_Class::as_Klass(mirror);
715
716 if (k == nullptr || !k->is_array_klass()) {
717 THROW(vmSymbols::java_lang_InvalidClassException());
718 } else if (k->is_objArray_klass()) {
719 base = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
720 scale = heapOopSize;
721 } else if (k->is_typeArray_klass()) {
722 TypeArrayKlass* tak = TypeArrayKlass::cast(k);
723 base = tak->array_header_in_bytes();
724 assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
725 scale = (1 << tak->log2_element_size());
726 } else if (k->is_flatArray_klass()) {
727 FlatArrayKlass* vak = FlatArrayKlass::cast(k);
728 InlineKlass* vklass = vak->element_klass();
729 base = vak->array_header_in_bytes();
730 scale = vak->element_byte_size();
731 } else {
732 ShouldNotReachHere();
733 }
734 }
735
736 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) {
737 int base = 0, scale = 0;
738 getBaseAndScale(base, scale, clazz, CHECK_0);
739
740 return field_offset_from_byte_offset(base);
741 } UNSAFE_END
742
743
744 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) {
745 int base = 0, scale = 0;
746 getBaseAndScale(base, scale, clazz, CHECK_0);
747
748 // This VM packs both fields and array elements down to the byte.
749 // But watch out: If this changes, so that array references for
750 // a given primitive type (say, T_BOOLEAN) use different memory units
751 // than fields, this method MUST return zero for such arrays.
752 // For example, the VM used to store sub-word sized fields in full
753 // words in the object layout, so that accessors like getByte(Object,int)
754 // did not really do what one might expect for arrays. Therefore,
755 // this function used to report a zero scale factor, so that the user
756 // would know not to attempt to access sub-word array elements.
757 // // Code for unpacked fields:
758 // if (scale < wordSize) return 0;
759
760 // The following allows for a pretty general fieldOffset cookie scheme,
761 // but requires it to be linear in byte offset.
762 return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
763 } UNSAFE_END
764
765
766 UNSAFE_ENTRY(jlong, Unsafe_GetObjectSize0(JNIEnv* env, jobject o, jobject obj))
767 oop p = JNIHandles::resolve(obj);
768 return p->size() * HeapWordSize;
769 UNSAFE_END
770
771
772 static inline void throw_new(JNIEnv *env, const char *ename) {
773 jclass cls = env->FindClass(ename);
774 if (env->ExceptionCheck()) {
775 env->ExceptionClear();
776 tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", ename);
777 return;
778 }
779
780 env->ThrowNew(cls, nullptr);
781 }
782
783 static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
784 // Code lifted from JDK 1.3 ClassLoader.c
785
786 jbyte *body;
787 char *utfName = nullptr;
788 jclass result = 0;
789 char buf[128];
790
791 assert(data != nullptr, "Class bytes must not be null");
971
972
973 /// JVM_RegisterUnsafeMethods
974
975 #define ADR "J"
976
977 #define LANG "Ljava/lang/"
978
979 #define OBJ LANG "Object;"
980 #define CLS LANG "Class;"
981 #define FLD LANG "reflect/Field;"
982 #define THR LANG "Throwable;"
983
984 #define DC_Args LANG "String;[BII" LANG "ClassLoader;" "Ljava/security/ProtectionDomain;"
985 #define DAC_Args CLS "[B[" OBJ
986
987 #define CC (char*) /*cast a literal from (const char*)*/
988 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
989
990 #define DECLARE_GETPUTOOP(Type, Desc) \
991 {CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \
992 {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type)}, \
993 {CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \
994 {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Put##Type##Volatile)}
995
996
997 static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = {
998 {CC "getReference", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetReference)},
999 {CC "putReference", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReference)},
1000 {CC "getReferenceVolatile", CC "(" OBJ "J)" OBJ, FN_PTR(Unsafe_GetReferenceVolatile)},
1001 {CC "putReferenceVolatile", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_PutReferenceVolatile)},
1002
1003 {CC "isFlattenedArray", CC "(" CLS ")Z", FN_PTR(Unsafe_IsFlattenedArray)},
1004 {CC "isFlattenedField0", CC "(" OBJ ")Z", FN_PTR(Unsafe_IsFlattenedField)},
1005 {CC "getValue", CC "(" OBJ "J" CLS ")" OBJ, FN_PTR(Unsafe_GetValue)},
1006 {CC "putValue", CC "(" OBJ "J" CLS OBJ ")V", FN_PTR(Unsafe_PutValue)},
1007 {CC "uninitializedDefaultValue", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_UninitializedDefaultValue)},
1008 {CC "makePrivateBuffer", CC "(" OBJ ")" OBJ, FN_PTR(Unsafe_MakePrivateBuffer)},
1009 {CC "finishPrivateBuffer", CC "(" OBJ ")" OBJ, FN_PTR(Unsafe_FinishPrivateBuffer)},
1010 {CC "valueHeaderSize", CC "(" CLS ")J", FN_PTR(Unsafe_ValueHeaderSize)},
1011
1012 {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)},
1013
1014 DECLARE_GETPUTOOP(Boolean, Z),
1015 DECLARE_GETPUTOOP(Byte, B),
1016 DECLARE_GETPUTOOP(Short, S),
1017 DECLARE_GETPUTOOP(Char, C),
1018 DECLARE_GETPUTOOP(Int, I),
1019 DECLARE_GETPUTOOP(Long, J),
1020 DECLARE_GETPUTOOP(Float, F),
1021 DECLARE_GETPUTOOP(Double, D),
1022
1023 {CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)},
1024 {CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)},
1025 {CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)},
1026
1027 {CC "objectFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset0)},
1028 {CC "objectFieldOffset1", CC "(" CLS LANG "String;)J", FN_PTR(Unsafe_ObjectFieldOffset1)},
1029 {CC "staticFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset0)},
1030 {CC "staticFieldBase0", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBase0)},
1031 {CC "ensureClassInitialized0", CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized0)},
1032 {CC "arrayBaseOffset0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset0)},
1033 {CC "arrayIndexScale0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale0)},
1034 {CC "getObjectSize0", CC "(Ljava/lang/Object;)J", FN_PTR(Unsafe_GetObjectSize0)},
1035
1036 {CC "defineClass0", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass0)},
1037 {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)},
1038 {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)},
1039 {CC "compareAndSetReference",CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSetReference)},
1040 {CC "compareAndSetInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSetInt)},
1041 {CC "compareAndSetLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSetLong)},
1042 {CC "compareAndExchangeReference", CC "(" OBJ "J" OBJ "" OBJ ")" OBJ, FN_PTR(Unsafe_CompareAndExchangeReference)},
1043 {CC "compareAndExchangeInt", CC "(" OBJ "J""I""I"")I", FN_PTR(Unsafe_CompareAndExchangeInt)},
1044 {CC "compareAndExchangeLong", CC "(" OBJ "J""J""J"")J", FN_PTR(Unsafe_CompareAndExchangeLong)},
1045
1046 {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)},
1047 {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)},
1048
1049 {CC "getLoadAverage0", CC "([DI)I", FN_PTR(Unsafe_GetLoadAverage0)},
1050
1051 {CC "copyMemory0", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)},
1052 {CC "copySwapMemory0", CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)},
1053 {CC "writeback0", CC "(" "J" ")V", FN_PTR(Unsafe_WriteBack0)},
1054 {CC "writebackPreSync0", CC "()V", FN_PTR(Unsafe_WriteBackPreSync0)},
|