comparison src/share/vm/prims/unsafe.cpp @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children ba764ed4b6f2
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 *
23 */
24
25 /*
26 * Implementation of class sun.misc.Unsafe
27 */
28
29 #include "incls/_precompiled.incl"
30 #include "incls/_unsafe.cpp.incl"
31
32 #define MAX_OBJECT_SIZE \
33 ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \
34 + ((julong)max_jint * sizeof(double)) )
35
36
37 #define UNSAFE_ENTRY(result_type, header) \
38 JVM_ENTRY(result_type, header)
39
40 // Can't use UNSAFE_LEAF because it has the signature of a straight
41 // call into the runtime (just like JVM_LEAF, funny that) but it's
42 // called like a Java Native and thus the wrapper built for it passes
43 // arguments like a JNI call. It expects those arguments to be popped
44 // from the stack on Intel like all good JNI args are, and adjusts the
45 // stack according. Since the JVM_LEAF call expects no extra
46 // arguments the stack isn't popped in the C code, is pushed by the
47 // wrapper and we get sick.
48 //#define UNSAFE_LEAF(result_type, header) \
49 // JVM_LEAF(result_type, header)
50
51 #define UNSAFE_END JVM_END
52
53 #define UnsafeWrapper(arg) /*nothing, for the present*/
54
55
56 inline void* addr_from_java(jlong addr) {
57 // This assert fails in a variety of ways on 32-bit systems.
58 // It is impossible to predict whether native code that converts
59 // pointers to longs will sign-extend or zero-extend the addresses.
60 //assert(addr == (uintptr_t)addr, "must not be odd high bits");
61 return (void*)(uintptr_t)addr;
62 }
63
64 inline jlong addr_to_java(void* p) {
65 assert(p == (void*)(uintptr_t)p, "must not be odd high bits");
66 return (uintptr_t)p;
67 }
68
69
70 // Note: The VM's obj_field and related accessors use byte-scaled
71 // ("unscaled") offsets, just as the unsafe methods do.
72
73 // However, the method Unsafe.fieldOffset explicitly declines to
74 // guarantee this. The field offset values manipulated by the Java user
75 // through the Unsafe API are opaque cookies that just happen to be byte
76 // offsets. We represent this state of affairs by passing the cookies
77 // through conversion functions when going between the VM and the Unsafe API.
78 // The conversion functions just happen to be no-ops at present.
79
80 inline jlong field_offset_to_byte_offset(jlong field_offset) {
81 return field_offset;
82 }
83
84 inline jlong field_offset_from_byte_offset(jlong byte_offset) {
85 return byte_offset;
86 }
87
88 inline jint invocation_key_from_method_slot(jint slot) {
89 return slot;
90 }
91
92 inline jint invocation_key_to_method_slot(jint key) {
93 return key;
94 }
95
96 inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
97 jlong byte_offset = field_offset_to_byte_offset(field_offset);
98 #ifdef ASSERT
99 if (p != NULL) {
100 assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");
101 if (byte_offset == (jint)byte_offset) {
102 void* ptr_plus_disp = (address)p + byte_offset;
103 assert((void*)p->obj_field_addr((jint)byte_offset) == ptr_plus_disp,
104 "raw [ptr+disp] must be consistent with oop::field_base");
105 }
106 }
107 #endif
108 if (sizeof(char*) == sizeof(jint)) // (this constant folds!)
109 return (address)p + (jint) byte_offset;
110 else
111 return (address)p + byte_offset;
112 }
113
114 // Externally callable versions:
115 // (Use these in compiler intrinsics which emulate unsafe primitives.)
116 jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
117 return field_offset;
118 }
119 jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
120 return byte_offset;
121 }
122 jint Unsafe_invocation_key_from_method_slot(jint slot) {
123 return invocation_key_from_method_slot(slot);
124 }
125 jint Unsafe_invocation_key_to_method_slot(jint key) {
126 return invocation_key_to_method_slot(key);
127 }
128
129
130 ///// Data in the Java heap.
131
132 #define GET_FIELD(obj, offset, type_name, v) \
133 oop p = JNIHandles::resolve(obj); \
134 type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
135
136 #define SET_FIELD(obj, offset, type_name, x) \
137 oop p = JNIHandles::resolve(obj); \
138 *(type_name*)index_oop_from_field_offset_long(p, offset) = x
139
140 #define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
141 oop p = JNIHandles::resolve(obj); \
142 volatile type_name v = *(volatile type_name*)index_oop_from_field_offset_long(p, offset)
143
144 #define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
145 oop p = JNIHandles::resolve(obj); \
146 *(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \
147 OrderAccess::fence();
148
149 // Get/SetObject must be special-cased, since it works with handles.
150
151 // The xxx140 variants for backward compatibility do not allow a full-width offset.
152 UNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset))
153 UnsafeWrapper("Unsafe_GetObject");
154 if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException());
155 GET_FIELD(obj, offset, oop, v);
156 return JNIHandles::make_local(env, v);
157 UNSAFE_END
158
159 UNSAFE_ENTRY(void, Unsafe_SetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jobject x_h))
160 UnsafeWrapper("Unsafe_SetObject");
161 if (obj == NULL) THROW(vmSymbols::java_lang_NullPointerException());
162 oop x = JNIHandles::resolve(x_h);
163 //SET_FIELD(obj, offset, oop, x);
164 oop p = JNIHandles::resolve(obj);
165 if (x != NULL) {
166 // If there is a heap base pointer, we are obliged to emit a store barrier.
167 oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
168 } else {
169 *(oop*)index_oop_from_field_offset_long(p, offset) = x;
170 }
171 UNSAFE_END
172
173 // The normal variants allow a null base pointer with an arbitrary address.
174 // But if the base pointer is non-null, the offset should make some sense.
175 // That is, it should be in the range [0, MAX_OBJECT_SIZE].
176 UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
177 UnsafeWrapper("Unsafe_GetObject");
178 GET_FIELD(obj, offset, oop, v);
179 return JNIHandles::make_local(env, v);
180 UNSAFE_END
181
182 UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
183 UnsafeWrapper("Unsafe_SetObject");
184 oop x = JNIHandles::resolve(x_h);
185 oop p = JNIHandles::resolve(obj);
186 oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
187 UNSAFE_END
188
189 UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
190 UnsafeWrapper("Unsafe_GetObjectVolatile");
191 GET_FIELD_VOLATILE(obj, offset, oop, v);
192 return JNIHandles::make_local(env, v);
193 UNSAFE_END
194
195 UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
196 UnsafeWrapper("Unsafe_SetObjectVolatile");
197 oop x = JNIHandles::resolve(x_h);
198 oop p = JNIHandles::resolve(obj);
199 oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
200 OrderAccess::fence();
201 UNSAFE_END
202
203 // Volatile long versions must use locks if !VM_Version::supports_cx8().
204 // support_cx8 is a surrogate for 'supports atomic long memory ops'.
205
206 UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
207 UnsafeWrapper("Unsafe_GetLongVolatile");
208 {
209 if (VM_Version::supports_cx8()) {
210 GET_FIELD_VOLATILE(obj, offset, jlong, v);
211 return v;
212 }
213 else {
214 Handle p (THREAD, JNIHandles::resolve(obj));
215 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
216 ObjectLocker ol(p, THREAD);
217 jlong value = *addr;
218 return value;
219 }
220 }
221 UNSAFE_END
222
223 UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
224 UnsafeWrapper("Unsafe_SetLongVolatile");
225 {
226 if (VM_Version::supports_cx8()) {
227 SET_FIELD_VOLATILE(obj, offset, jlong, x);
228 }
229 else {
230 Handle p (THREAD, JNIHandles::resolve(obj));
231 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
232 ObjectLocker ol(p, THREAD);
233 *addr = x;
234 }
235 }
236 UNSAFE_END
237
238
239 #define DEFINE_GETSETOOP(jboolean, Boolean) \
240 \
241 UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \
242 UnsafeWrapper("Unsafe_Get"#Boolean); \
243 if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); \
244 GET_FIELD(obj, offset, jboolean, v); \
245 return v; \
246 UNSAFE_END \
247 \
248 UNSAFE_ENTRY(void, Unsafe_Set##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jboolean x)) \
249 UnsafeWrapper("Unsafe_Set"#Boolean); \
250 if (obj == NULL) THROW(vmSymbols::java_lang_NullPointerException()); \
251 SET_FIELD(obj, offset, jboolean, x); \
252 UNSAFE_END \
253 \
254 UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \
255 UnsafeWrapper("Unsafe_Get"#Boolean); \
256 GET_FIELD(obj, offset, jboolean, v); \
257 return v; \
258 UNSAFE_END \
259 \
260 UNSAFE_ENTRY(void, Unsafe_Set##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \
261 UnsafeWrapper("Unsafe_Set"#Boolean); \
262 SET_FIELD(obj, offset, jboolean, x); \
263 UNSAFE_END \
264 \
265 // END DEFINE_GETSETOOP.
266
267
268 #define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \
269 \
270 UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \
271 UnsafeWrapper("Unsafe_Get"#Boolean); \
272 GET_FIELD_VOLATILE(obj, offset, jboolean, v); \
273 return v; \
274 UNSAFE_END \
275 \
276 UNSAFE_ENTRY(void, Unsafe_Set##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \
277 UnsafeWrapper("Unsafe_Set"#Boolean); \
278 SET_FIELD_VOLATILE(obj, offset, jboolean, x); \
279 UNSAFE_END \
280 \
281 // END DEFINE_GETSETOOP_VOLATILE.
282
283 DEFINE_GETSETOOP(jboolean, Boolean)
284 DEFINE_GETSETOOP(jbyte, Byte)
285 DEFINE_GETSETOOP(jshort, Short);
286 DEFINE_GETSETOOP(jchar, Char);
287 DEFINE_GETSETOOP(jint, Int);
288 DEFINE_GETSETOOP(jlong, Long);
289 DEFINE_GETSETOOP(jfloat, Float);
290 DEFINE_GETSETOOP(jdouble, Double);
291
292 DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
293 DEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
294 DEFINE_GETSETOOP_VOLATILE(jshort, Short);
295 DEFINE_GETSETOOP_VOLATILE(jchar, Char);
296 DEFINE_GETSETOOP_VOLATILE(jint, Int);
297 // no long -- handled specially
298 DEFINE_GETSETOOP_VOLATILE(jfloat, Float);
299 DEFINE_GETSETOOP_VOLATILE(jdouble, Double);
300
301 #undef DEFINE_GETSETOOP
302
303 // The non-intrinsified versions of setOrdered just use setVolatile
304
305 UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) \
306 UnsafeWrapper("Unsafe_SetOrderedInt"); \
307 SET_FIELD_VOLATILE(obj, offset, jint, x); \
308 UNSAFE_END
309
310 UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
311 UnsafeWrapper("Unsafe_SetOrderedObject");
312 oop x = JNIHandles::resolve(x_h);
313 oop p = JNIHandles::resolve(obj);
314 oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
315 OrderAccess::fence();
316 UNSAFE_END
317
318 UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
319 UnsafeWrapper("Unsafe_SetOrderedLong");
320 {
321 if (VM_Version::supports_cx8()) {
322 SET_FIELD_VOLATILE(obj, offset, jlong, x);
323 }
324 else {
325 Handle p (THREAD, JNIHandles::resolve(obj));
326 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
327 ObjectLocker ol(p, THREAD);
328 *addr = x;
329 }
330 }
331 UNSAFE_END
332
333 ////// Data in the C heap.
334
335 // Note: These do not throw NullPointerException for bad pointers.
336 // They just crash. Only a oop base pointer can generate a NullPointerException.
337 //
338 #define DEFINE_GETSETNATIVE(java_type, Type, native_type) \
339 \
340 UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) \
341 UnsafeWrapper("Unsafe_GetNative"#Type); \
342 void* p = addr_from_java(addr); \
343 JavaThread* t = JavaThread::current(); \
344 t->set_doing_unsafe_access(true); \
345 java_type x = *(volatile native_type*)p; \
346 t->set_doing_unsafe_access(false); \
347 return x; \
348 UNSAFE_END \
349 \
350 UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) \
351 UnsafeWrapper("Unsafe_SetNative"#Type); \
352 JavaThread* t = JavaThread::current(); \
353 t->set_doing_unsafe_access(true); \
354 void* p = addr_from_java(addr); \
355 *(volatile native_type*)p = x; \
356 t->set_doing_unsafe_access(false); \
357 UNSAFE_END \
358 \
359 // END DEFINE_GETSETNATIVE.
360
361 DEFINE_GETSETNATIVE(jbyte, Byte, signed char)
362 DEFINE_GETSETNATIVE(jshort, Short, signed short);
363 DEFINE_GETSETNATIVE(jchar, Char, unsigned short);
364 DEFINE_GETSETNATIVE(jint, Int, jint);
365 // no long -- handled specially
366 DEFINE_GETSETNATIVE(jfloat, Float, float);
367 DEFINE_GETSETNATIVE(jdouble, Double, double);
368
369 #undef DEFINE_GETSETNATIVE
370
371 UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr))
372 UnsafeWrapper("Unsafe_GetNativeLong");
373 JavaThread* t = JavaThread::current();
374 // We do it this way to avoid problems with access to heap using 64
375 // bit loads, as jlong in heap could be not 64-bit aligned, and on
376 // some CPUs (SPARC) it leads to SIGBUS.
377 t->set_doing_unsafe_access(true);
378 void* p = addr_from_java(addr);
379 jlong x;
380 if (((intptr_t)p & 7) == 0) {
381 // jlong is aligned, do a volatile access
382 x = *(volatile jlong*)p;
383 } else {
384 jlong_accessor acc;
385 acc.words[0] = ((volatile jint*)p)[0];
386 acc.words[1] = ((volatile jint*)p)[1];
387 x = acc.long_value;
388 }
389 t->set_doing_unsafe_access(false);
390 return x;
391 UNSAFE_END
392
393 UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x))
394 UnsafeWrapper("Unsafe_SetNativeLong");
395 JavaThread* t = JavaThread::current();
396 // see comment for Unsafe_GetNativeLong
397 t->set_doing_unsafe_access(true);
398 void* p = addr_from_java(addr);
399 if (((intptr_t)p & 7) == 0) {
400 // jlong is aligned, do a volatile access
401 *(volatile jlong*)p = x;
402 } else {
403 jlong_accessor acc;
404 acc.long_value = x;
405 ((volatile jint*)p)[0] = acc.words[0];
406 ((volatile jint*)p)[1] = acc.words[1];
407 }
408 t->set_doing_unsafe_access(false);
409 UNSAFE_END
410
411
412 UNSAFE_ENTRY(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr))
413 UnsafeWrapper("Unsafe_GetNativeAddress");
414 void* p = addr_from_java(addr);
415 return addr_to_java(*(void**)p);
416 UNSAFE_END
417
418 UNSAFE_ENTRY(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x))
419 UnsafeWrapper("Unsafe_SetNativeAddress");
420 void* p = addr_from_java(addr);
421 *(void**)p = addr_from_java(x);
422 UNSAFE_END
423
424
425 ////// Allocation requests
426
427 UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls))
428 UnsafeWrapper("Unsafe_AllocateInstance");
429 {
430 ThreadToNativeFromVM ttnfv(thread);
431 return env->AllocObject(cls);
432 }
433 UNSAFE_END
434
435 UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size))
436 UnsafeWrapper("Unsafe_AllocateMemory");
437 size_t sz = (size_t)size;
438 if (sz != (julong)size || size < 0) {
439 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
440 }
441 if (sz == 0) {
442 return 0;
443 }
444 sz = round_to(sz, HeapWordSize);
445 void* x = os::malloc(sz);
446 if (x == NULL) {
447 THROW_0(vmSymbols::java_lang_OutOfMemoryError());
448 }
449 //Copy::fill_to_words((HeapWord*)x, sz / HeapWordSize);
450 return addr_to_java(x);
451 UNSAFE_END
452
453 UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory(JNIEnv *env, jobject unsafe, jlong addr, jlong size))
454 UnsafeWrapper("Unsafe_ReallocateMemory");
455 void* p = addr_from_java(addr);
456 size_t sz = (size_t)size;
457 if (sz != (julong)size || size < 0) {
458 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
459 }
460 if (sz == 0) {
461 os::free(p);
462 return 0;
463 }
464 sz = round_to(sz, HeapWordSize);
465 void* x = (p == NULL) ? os::malloc(sz) : os::realloc(p, sz);
466 if (x == NULL) {
467 THROW_0(vmSymbols::java_lang_OutOfMemoryError());
468 }
469 return addr_to_java(x);
470 UNSAFE_END
471
472 UNSAFE_ENTRY(void, Unsafe_FreeMemory(JNIEnv *env, jobject unsafe, jlong addr))
473 UnsafeWrapper("Unsafe_FreeMemory");
474 void* p = addr_from_java(addr);
475 if (p == NULL) {
476 return;
477 }
478 os::free(p);
479 UNSAFE_END
480
481 UNSAFE_ENTRY(void, Unsafe_SetMemory(JNIEnv *env, jobject unsafe, jlong addr, jlong size, jbyte value))
482 UnsafeWrapper("Unsafe_SetMemory");
483 size_t sz = (size_t)size;
484 if (sz != (julong)size || size < 0) {
485 THROW(vmSymbols::java_lang_IllegalArgumentException());
486 }
487 char* p = (char*) addr_from_java(addr);
488 Copy::fill_to_memory_atomic(p, sz, value);
489 UNSAFE_END
490
491 UNSAFE_ENTRY(void, Unsafe_SetMemory2(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value))
492 UnsafeWrapper("Unsafe_SetMemory");
493 size_t sz = (size_t)size;
494 if (sz != (julong)size || size < 0) {
495 THROW(vmSymbols::java_lang_IllegalArgumentException());
496 }
497 oop base = JNIHandles::resolve(obj);
498 void* p = index_oop_from_field_offset_long(base, offset);
499 Copy::fill_to_memory_atomic(p, sz, value);
500 UNSAFE_END
501
502 UNSAFE_ENTRY(void, Unsafe_CopyMemory(JNIEnv *env, jobject unsafe, jlong srcAddr, jlong dstAddr, jlong size))
503 UnsafeWrapper("Unsafe_CopyMemory");
504 if (size == 0) {
505 return;
506 }
507 size_t sz = (size_t)size;
508 if (sz != (julong)size || size < 0) {
509 THROW(vmSymbols::java_lang_IllegalArgumentException());
510 }
511 void* src = addr_from_java(srcAddr);
512 void* dst = addr_from_java(dstAddr);
513 Copy::conjoint_memory_atomic(src, dst, sz);
514 UNSAFE_END
515
516 UNSAFE_ENTRY(void, Unsafe_CopyMemory2(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size))
517 UnsafeWrapper("Unsafe_CopyMemory");
518 if (size == 0) {
519 return;
520 }
521 size_t sz = (size_t)size;
522 if (sz != (julong)size || size < 0) {
523 THROW(vmSymbols::java_lang_IllegalArgumentException());
524 }
525 oop srcp = JNIHandles::resolve(srcObj);
526 oop dstp = JNIHandles::resolve(dstObj);
527 if (dstp != NULL && !dstp->is_typeArray()) {
528 // NYI: This works only for non-oop arrays at present.
529 // Generalizing it would be reasonable, but requires card marking.
530 // Also, autoboxing a Long from 0L in copyMemory(x,y, 0L,z, n) would be bad.
531 THROW(vmSymbols::java_lang_IllegalArgumentException());
532 }
533 void* src = index_oop_from_field_offset_long(srcp, srcOffset);
534 void* dst = index_oop_from_field_offset_long(dstp, dstOffset);
535 Copy::conjoint_memory_atomic(src, dst, sz);
536 UNSAFE_END
537
538
539 ////// Random queries
540
541 // See comment at file start about UNSAFE_LEAF
542 //UNSAFE_LEAF(jint, Unsafe_AddressSize())
543 UNSAFE_ENTRY(jint, Unsafe_AddressSize(JNIEnv *env, jobject unsafe))
544 UnsafeWrapper("Unsafe_AddressSize");
545 return sizeof(void*);
546 UNSAFE_END
547
548 // See comment at file start about UNSAFE_LEAF
549 //UNSAFE_LEAF(jint, Unsafe_PageSize())
550 UNSAFE_ENTRY(jint, Unsafe_PageSize(JNIEnv *env, jobject unsafe))
551 UnsafeWrapper("Unsafe_PageSize");
552 return os::vm_page_size();
553 UNSAFE_END
554
555 jint find_field_offset(jobject field, int must_be_static, TRAPS) {
556 if (field == NULL) {
557 THROW_0(vmSymbols::java_lang_NullPointerException());
558 }
559
560 oop reflected = JNIHandles::resolve_non_null(field);
561 oop mirror = java_lang_reflect_Field::clazz(reflected);
562 klassOop k = java_lang_Class::as_klassOop(mirror);
563 int slot = java_lang_reflect_Field::slot(reflected);
564 int modifiers = java_lang_reflect_Field::modifiers(reflected);
565
566 if (must_be_static >= 0) {
567 int really_is_static = ((modifiers & JVM_ACC_STATIC) != 0);
568 if (must_be_static != really_is_static) {
569 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
570 }
571 }
572
573 int offset = instanceKlass::cast(k)->offset_from_fields(slot);
574 return field_offset_from_byte_offset(offset);
575 }
576
577 UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
578 UnsafeWrapper("Unsafe_ObjectFieldOffset");
579 return find_field_offset(field, 0, THREAD);
580 UNSAFE_END
581
582 UNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
583 UnsafeWrapper("Unsafe_StaticFieldOffset");
584 return find_field_offset(field, 1, THREAD);
585 UNSAFE_END
586
587 UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsafe, jobject field))
588 UnsafeWrapper("Unsafe_StaticFieldBase");
589 // Note: In this VM implementation, a field address is always a short
590 // offset from the base of a a klass metaobject. Thus, the full dynamic
591 // range of the return type is never used. However, some implementations
592 // might put the static field inside an array shared by many classes,
593 // or even at a fixed address, in which case the address could be quite
594 // large. In that last case, this function would return NULL, since
595 // the address would operate alone, without any base pointer.
596
597 if (field == NULL) THROW_0(vmSymbols::java_lang_NullPointerException());
598
599 oop reflected = JNIHandles::resolve_non_null(field);
600 oop mirror = java_lang_reflect_Field::clazz(reflected);
601 int modifiers = java_lang_reflect_Field::modifiers(reflected);
602
603 if ((modifiers & JVM_ACC_STATIC) == 0) {
604 THROW_0(vmSymbols::java_lang_IllegalArgumentException());
605 }
606
607 return JNIHandles::make_local(env, java_lang_Class::as_klassOop(mirror));
608 UNSAFE_END
609
610 //@deprecated
611 UNSAFE_ENTRY(jint, Unsafe_FieldOffset(JNIEnv *env, jobject unsafe, jobject field))
612 UnsafeWrapper("Unsafe_FieldOffset");
613 // tries (but fails) to be polymorphic between static and non-static:
614 jlong offset = find_field_offset(field, -1, THREAD);
615 guarantee(offset == (jint)offset, "offset fits in 32 bits");
616 return (jint)offset;
617 UNSAFE_END
618
619 //@deprecated
620 UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromClass(JNIEnv *env, jobject unsafe, jobject clazz))
621 UnsafeWrapper("Unsafe_StaticFieldBase");
622 if (clazz == NULL) {
623 THROW_0(vmSymbols::java_lang_NullPointerException());
624 }
625 return JNIHandles::make_local(env, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz)));
626 UNSAFE_END
627
628 UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jobject clazz))
629 UnsafeWrapper("Unsafe_EnsureClassInitialized");
630 if (clazz == NULL) {
631 THROW(vmSymbols::java_lang_NullPointerException());
632 }
633 oop mirror = JNIHandles::resolve_non_null(clazz);
634 instanceKlass* k = instanceKlass::cast(java_lang_Class::as_klassOop(mirror));
635 if (k != NULL) {
636 k->initialize(CHECK);
637 }
638 UNSAFE_END
639
640 static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) {
641 if (acls == NULL) {
642 THROW(vmSymbols::java_lang_NullPointerException());
643 }
644 oop mirror = JNIHandles::resolve_non_null(acls);
645 klassOop k = java_lang_Class::as_klassOop(mirror);
646 if (k == NULL || !k->klass_part()->oop_is_array()) {
647 THROW(vmSymbols::java_lang_InvalidClassException());
648 } else if (k->klass_part()->oop_is_objArray()) {
649 base = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
650 scale = oopSize;
651 } else if (k->klass_part()->oop_is_typeArray()) {
652 typeArrayKlass* tak = typeArrayKlass::cast(k);
653 base = tak->array_header_in_bytes();
654 assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
655 scale = (1 << tak->log2_element_size());
656 } else {
657 ShouldNotReachHere();
658 }
659 }
660
661 UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls))
662 UnsafeWrapper("Unsafe_ArrayBaseOffset");
663 int base, scale;
664 getBaseAndScale(base, scale, acls, CHECK_0);
665 return field_offset_from_byte_offset(base);
666 UNSAFE_END
667
668
669 UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls))
670 UnsafeWrapper("Unsafe_ArrayIndexScale");
671 int base, scale;
672 getBaseAndScale(base, scale, acls, CHECK_0);
673 // This VM packs both fields and array elements down to the byte.
674 // But watch out: If this changes, so that array references for
675 // a given primitive type (say, T_BOOLEAN) use different memory units
676 // than fields, this method MUST return zero for such arrays.
677 // For example, the VM used to store sub-word sized fields in full
678 // words in the object layout, so that accessors like getByte(Object,int)
679 // did not really do what one might expect for arrays. Therefore,
680 // this function used to report a zero scale factor, so that the user
681 // would know not to attempt to access sub-word array elements.
682 // // Code for unpacked fields:
683 // if (scale < wordSize) return 0;
684
685 // The following allows for a pretty general fieldOffset cookie scheme,
686 // but requires it to be linear in byte offset.
687 return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
688 UNSAFE_END
689
690
691 static inline void throw_new(JNIEnv *env, const char *ename) {
692 char buf[100];
693 strcpy(buf, "java/lang/");
694 strcat(buf, ename);
695 jclass cls = env->FindClass(buf);
696 char* msg = NULL;
697 env->ThrowNew(cls, msg);
698 }
699
700 static jclass Unsafe_DefineClass(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
701 {
702 // Code lifted from JDK 1.3 ClassLoader.c
703
704 jbyte *body;
705 char *utfName;
706 jclass result = 0;
707 char buf[128];
708
709 if (UsePerfData) {
710 ClassLoader::unsafe_defineClassCallCounter()->inc();
711 }
712
713 if (data == NULL) {
714 throw_new(env, "NullPointerException");
715 return 0;
716 }
717
718 /* Work around 4153825. malloc crashes on Solaris when passed a
719 * negative size.
720 */
721 if (length < 0) {
722 throw_new(env, "ArrayIndexOutOfBoundsException");
723 return 0;
724 }
725
726 body = NEW_C_HEAP_ARRAY(jbyte, length);
727
728 if (body == 0) {
729 throw_new(env, "OutOfMemoryError");
730 return 0;
731 }
732
733 env->GetByteArrayRegion(data, offset, length, body);
734
735 if (env->ExceptionOccurred())
736 goto free_body;
737
738 if (name != NULL) {
739 uint len = env->GetStringUTFLength(name);
740 int unicode_len = env->GetStringLength(name);
741 if (len >= sizeof(buf)) {
742 utfName = NEW_C_HEAP_ARRAY(char, len + 1);
743 if (utfName == NULL) {
744 throw_new(env, "OutOfMemoryError");
745 goto free_body;
746 }
747 } else {
748 utfName = buf;
749 }
750 env->GetStringUTFRegion(name, 0, unicode_len, utfName);
751 //VerifyFixClassname(utfName);
752 for (uint i = 0; i < len; i++) {
753 if (utfName[i] == '.') utfName[i] = '/';
754 }
755 } else {
756 utfName = NULL;
757 }
758
759 result = JVM_DefineClass(env, utfName, loader, body, length, pd);
760
761 if (utfName && utfName != buf)
762 FREE_C_HEAP_ARRAY(char, utfName);
763
764 free_body:
765 FREE_C_HEAP_ARRAY(jbyte, body);
766 return result;
767 }
768 }
769
770
771 UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length))
772 UnsafeWrapper("Unsafe_DefineClass");
773 {
774 ThreadToNativeFromVM ttnfv(thread);
775
776 int depthFromDefineClass0 = 1;
777 jclass caller = JVM_GetCallerClass(env, depthFromDefineClass0);
778 jobject loader = (caller == NULL) ? NULL : JVM_GetClassLoader(env, caller);
779 jobject pd = (caller == NULL) ? NULL : JVM_GetProtectionDomain(env, caller);
780
781 return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
782 }
783 UNSAFE_END
784
785
786 UNSAFE_ENTRY(jclass, Unsafe_DefineClass1(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd))
787 UnsafeWrapper("Unsafe_DefineClass");
788 {
789 ThreadToNativeFromVM ttnfv(thread);
790
791 return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
792 }
793 UNSAFE_END
794
795
796 UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
797 UnsafeWrapper("Unsafe_MonitorEnter");
798 {
799 if (jobj == NULL) {
800 THROW(vmSymbols::java_lang_NullPointerException());
801 }
802 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
803 ObjectSynchronizer::jni_enter(obj, CHECK);
804 }
805 UNSAFE_END
806
807
808 UNSAFE_ENTRY(jboolean, Unsafe_TryMonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
809 UnsafeWrapper("Unsafe_TryMonitorEnter");
810 {
811 if (jobj == NULL) {
812 THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
813 }
814 Handle obj(thread, JNIHandles::resolve_non_null(jobj));
815 bool res = ObjectSynchronizer::jni_try_enter(obj, CHECK_0);
816 return (res ? JNI_TRUE : JNI_FALSE);
817 }
818 UNSAFE_END
819
820
821 UNSAFE_ENTRY(void, Unsafe_MonitorExit(JNIEnv *env, jobject unsafe, jobject jobj))
822 UnsafeWrapper("Unsafe_MonitorExit");
823 {
824 if (jobj == NULL) {
825 THROW(vmSymbols::java_lang_NullPointerException());
826 }
827 Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
828 ObjectSynchronizer::jni_exit(obj(), CHECK);
829 }
830 UNSAFE_END
831
832
833 UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr))
834 UnsafeWrapper("Unsafe_ThrowException");
835 {
836 ThreadToNativeFromVM ttnfv(thread);
837 env->Throw(thr);
838 }
839 UNSAFE_END
840
841 // JSR166 ------------------------------------------------------------------
842
843 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
844 UnsafeWrapper("Unsafe_CompareAndSwapObject");
845 oop x = JNIHandles::resolve(x_h);
846 oop e = JNIHandles::resolve(e_h);
847 oop p = JNIHandles::resolve(obj);
848 intptr_t* addr = (intptr_t *)index_oop_from_field_offset_long(p, offset);
849 intptr_t res = Atomic::cmpxchg_ptr((intptr_t)x, addr, (intptr_t)e);
850 jboolean success = (res == (intptr_t)e);
851 if (success)
852 update_barrier_set((oop*)addr, x);
853 return success;
854 UNSAFE_END
855
856 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
857 UnsafeWrapper("Unsafe_CompareAndSwapInt");
858 oop p = JNIHandles::resolve(obj);
859 jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
860 return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
861 UNSAFE_END
862
863 UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x))
864 UnsafeWrapper("Unsafe_CompareAndSwapLong");
865 Handle p (THREAD, JNIHandles::resolve(obj));
866 jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
867 if (VM_Version::supports_cx8())
868 return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
869 else {
870 jboolean success = false;
871 ObjectLocker ol(p, THREAD);
872 if (*addr == e) { *addr = x; success = true; }
873 return success;
874 }
875 UNSAFE_END
876
877 UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time))
878 UnsafeWrapper("Unsafe_Park");
879 JavaThreadParkedState jtps(thread, time != 0);
880 thread->parker()->park(isAbsolute != 0, time);
881 UNSAFE_END
882
883 UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
884 UnsafeWrapper("Unsafe_Unpark");
885 Parker* p = NULL;
886 if (jthread != NULL) {
887 oop java_thread = JNIHandles::resolve_non_null(jthread);
888 if (java_thread != NULL) {
889 jlong lp = java_lang_Thread::park_event(java_thread);
890 if (lp != 0) {
891 // This cast is OK even though the jlong might have been read
892 // non-atomically on 32bit systems, since there, one word will
893 // always be zero anyway and the value set is always the same
894 p = (Parker*)addr_from_java(lp);
895 } else {
896 // Grab lock if apparently null or using older version of library
897 MutexLocker mu(Threads_lock);
898 java_thread = JNIHandles::resolve_non_null(jthread);
899 if (java_thread != NULL) {
900 JavaThread* thr = java_lang_Thread::thread(java_thread);
901 if (thr != NULL) {
902 p = thr->parker();
903 if (p != NULL) { // Bind to Java thread for next time.
904 java_lang_Thread::set_park_event(java_thread, addr_to_java(p));
905 }
906 }
907 }
908 }
909 }
910 }
911 if (p != NULL) {
912 p->unpark();
913 }
914 UNSAFE_END
915
916 UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem))
917 UnsafeWrapper("Unsafe_Loadavg");
918 const int max_nelem = 3;
919 double la[max_nelem];
920 jint ret;
921
922 typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(loadavg));
923 assert(a->is_typeArray(), "must be type array");
924
925 if (nelem < 0 || nelem > max_nelem || a->length() < nelem) {
926 ThreadToNativeFromVM ttnfv(thread);
927 throw_new(env, "ArrayIndexOutOfBoundsException");
928 return -1;
929 }
930
931 ret = os::loadavg(la, nelem);
932 if (ret == -1) return -1;
933
934 // if successful, ret is the number of samples actually retrieved.
935 assert(ret >= 0 && ret <= max_nelem, "Unexpected loadavg return value");
936 switch(ret) {
937 case 3: a->double_at_put(2, (jdouble)la[2]); // fall through
938 case 2: a->double_at_put(1, (jdouble)la[1]); // fall through
939 case 1: a->double_at_put(0, (jdouble)la[0]); break;
940 }
941 return ret;
942 UNSAFE_END
943
944 UNSAFE_ENTRY(void, Unsafe_PrefetchRead(JNIEnv* env, jclass ignored, jobject obj, jlong offset))
945 UnsafeWrapper("Unsafe_PrefetchRead");
946 oop p = JNIHandles::resolve(obj);
947 void* addr = index_oop_from_field_offset_long(p, 0);
948 Prefetch::read(addr, (intx)offset);
949 UNSAFE_END
950
951 UNSAFE_ENTRY(void, Unsafe_PrefetchWrite(JNIEnv* env, jclass ignored, jobject obj, jlong offset))
952 UnsafeWrapper("Unsafe_PrefetchWrite");
953 oop p = JNIHandles::resolve(obj);
954 void* addr = index_oop_from_field_offset_long(p, 0);
955 Prefetch::write(addr, (intx)offset);
956 UNSAFE_END
957
958
959 /// JVM_RegisterUnsafeMethods
960
961 #define ADR "J"
962
963 #define LANG "Ljava/lang/"
964
965 #define OBJ LANG"Object;"
966 #define CLS LANG"Class;"
967 #define CTR LANG"reflect/Constructor;"
968 #define FLD LANG"reflect/Field;"
969 #define MTH LANG"reflect/Method;"
970 #define THR LANG"Throwable;"
971
972 #define DC0_Args LANG"String;[BII"
973 #define DC1_Args DC0_Args LANG"ClassLoader;" "Ljava/security/ProtectionDomain;"
974
975 #define CC (char*) /*cast a literal from (const char*)*/
976 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
977
978 // define deprecated accessors for compabitility with 1.4.0
979 #define DECLARE_GETSETOOP_140(Boolean, Z) \
980 {CC"get"#Boolean, CC"("OBJ"I)"#Z, FN_PTR(Unsafe_Get##Boolean##140)}, \
981 {CC"put"#Boolean, CC"("OBJ"I"#Z")V", FN_PTR(Unsafe_Set##Boolean##140)}
982
983 // Note: In 1.4.1, getObject and kin take both int and long offsets.
984 #define DECLARE_GETSETOOP_141(Boolean, Z) \
985 {CC"get"#Boolean, CC"("OBJ"J)"#Z, FN_PTR(Unsafe_Get##Boolean)}, \
986 {CC"put"#Boolean, CC"("OBJ"J"#Z")V", FN_PTR(Unsafe_Set##Boolean)}
987
988 // Note: In 1.5.0, there are volatile versions too
989 #define DECLARE_GETSETOOP(Boolean, Z) \
990 {CC"get"#Boolean, CC"("OBJ"J)"#Z, FN_PTR(Unsafe_Get##Boolean)}, \
991 {CC"put"#Boolean, CC"("OBJ"J"#Z")V", FN_PTR(Unsafe_Set##Boolean)}, \
992 {CC"get"#Boolean"Volatile", CC"("OBJ"J)"#Z, FN_PTR(Unsafe_Get##Boolean##Volatile)}, \
993 {CC"put"#Boolean"Volatile", CC"("OBJ"J"#Z")V", FN_PTR(Unsafe_Set##Boolean##Volatile)}
994
995
996 #define DECLARE_GETSETNATIVE(Byte, B) \
997 {CC"get"#Byte, CC"("ADR")"#B, FN_PTR(Unsafe_GetNative##Byte)}, \
998 {CC"put"#Byte, CC"("ADR#B")V", FN_PTR(Unsafe_SetNative##Byte)}
999
1000
1001
1002 // %%% These are temporarily supported until the SDK sources
1003 // contain the necessarily updated Unsafe.java.
1004 static JNINativeMethod methods_140[] = {
1005
1006 {CC"getObject", CC"("OBJ"I)"OBJ"", FN_PTR(Unsafe_GetObject140)},
1007 {CC"putObject", CC"("OBJ"I"OBJ")V", FN_PTR(Unsafe_SetObject140)},
1008
1009 DECLARE_GETSETOOP_140(Boolean, Z),
1010 DECLARE_GETSETOOP_140(Byte, B),
1011 DECLARE_GETSETOOP_140(Short, S),
1012 DECLARE_GETSETOOP_140(Char, C),
1013 DECLARE_GETSETOOP_140(Int, I),
1014 DECLARE_GETSETOOP_140(Long, J),
1015 DECLARE_GETSETOOP_140(Float, F),
1016 DECLARE_GETSETOOP_140(Double, D),
1017
1018 DECLARE_GETSETNATIVE(Byte, B),
1019 DECLARE_GETSETNATIVE(Short, S),
1020 DECLARE_GETSETNATIVE(Char, C),
1021 DECLARE_GETSETNATIVE(Int, I),
1022 DECLARE_GETSETNATIVE(Long, J),
1023 DECLARE_GETSETNATIVE(Float, F),
1024 DECLARE_GETSETNATIVE(Double, D),
1025
1026 {CC"getAddress", CC"("ADR")"ADR, FN_PTR(Unsafe_GetNativeAddress)},
1027 {CC"putAddress", CC"("ADR""ADR")V", FN_PTR(Unsafe_SetNativeAddress)},
1028
1029 {CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
1030 {CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
1031 // {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
1032 // {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
1033 {CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
1034
1035 {CC"fieldOffset", CC"("FLD")I", FN_PTR(Unsafe_FieldOffset)}, //deprecated
1036 {CC"staticFieldBase", CC"("CLS")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromClass)}, //deprecated
1037 {CC"ensureClassInitialized",CC"("CLS")V", FN_PTR(Unsafe_EnsureClassInitialized)},
1038 {CC"arrayBaseOffset", CC"("CLS")I", FN_PTR(Unsafe_ArrayBaseOffset)},
1039 {CC"arrayIndexScale", CC"("CLS")I", FN_PTR(Unsafe_ArrayIndexScale)},
1040 {CC"addressSize", CC"()I", FN_PTR(Unsafe_AddressSize)},
1041 {CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
1042
1043 {CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
1044 {CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
1045 {CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
1046 {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
1047 {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
1048 {CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}
1049 };
1050
1051 // These are the old methods prior to the JSR 166 changes in 1.5.0
1052 static JNINativeMethod methods_141[] = {
1053
1054 {CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)},
1055 {CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)},
1056
1057 DECLARE_GETSETOOP_141(Boolean, Z),
1058 DECLARE_GETSETOOP_141(Byte, B),
1059 DECLARE_GETSETOOP_141(Short, S),
1060 DECLARE_GETSETOOP_141(Char, C),
1061 DECLARE_GETSETOOP_141(Int, I),
1062 DECLARE_GETSETOOP_141(Long, J),
1063 DECLARE_GETSETOOP_141(Float, F),
1064 DECLARE_GETSETOOP_141(Double, D),
1065
1066 DECLARE_GETSETNATIVE(Byte, B),
1067 DECLARE_GETSETNATIVE(Short, S),
1068 DECLARE_GETSETNATIVE(Char, C),
1069 DECLARE_GETSETNATIVE(Int, I),
1070 DECLARE_GETSETNATIVE(Long, J),
1071 DECLARE_GETSETNATIVE(Float, F),
1072 DECLARE_GETSETNATIVE(Double, D),
1073
1074 {CC"getAddress", CC"("ADR")"ADR, FN_PTR(Unsafe_GetNativeAddress)},
1075 {CC"putAddress", CC"("ADR""ADR")V", FN_PTR(Unsafe_SetNativeAddress)},
1076
1077 {CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
1078 {CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
1079 // {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
1080 // {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
1081 {CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
1082
1083 {CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)},
1084 {CC"staticFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_StaticFieldOffset)},
1085 {CC"staticFieldBase", CC"("FLD")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)},
1086 {CC"ensureClassInitialized",CC"("CLS")V", FN_PTR(Unsafe_EnsureClassInitialized)},
1087 {CC"arrayBaseOffset", CC"("CLS")I", FN_PTR(Unsafe_ArrayBaseOffset)},
1088 {CC"arrayIndexScale", CC"("CLS")I", FN_PTR(Unsafe_ArrayIndexScale)},
1089 {CC"addressSize", CC"()I", FN_PTR(Unsafe_AddressSize)},
1090 {CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
1091
1092 {CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
1093 {CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
1094 {CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
1095 {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
1096 {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
1097 {CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)}
1098
1099 };
1100
1101 // These are the old methods prior to the JSR 166 changes in 1.6.0
1102 static JNINativeMethod methods_15[] = {
1103
1104 {CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)},
1105 {CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)},
1106 {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObjectVolatile)},
1107 {CC"putObjectVolatile",CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObjectVolatile)},
1108
1109
1110 DECLARE_GETSETOOP(Boolean, Z),
1111 DECLARE_GETSETOOP(Byte, B),
1112 DECLARE_GETSETOOP(Short, S),
1113 DECLARE_GETSETOOP(Char, C),
1114 DECLARE_GETSETOOP(Int, I),
1115 DECLARE_GETSETOOP(Long, J),
1116 DECLARE_GETSETOOP(Float, F),
1117 DECLARE_GETSETOOP(Double, D),
1118
1119 DECLARE_GETSETNATIVE(Byte, B),
1120 DECLARE_GETSETNATIVE(Short, S),
1121 DECLARE_GETSETNATIVE(Char, C),
1122 DECLARE_GETSETNATIVE(Int, I),
1123 DECLARE_GETSETNATIVE(Long, J),
1124 DECLARE_GETSETNATIVE(Float, F),
1125 DECLARE_GETSETNATIVE(Double, D),
1126
1127 {CC"getAddress", CC"("ADR")"ADR, FN_PTR(Unsafe_GetNativeAddress)},
1128 {CC"putAddress", CC"("ADR""ADR")V", FN_PTR(Unsafe_SetNativeAddress)},
1129
1130 {CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
1131 {CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
1132 // {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
1133 // {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
1134 {CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
1135
1136 {CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)},
1137 {CC"staticFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_StaticFieldOffset)},
1138 {CC"staticFieldBase", CC"("FLD")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)},
1139 {CC"ensureClassInitialized",CC"("CLS")V", FN_PTR(Unsafe_EnsureClassInitialized)},
1140 {CC"arrayBaseOffset", CC"("CLS")I", FN_PTR(Unsafe_ArrayBaseOffset)},
1141 {CC"arrayIndexScale", CC"("CLS")I", FN_PTR(Unsafe_ArrayIndexScale)},
1142 {CC"addressSize", CC"()I", FN_PTR(Unsafe_AddressSize)},
1143 {CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
1144
1145 {CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
1146 {CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
1147 {CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
1148 {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
1149 {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
1150 {CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
1151 {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
1152 {CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
1153 {CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)},
1154 {CC"park", CC"(ZJ)V", FN_PTR(Unsafe_Park)},
1155 {CC"unpark", CC"("OBJ")V", FN_PTR(Unsafe_Unpark)}
1156
1157 };
1158
1159 // These are the correct methods, moving forward:
1160 static JNINativeMethod methods[] = {
1161
1162 {CC"getObject", CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObject)},
1163 {CC"putObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObject)},
1164 {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"", FN_PTR(Unsafe_GetObjectVolatile)},
1165 {CC"putObjectVolatile",CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetObjectVolatile)},
1166
1167
1168 DECLARE_GETSETOOP(Boolean, Z),
1169 DECLARE_GETSETOOP(Byte, B),
1170 DECLARE_GETSETOOP(Short, S),
1171 DECLARE_GETSETOOP(Char, C),
1172 DECLARE_GETSETOOP(Int, I),
1173 DECLARE_GETSETOOP(Long, J),
1174 DECLARE_GETSETOOP(Float, F),
1175 DECLARE_GETSETOOP(Double, D),
1176
1177 DECLARE_GETSETNATIVE(Byte, B),
1178 DECLARE_GETSETNATIVE(Short, S),
1179 DECLARE_GETSETNATIVE(Char, C),
1180 DECLARE_GETSETNATIVE(Int, I),
1181 DECLARE_GETSETNATIVE(Long, J),
1182 DECLARE_GETSETNATIVE(Float, F),
1183 DECLARE_GETSETNATIVE(Double, D),
1184
1185 {CC"getAddress", CC"("ADR")"ADR, FN_PTR(Unsafe_GetNativeAddress)},
1186 {CC"putAddress", CC"("ADR""ADR")V", FN_PTR(Unsafe_SetNativeAddress)},
1187
1188 {CC"allocateMemory", CC"(J)"ADR, FN_PTR(Unsafe_AllocateMemory)},
1189 {CC"reallocateMemory", CC"("ADR"J)"ADR, FN_PTR(Unsafe_ReallocateMemory)},
1190 // {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
1191 // {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)},
1192 {CC"freeMemory", CC"("ADR")V", FN_PTR(Unsafe_FreeMemory)},
1193
1194 {CC"objectFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_ObjectFieldOffset)},
1195 {CC"staticFieldOffset", CC"("FLD")J", FN_PTR(Unsafe_StaticFieldOffset)},
1196 {CC"staticFieldBase", CC"("FLD")"OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)},
1197 {CC"ensureClassInitialized",CC"("CLS")V", FN_PTR(Unsafe_EnsureClassInitialized)},
1198 {CC"arrayBaseOffset", CC"("CLS")I", FN_PTR(Unsafe_ArrayBaseOffset)},
1199 {CC"arrayIndexScale", CC"("CLS")I", FN_PTR(Unsafe_ArrayIndexScale)},
1200 {CC"addressSize", CC"()I", FN_PTR(Unsafe_AddressSize)},
1201 {CC"pageSize", CC"()I", FN_PTR(Unsafe_PageSize)},
1202
1203 {CC"defineClass", CC"("DC0_Args")"CLS, FN_PTR(Unsafe_DefineClass0)},
1204 {CC"defineClass", CC"("DC1_Args")"CLS, FN_PTR(Unsafe_DefineClass1)},
1205 {CC"allocateInstance", CC"("CLS")"OBJ, FN_PTR(Unsafe_AllocateInstance)},
1206 {CC"monitorEnter", CC"("OBJ")V", FN_PTR(Unsafe_MonitorEnter)},
1207 {CC"monitorExit", CC"("OBJ")V", FN_PTR(Unsafe_MonitorExit)},
1208 {CC"tryMonitorEnter", CC"("OBJ")Z", FN_PTR(Unsafe_TryMonitorEnter)},
1209 {CC"throwException", CC"("THR")V", FN_PTR(Unsafe_ThrowException)},
1210 {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z", FN_PTR(Unsafe_CompareAndSwapObject)},
1211 {CC"compareAndSwapInt", CC"("OBJ"J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)},
1212 {CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)},
1213 {CC"putOrderedObject", CC"("OBJ"J"OBJ")V", FN_PTR(Unsafe_SetOrderedObject)},
1214 {CC"putOrderedInt", CC"("OBJ"JI)V", FN_PTR(Unsafe_SetOrderedInt)},
1215 {CC"putOrderedLong", CC"("OBJ"JJ)V", FN_PTR(Unsafe_SetOrderedLong)},
1216 {CC"park", CC"(ZJ)V", FN_PTR(Unsafe_Park)},
1217 {CC"unpark", CC"("OBJ")V", FN_PTR(Unsafe_Unpark)}
1218
1219 // {CC"getLoadAverage", CC"([DI)I", FN_PTR(Unsafe_Loadavg)},
1220
1221 // {CC"prefetchRead", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchRead)},
1222 // {CC"prefetchWrite", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchWrite)}
1223 // {CC"prefetchReadStatic", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchRead)},
1224 // {CC"prefetchWriteStatic",CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchWrite)}
1225
1226 };
1227
1228 JNINativeMethod loadavg_method[] = {
1229 {CC"getLoadAverage", CC"([DI)I", FN_PTR(Unsafe_Loadavg)}
1230 };
1231
1232 JNINativeMethod prefetch_methods[] = {
1233 {CC"prefetchRead", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchRead)},
1234 {CC"prefetchWrite", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchWrite)},
1235 {CC"prefetchReadStatic", CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchRead)},
1236 {CC"prefetchWriteStatic",CC"("OBJ"J)V", FN_PTR(Unsafe_PrefetchWrite)}
1237 };
1238
1239 JNINativeMethod memcopy_methods[] = {
1240 {CC"copyMemory", CC"("OBJ"J"OBJ"JJ)V", FN_PTR(Unsafe_CopyMemory2)},
1241 {CC"setMemory", CC"("OBJ"JJB)V", FN_PTR(Unsafe_SetMemory2)}
1242 };
1243
1244 JNINativeMethod memcopy_methods_15[] = {
1245 {CC"setMemory", CC"("ADR"JB)V", FN_PTR(Unsafe_SetMemory)},
1246 {CC"copyMemory", CC"("ADR ADR"J)V", FN_PTR(Unsafe_CopyMemory)}
1247 };
1248
1249
1250 #undef CC
1251 #undef FN_PTR
1252
1253 #undef ADR
1254 #undef LANG
1255 #undef OBJ
1256 #undef CLS
1257 #undef CTR
1258 #undef FLD
1259 #undef MTH
1260 #undef THR
1261 #undef DC0_Args
1262 #undef DC1_Args
1263
1264 #undef DECLARE_GETSETOOP
1265 #undef DECLARE_GETSETNATIVE
1266
1267
1268 // This one function is exported, used by NativeLookup.
1269 // The Unsafe_xxx functions above are called only from the interpreter.
1270 // The optimizer looks at names and signatures to recognize
1271 // individual functions.
1272
1273 JVM_ENTRY(void, JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls))
1274 UnsafeWrapper("JVM_RegisterUnsafeMethods");
1275 {
1276 ThreadToNativeFromVM ttnfv(thread);
1277 {
1278 env->RegisterNatives(unsafecls, loadavg_method, sizeof(loadavg_method)/sizeof(JNINativeMethod));
1279 if (env->ExceptionOccurred()) {
1280 if (PrintMiscellaneous && (Verbose || WizardMode)) {
1281 tty->print_cr("Warning: SDK 1.6 Unsafe.loadavg not found.");
1282 }
1283 env->ExceptionClear();
1284 }
1285 }
1286 {
1287 env->RegisterNatives(unsafecls, prefetch_methods, sizeof(prefetch_methods)/sizeof(JNINativeMethod));
1288 if (env->ExceptionOccurred()) {
1289 if (PrintMiscellaneous && (Verbose || WizardMode)) {
1290 tty->print_cr("Warning: SDK 1.6 Unsafe.prefetchRead/Write not found.");
1291 }
1292 env->ExceptionClear();
1293 }
1294 }
1295 {
1296 env->RegisterNatives(unsafecls, memcopy_methods, sizeof(memcopy_methods)/sizeof(JNINativeMethod));
1297 if (env->ExceptionOccurred()) {
1298 if (PrintMiscellaneous && (Verbose || WizardMode)) {
1299 tty->print_cr("Warning: SDK 1.7 Unsafe.copyMemory not found.");
1300 }
1301 env->ExceptionClear();
1302 env->RegisterNatives(unsafecls, memcopy_methods_15, sizeof(memcopy_methods_15)/sizeof(JNINativeMethod));
1303 if (env->ExceptionOccurred()) {
1304 if (PrintMiscellaneous && (Verbose || WizardMode)) {
1305 tty->print_cr("Warning: SDK 1.5 Unsafe.copyMemory not found.");
1306 }
1307 env->ExceptionClear();
1308 }
1309 }
1310 }
1311 int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod));
1312 if (env->ExceptionOccurred()) {
1313 if (PrintMiscellaneous && (Verbose || WizardMode)) {
1314 tty->print_cr("Warning: SDK 1.6 version of Unsafe not found.");
1315 }
1316 env->ExceptionClear();
1317 // %%% For now, be backward compatible with an older class:
1318 status = env->RegisterNatives(unsafecls, methods_15, sizeof(methods_15)/sizeof(JNINativeMethod));
1319 }
1320 if (env->ExceptionOccurred()) {
1321 if (PrintMiscellaneous && (Verbose || WizardMode)) {
1322 tty->print_cr("Warning: SDK 1.5 version of Unsafe not found.");
1323 }
1324 env->ExceptionClear();
1325 // %%% For now, be backward compatible with an older class:
1326 status = env->RegisterNatives(unsafecls, methods_141, sizeof(methods_141)/sizeof(JNINativeMethod));
1327 }
1328 if (env->ExceptionOccurred()) {
1329 if (PrintMiscellaneous && (Verbose || WizardMode)) {
1330 tty->print_cr("Warning: SDK 1.4.1 version of Unsafe not found.");
1331 }
1332 env->ExceptionClear();
1333 // %%% For now, be backward compatible with an older class:
1334 status = env->RegisterNatives(unsafecls, methods_140, sizeof(methods_140)/sizeof(JNINativeMethod));
1335 }
1336 guarantee(status == 0, "register unsafe natives");
1337 }
1338 JVM_END