unsafe.cpp revision 113:ba764ed4b6f2
1201342Snyan/*
2201342Snyan * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
3201342Snyan * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4201342Snyan *
5201342Snyan * This code is free software; you can redistribute it and/or modify it
6201342Snyan * under the terms of the GNU General Public License version 2 only, as
7201342Snyan * published by the Free Software Foundation.
8201342Snyan *
9201342Snyan * This code is distributed in the hope that it will be useful, but WITHOUT
10201342Snyan * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11201342Snyan * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12201342Snyan * version 2 for more details (a copy is included in the LICENSE file that
13201342Snyan * accompanied this code).
14201342Snyan *
15201342Snyan * You should have received a copy of the GNU General Public License version
16201342Snyan * 2 along with this work; if not, write to the Free Software Foundation,
17201342Snyan * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18201342Snyan *
19201342Snyan * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20201342Snyan * CA 95054 USA or visit www.sun.com if you need additional information or
21201342Snyan * have any questions.
22201342Snyan *
23201342Snyan */
24201342Snyan
25201342Snyan/*
26201342Snyan *      Implementation of class sun.misc.Unsafe
27201342Snyan */
28201342Snyan
29201342Snyan#include "incls/_precompiled.incl"
30201342Snyan#include "incls/_unsafe.cpp.incl"
31201342Snyan
32201342Snyan#define MAX_OBJECT_SIZE \
33201342Snyan  ( arrayOopDesc::header_size(T_DOUBLE) * HeapWordSize \
34201342Snyan    + ((julong)max_jint * sizeof(double)) )
35201342Snyan
36201342Snyan
37201342Snyan#define UNSAFE_ENTRY(result_type, header) \
38201342Snyan  JVM_ENTRY(result_type, header)
39201342Snyan
40201342Snyan// Can't use UNSAFE_LEAF because it has the signature of a straight
41201342Snyan// call into the runtime (just like JVM_LEAF, funny that) but it's
42201342Snyan// called like a Java Native and thus the wrapper built for it passes
43201342Snyan// arguments like a JNI call.  It expects those arguments to be popped
44201342Snyan// from the stack on Intel like all good JNI args are, and adjusts the
45201342Snyan// stack according.  Since the JVM_LEAF call expects no extra
46201342Snyan// arguments the stack isn't popped in the C code, is pushed by the
47201342Snyan// wrapper and we get sick.
48201342Snyan//#define UNSAFE_LEAF(result_type, header) \
49201342Snyan//  JVM_LEAF(result_type, header)
50201342Snyan
51201342Snyan#define UNSAFE_END JVM_END
52201342Snyan
53201342Snyan#define UnsafeWrapper(arg) /*nothing, for the present*/
54201342Snyan
55201342Snyan
56201342Snyaninline void* addr_from_java(jlong addr) {
57201342Snyan  // This assert fails in a variety of ways on 32-bit systems.
58201342Snyan  // It is impossible to predict whether native code that converts
59201342Snyan  // pointers to longs will sign-extend or zero-extend the addresses.
60201342Snyan  //assert(addr == (uintptr_t)addr, "must not be odd high bits");
61201342Snyan  return (void*)(uintptr_t)addr;
62201342Snyan}
63201342Snyan
64201342Snyaninline jlong addr_to_java(void* p) {
65201342Snyan  assert(p == (void*)(uintptr_t)p, "must not be odd high bits");
66201342Snyan  return (uintptr_t)p;
67201342Snyan}
68201342Snyan
69201342Snyan
70201342Snyan// Note: The VM's obj_field and related accessors use byte-scaled
71201342Snyan// ("unscaled") offsets, just as the unsafe methods do.
72201342Snyan
73201342Snyan// However, the method Unsafe.fieldOffset explicitly declines to
74201342Snyan// guarantee this.  The field offset values manipulated by the Java user
75201342Snyan// through the Unsafe API are opaque cookies that just happen to be byte
76201342Snyan// offsets.  We represent this state of affairs by passing the cookies
77201342Snyan// through conversion functions when going between the VM and the Unsafe API.
78201342Snyan// The conversion functions just happen to be no-ops at present.
79226506Sdes
80226506Sdesinline jlong field_offset_to_byte_offset(jlong field_offset) {
81201342Snyan  return field_offset;
82201342Snyan}
83201342Snyan
84201342Snyaninline jlong field_offset_from_byte_offset(jlong byte_offset) {
85201342Snyan  return byte_offset;
86201342Snyan}
87201342Snyan
88201342Snyaninline jint invocation_key_from_method_slot(jint slot) {
89201342Snyan  return slot;
90201342Snyan}
91201342Snyan
92201342Snyaninline jint invocation_key_to_method_slot(jint key) {
93201342Snyan  return key;
94201342Snyan}
95201342Snyan
96201342Snyaninline void* index_oop_from_field_offset_long(oop p, jlong field_offset) {
97201342Snyan  jlong byte_offset = field_offset_to_byte_offset(field_offset);
98201342Snyan#ifdef ASSERT
99201342Snyan  if (p != NULL) {
100201342Snyan    assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset");
101201342Snyan    if (byte_offset == (jint)byte_offset) {
102201342Snyan      void* ptr_plus_disp = (address)p + byte_offset;
103201342Snyan      assert((void*)p->obj_field_addr<oop>((jint)byte_offset) == ptr_plus_disp,
104201342Snyan             "raw [ptr+disp] must be consistent with oop::field_base");
105201342Snyan    }
106201342Snyan  }
107201342Snyan#endif
108201342Snyan  if (sizeof(char*) == sizeof(jint))    // (this constant folds!)
109201342Snyan    return (address)p + (jint) byte_offset;
110201342Snyan  else
111201342Snyan    return (address)p +        byte_offset;
112201342Snyan}
113201342Snyan
114201342Snyan// Externally callable versions:
115201342Snyan// (Use these in compiler intrinsics which emulate unsafe primitives.)
116201342Snyanjlong Unsafe_field_offset_to_byte_offset(jlong field_offset) {
117201342Snyan  return field_offset;
118201342Snyan}
119201342Snyanjlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) {
120201342Snyan  return byte_offset;
121201342Snyan}
122201342Snyanjint Unsafe_invocation_key_from_method_slot(jint slot) {
123201342Snyan  return invocation_key_from_method_slot(slot);
124201342Snyan}
125201342Snyanjint Unsafe_invocation_key_to_method_slot(jint key) {
126201342Snyan  return invocation_key_to_method_slot(key);
127201342Snyan}
128201342Snyan
129239063Snyan
130239063Snyan///// Data in the Java heap.
131201342Snyan
132201342Snyan#define GET_FIELD(obj, offset, type_name, v) \
133232784Snyan  oop p = JNIHandles::resolve(obj); \
134239063Snyan  type_name v = *(type_name*)index_oop_from_field_offset_long(p, offset)
135239063Snyan
136201342Snyan#define SET_FIELD(obj, offset, type_name, x) \
137201342Snyan  oop p = JNIHandles::resolve(obj); \
138219960Snyan  *(type_name*)index_oop_from_field_offset_long(p, offset) = x
139201342Snyan
140201342Snyan#define GET_FIELD_VOLATILE(obj, offset, type_name, v) \
141201342Snyan  oop p = JNIHandles::resolve(obj); \
142201342Snyan  volatile type_name v = *(volatile type_name*)index_oop_from_field_offset_long(p, offset)
143201342Snyan
144201342Snyan#define SET_FIELD_VOLATILE(obj, offset, type_name, x) \
145201342Snyan  oop p = JNIHandles::resolve(obj); \
146201342Snyan  *(volatile type_name*)index_oop_from_field_offset_long(p, offset) = x; \
147201342Snyan  OrderAccess::fence();
148201342Snyan
149201342Snyan// Macros for oops that check UseCompressedOops
150220685Snyan
151201342Snyan#define GET_OOP_FIELD(obj, offset, v) \
152201342Snyan  oop p = JNIHandles::resolve(obj);   \
153201342Snyan  oop v;                              \
154201342Snyan  if (UseCompressedOops) {            \
155201342Snyan    narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); \
156201342Snyan    v = oopDesc::decode_heap_oop(n);                                \
157201342Snyan  } else {                            \
158201342Snyan    v = *(oop*)index_oop_from_field_offset_long(p, offset);                 \
159201342Snyan  }
160201342Snyan
161201342Snyan#define GET_OOP_FIELD_VOLATILE(obj, offset, v) \
162201342Snyan  oop p = JNIHandles::resolve(obj);   \
163201342Snyan  volatile oop v;                     \
164201342Snyan  if (UseCompressedOops) {            \
165201342Snyan    volatile narrowOop n = *(volatile narrowOop*)index_oop_from_field_offset_long(p, offset); \
166201342Snyan    v = oopDesc::decode_heap_oop(n);                               \
167201342Snyan  } else {                            \
168201342Snyan    v = *(volatile oop*)index_oop_from_field_offset_long(p, offset);       \
169201342Snyan  }
170201342Snyan
171201342Snyan
172201342Snyan// Get/SetObject must be special-cased, since it works with handles.
173201342Snyan
174235988Sgleb// The xxx140 variants for backward compatibility do not allow a full-width offset.
175201342SnyanUNSAFE_ENTRY(jobject, Unsafe_GetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset))
176201342Snyan  UnsafeWrapper("Unsafe_GetObject");
177201342Snyan  if (obj == NULL)  THROW_0(vmSymbols::java_lang_NullPointerException());
178201342Snyan  GET_OOP_FIELD(obj, offset, v)
179201342Snyan  return JNIHandles::make_local(env, v);
180201342SnyanUNSAFE_END
181201342Snyan
182201342SnyanUNSAFE_ENTRY(void, Unsafe_SetObject140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jobject x_h))
183201342Snyan  UnsafeWrapper("Unsafe_SetObject");
184201342Snyan  if (obj == NULL)  THROW(vmSymbols::java_lang_NullPointerException());
185201342Snyan  oop x = JNIHandles::resolve(x_h);
186201342Snyan  //SET_FIELD(obj, offset, oop, x);
187201342Snyan  oop p = JNIHandles::resolve(obj);
188201342Snyan  if (UseCompressedOops) {
189201342Snyan    if (x != NULL) {
190201342Snyan      // If there is a heap base pointer, we are obliged to emit a store barrier.
191201342Snyan      oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
192201342Snyan    } else {
193201342Snyan      narrowOop n = oopDesc::encode_heap_oop_not_null(x);
194201342Snyan      *(narrowOop*)index_oop_from_field_offset_long(p, offset) = n;
195201342Snyan    }
196201342Snyan  } else {
197201342Snyan    if (x != NULL) {
198201342Snyan      // If there is a heap base pointer, we are obliged to emit a store barrier.
199201342Snyan      oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
200201342Snyan    } else {
201201342Snyan      *(oop*)index_oop_from_field_offset_long(p, offset) = x;
202201342Snyan    }
203201342Snyan  }
204201342SnyanUNSAFE_END
205201342Snyan
206201342Snyan// The normal variants allow a null base pointer with an arbitrary address.
207201342Snyan// But if the base pointer is non-null, the offset should make some sense.
208201342Snyan// That is, it should be in the range [0, MAX_OBJECT_SIZE].
209201342SnyanUNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
210201342Snyan  UnsafeWrapper("Unsafe_GetObject");
211201342Snyan  GET_OOP_FIELD(obj, offset, v)
212201342Snyan  return JNIHandles::make_local(env, v);
213201342SnyanUNSAFE_END
214201342Snyan
215201342SnyanUNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
216201342Snyan  UnsafeWrapper("Unsafe_SetObject");
217201342Snyan  oop x = JNIHandles::resolve(x_h);
218201342Snyan  oop p = JNIHandles::resolve(obj);
219201342Snyan  if (UseCompressedOops) {
220201342Snyan    oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
221201342Snyan  } else {
222201342Snyan    oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
223201342Snyan  }
224201342SnyanUNSAFE_END
225201342Snyan
226201342SnyanUNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
227201342Snyan  UnsafeWrapper("Unsafe_GetObjectVolatile");
228201342Snyan  GET_OOP_FIELD_VOLATILE(obj, offset, v)
229201342Snyan  return JNIHandles::make_local(env, v);
230201342SnyanUNSAFE_END
231201342Snyan
232201342SnyanUNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
233201342Snyan  UnsafeWrapper("Unsafe_SetObjectVolatile");
234201342Snyan  oop x = JNIHandles::resolve(x_h);
235201342Snyan  oop p = JNIHandles::resolve(obj);
236201342Snyan  if (UseCompressedOops) {
237201342Snyan    oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
238201342Snyan  } else {
239201342Snyan    oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
240201342Snyan  }
241201342Snyan  OrderAccess::fence();
242201342SnyanUNSAFE_END
243201342Snyan
244201342Snyan// Volatile long versions must use locks if !VM_Version::supports_cx8().
245201342Snyan// support_cx8 is a surrogate for 'supports atomic long memory ops'.
246201342Snyan
247201342SnyanUNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset))
248201342Snyan  UnsafeWrapper("Unsafe_GetLongVolatile");
249201342Snyan  {
250201342Snyan    if (VM_Version::supports_cx8()) {
251201342Snyan      GET_FIELD_VOLATILE(obj, offset, jlong, v);
252201342Snyan      return v;
253201342Snyan    }
254201342Snyan    else {
255201342Snyan      Handle p (THREAD, JNIHandles::resolve(obj));
256201342Snyan      jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
257201342Snyan      ObjectLocker ol(p, THREAD);
258201342Snyan      jlong value = *addr;
259201342Snyan      return value;
260201342Snyan    }
261201342Snyan  }
262201342SnyanUNSAFE_END
263201342Snyan
264201342SnyanUNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
265201342Snyan  UnsafeWrapper("Unsafe_SetLongVolatile");
266201342Snyan  {
267201342Snyan    if (VM_Version::supports_cx8()) {
268201342Snyan      SET_FIELD_VOLATILE(obj, offset, jlong, x);
269201342Snyan    }
270201342Snyan    else {
271201342Snyan      Handle p (THREAD, JNIHandles::resolve(obj));
272201342Snyan      jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
273201342Snyan      ObjectLocker ol(p, THREAD);
274201342Snyan      *addr = x;
275201342Snyan    }
276201342Snyan  }
277201342SnyanUNSAFE_END
278201342Snyan
279201342Snyan
280201342Snyan#define DEFINE_GETSETOOP(jboolean, Boolean) \
281201342Snyan \
282201342SnyanUNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \
283201342Snyan  UnsafeWrapper("Unsafe_Get"#Boolean); \
284201342Snyan  if (obj == NULL)  THROW_0(vmSymbols::java_lang_NullPointerException()); \
285201342Snyan  GET_FIELD(obj, offset, jboolean, v); \
286201342Snyan  return v; \
287201342SnyanUNSAFE_END \
288201342Snyan \
289201342SnyanUNSAFE_ENTRY(void, Unsafe_Set##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jboolean x)) \
290201342Snyan  UnsafeWrapper("Unsafe_Set"#Boolean); \
291201342Snyan  if (obj == NULL)  THROW(vmSymbols::java_lang_NullPointerException()); \
292201342Snyan  SET_FIELD(obj, offset, jboolean, x); \
293201342SnyanUNSAFE_END \
294201342Snyan \
295201342SnyanUNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \
296201342Snyan  UnsafeWrapper("Unsafe_Get"#Boolean); \
297201342Snyan  GET_FIELD(obj, offset, jboolean, v); \
298201342Snyan  return v; \
299201342SnyanUNSAFE_END \
300201342Snyan \
301201342SnyanUNSAFE_ENTRY(void, Unsafe_Set##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \
302201342Snyan  UnsafeWrapper("Unsafe_Set"#Boolean); \
303201342Snyan  SET_FIELD(obj, offset, jboolean, x); \
304201342SnyanUNSAFE_END \
305201342Snyan \
306201342Snyan// END DEFINE_GETSETOOP.
307201342Snyan
308201342Snyan
309201342Snyan#define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \
310201342Snyan \
311201342SnyanUNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \
312201342Snyan  UnsafeWrapper("Unsafe_Get"#Boolean); \
313201342Snyan  GET_FIELD_VOLATILE(obj, offset, jboolean, v); \
314201342Snyan  return v; \
315201342SnyanUNSAFE_END \
316201342Snyan \
317201342SnyanUNSAFE_ENTRY(void, Unsafe_Set##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \
318201342Snyan  UnsafeWrapper("Unsafe_Set"#Boolean); \
319201342Snyan  SET_FIELD_VOLATILE(obj, offset, jboolean, x); \
320201342SnyanUNSAFE_END \
321201342Snyan \
322201342Snyan// END DEFINE_GETSETOOP_VOLATILE.
323201342Snyan
324201342SnyanDEFINE_GETSETOOP(jboolean, Boolean)
325201342SnyanDEFINE_GETSETOOP(jbyte, Byte)
326201342SnyanDEFINE_GETSETOOP(jshort, Short);
327201342SnyanDEFINE_GETSETOOP(jchar, Char);
328201342SnyanDEFINE_GETSETOOP(jint, Int);
329201342SnyanDEFINE_GETSETOOP(jlong, Long);
330201342SnyanDEFINE_GETSETOOP(jfloat, Float);
331201342SnyanDEFINE_GETSETOOP(jdouble, Double);
332201342Snyan
333254015SmarcelDEFINE_GETSETOOP_VOLATILE(jboolean, Boolean)
334201342SnyanDEFINE_GETSETOOP_VOLATILE(jbyte, Byte)
335254015SmarcelDEFINE_GETSETOOP_VOLATILE(jshort, Short);
336254015SmarcelDEFINE_GETSETOOP_VOLATILE(jchar, Char);
337201342SnyanDEFINE_GETSETOOP_VOLATILE(jint, Int);
338201342Snyan// no long -- handled specially
339201342SnyanDEFINE_GETSETOOP_VOLATILE(jfloat, Float);
340201342SnyanDEFINE_GETSETOOP_VOLATILE(jdouble, Double);
341201342Snyan
342201342Snyan#undef DEFINE_GETSETOOP
343201342Snyan
344201342Snyan// The non-intrinsified versions of setOrdered just use setVolatile
345201342Snyan
346201342SnyanUNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) \
347201342Snyan  UnsafeWrapper("Unsafe_SetOrderedInt"); \
348201342Snyan  SET_FIELD_VOLATILE(obj, offset, jint, x); \
349201342SnyanUNSAFE_END
350201342Snyan
351201342SnyanUNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h))
352218737Snyan  UnsafeWrapper("Unsafe_SetOrderedObject");
353235988Sgleb  oop x = JNIHandles::resolve(x_h);
354232784Snyan  oop p = JNIHandles::resolve(obj);
355201342Snyan  if (UseCompressedOops) {
356201342Snyan    oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x);
357201342Snyan  } else {
358201342Snyan    oop_store((oop*)index_oop_from_field_offset_long(p, offset), x);
359201342Snyan  }
360201342Snyan  OrderAccess::fence();
361201342SnyanUNSAFE_END
362201342Snyan
363201342SnyanUNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x))
364201342Snyan  UnsafeWrapper("Unsafe_SetOrderedLong");
365201342Snyan  {
366201342Snyan    if (VM_Version::supports_cx8()) {
367201342Snyan      SET_FIELD_VOLATILE(obj, offset, jlong, x);
368201342Snyan    }
369201342Snyan    else {
370201342Snyan      Handle p (THREAD, JNIHandles::resolve(obj));
371201342Snyan      jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
372201342Snyan      ObjectLocker ol(p, THREAD);
373201342Snyan      *addr = x;
374201342Snyan    }
375201342Snyan  }
376201342SnyanUNSAFE_END
377201342Snyan
378201342Snyan////// Data in the C heap.
379201342Snyan
380226506Sdes// Note:  These do not throw NullPointerException for bad pointers.
381232784Snyan// They just crash.  Only a oop base pointer can generate a NullPointerException.
382232784Snyan//
383232784Snyan#define DEFINE_GETSETNATIVE(java_type, Type, native_type) \
384232784Snyan \
385201342SnyanUNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) \
386201342Snyan  UnsafeWrapper("Unsafe_GetNative"#Type); \
387201342Snyan  void* p = addr_from_java(addr); \
388201342Snyan  JavaThread* t = JavaThread::current(); \
389201342Snyan  t->set_doing_unsafe_access(true); \
390201342Snyan  java_type x = *(volatile native_type*)p; \
391201342Snyan  t->set_doing_unsafe_access(false); \
392201342Snyan  return x; \
393201342SnyanUNSAFE_END \
394201342Snyan \
395201342SnyanUNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) \
396201342Snyan  UnsafeWrapper("Unsafe_SetNative"#Type); \
397201342Snyan  JavaThread* t = JavaThread::current(); \
398201342Snyan  t->set_doing_unsafe_access(true); \
399201342Snyan  void* p = addr_from_java(addr); \
400201342Snyan  *(volatile native_type*)p = x; \
401232784Snyan  t->set_doing_unsafe_access(false); \
402219225SnyanUNSAFE_END \
403232784Snyan \
404201342Snyan// END DEFINE_GETSETNATIVE.
405219225Snyan
406201342SnyanDEFINE_GETSETNATIVE(jbyte, Byte, signed char)
407201342SnyanDEFINE_GETSETNATIVE(jshort, Short, signed short);
408201342SnyanDEFINE_GETSETNATIVE(jchar, Char, unsigned short);
409201342SnyanDEFINE_GETSETNATIVE(jint, Int, jint);
410201342Snyan// no long -- handled specially
411201342SnyanDEFINE_GETSETNATIVE(jfloat, Float, float);
412201342SnyanDEFINE_GETSETNATIVE(jdouble, Double, double);
413201342Snyan
414201342Snyan#undef DEFINE_GETSETNATIVE
415201342Snyan
416201342SnyanUNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr))
417201342Snyan  UnsafeWrapper("Unsafe_GetNativeLong");
418201342Snyan  JavaThread* t = JavaThread::current();
419201342Snyan  // We do it this way to avoid problems with access to heap using 64
420219225Snyan  // bit loads, as jlong in heap could be not 64-bit aligned, and on
421201342Snyan  // some CPUs (SPARC) it leads to SIGBUS.
422201342Snyan  t->set_doing_unsafe_access(true);
423201342Snyan  void* p = addr_from_java(addr);
424201342Snyan  jlong x;
425201342Snyan  if (((intptr_t)p & 7) == 0) {
426201342Snyan    // jlong is aligned, do a volatile access
427201342Snyan    x = *(volatile jlong*)p;
428201342Snyan  } else {
429201342Snyan    jlong_accessor acc;
430201342Snyan    acc.words[0] = ((volatile jint*)p)[0];
431201342Snyan    acc.words[1] = ((volatile jint*)p)[1];
432201342Snyan    x = acc.long_value;
433201342Snyan  }
434201342Snyan  t->set_doing_unsafe_access(false);
435201342Snyan  return x;
436201342SnyanUNSAFE_END
437201342Snyan
438201342SnyanUNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x))
439201342Snyan  UnsafeWrapper("Unsafe_SetNativeLong");
440201342Snyan  JavaThread* t = JavaThread::current();
441201342Snyan  // see comment for Unsafe_GetNativeLong
442201342Snyan  t->set_doing_unsafe_access(true);
443201342Snyan  void* p = addr_from_java(addr);
444201342Snyan  if (((intptr_t)p & 7) == 0) {
445201342Snyan    // jlong is aligned, do a volatile access
446201342Snyan    *(volatile jlong*)p = x;
447201342Snyan  } else {
448235988Sgleb    jlong_accessor acc;
449219960Snyan    acc.long_value = x;
450218737Snyan    ((volatile jint*)p)[0] = acc.words[0];
451201342Snyan    ((volatile jint*)p)[1] = acc.words[1];
452201342Snyan  }
453201342Snyan  t->set_doing_unsafe_access(false);
454201342SnyanUNSAFE_END
455201342Snyan
456201342Snyan
457201342SnyanUNSAFE_ENTRY(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr))
458201342Snyan  UnsafeWrapper("Unsafe_GetNativeAddress");
459219960Snyan  void* p = addr_from_java(addr);
460219960Snyan  return addr_to_java(*(void**)p);
461201342SnyanUNSAFE_END
462201342Snyan
463201342SnyanUNSAFE_ENTRY(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x))
464201342Snyan  UnsafeWrapper("Unsafe_SetNativeAddress");
465201342Snyan  void* p = addr_from_java(addr);
466201342Snyan  *(void**)p = addr_from_java(x);
467201342SnyanUNSAFE_END
468201342Snyan
469219960Snyan
470201342Snyan////// Allocation requests
471201342Snyan
472201342SnyanUNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls))
473201342Snyan  UnsafeWrapper("Unsafe_AllocateInstance");
474201342Snyan  {
475201342Snyan    ThreadToNativeFromVM ttnfv(thread);
476201342Snyan    return env->AllocObject(cls);
477201342Snyan  }
478201342SnyanUNSAFE_END
479201342Snyan
480201342SnyanUNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size))
481201342Snyan  UnsafeWrapper("Unsafe_AllocateMemory");
482201342Snyan  size_t sz = (size_t)size;
483201342Snyan  if (sz != (julong)size || size < 0) {
484201342Snyan    THROW_0(vmSymbols::java_lang_IllegalArgumentException());
485201342Snyan  }
486201342Snyan  if (sz == 0) {
487201342Snyan    return 0;
488201342Snyan  }
489201342Snyan  sz = round_to(sz, HeapWordSize);
490201342Snyan  void* x = os::malloc(sz);
491214257Snyan  if (x == NULL) {
492201342Snyan    THROW_0(vmSymbols::java_lang_OutOfMemoryError());
493201342Snyan  }
494201342Snyan  //Copy::fill_to_words((HeapWord*)x, sz / HeapWordSize);
495201342Snyan  return addr_to_java(x);
496201342SnyanUNSAFE_END
497201342Snyan
498201342SnyanUNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory(JNIEnv *env, jobject unsafe, jlong addr, jlong size))
499201342Snyan  UnsafeWrapper("Unsafe_ReallocateMemory");
500218842Snyan  void* p = addr_from_java(addr);
501219960Snyan  size_t sz = (size_t)size;
502219960Snyan  if (sz != (julong)size || size < 0) {
503219960Snyan    THROW_0(vmSymbols::java_lang_IllegalArgumentException());
504201342Snyan  }
505219960Snyan  if (sz == 0) {
506201342Snyan    os::free(p);
507201342Snyan    return 0;
508201342Snyan  }
509201342Snyan  sz = round_to(sz, HeapWordSize);
510201342Snyan  void* x = (p == NULL) ? os::malloc(sz) : os::realloc(p, sz);
511201342Snyan  if (x == NULL) {
512201342Snyan    THROW_0(vmSymbols::java_lang_OutOfMemoryError());
513201342Snyan  }
514201342Snyan  return addr_to_java(x);
515201342SnyanUNSAFE_END
516201342Snyan
517201342SnyanUNSAFE_ENTRY(void, Unsafe_FreeMemory(JNIEnv *env, jobject unsafe, jlong addr))
518201342Snyan  UnsafeWrapper("Unsafe_FreeMemory");
519201342Snyan  void* p = addr_from_java(addr);
520201342Snyan  if (p == NULL) {
521201342Snyan    return;
522201342Snyan  }
523201342Snyan  os::free(p);
524201342SnyanUNSAFE_END
525201342Snyan
526201342SnyanUNSAFE_ENTRY(void, Unsafe_SetMemory(JNIEnv *env, jobject unsafe, jlong addr, jlong size, jbyte value))
527201342Snyan  UnsafeWrapper("Unsafe_SetMemory");
528201342Snyan  size_t sz = (size_t)size;
529201342Snyan  if (sz != (julong)size || size < 0) {
530201342Snyan    THROW(vmSymbols::java_lang_IllegalArgumentException());
531201342Snyan  }
532201342Snyan  char* p = (char*) addr_from_java(addr);
533201342Snyan  Copy::fill_to_memory_atomic(p, sz, value);
534201342SnyanUNSAFE_END
535201342Snyan
536201342SnyanUNSAFE_ENTRY(void, Unsafe_SetMemory2(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value))
537201342Snyan  UnsafeWrapper("Unsafe_SetMemory");
538201342Snyan  size_t sz = (size_t)size;
539201342Snyan  if (sz != (julong)size || size < 0) {
540201342Snyan    THROW(vmSymbols::java_lang_IllegalArgumentException());
541201342Snyan  }
542201342Snyan  oop base = JNIHandles::resolve(obj);
543201342Snyan  void* p = index_oop_from_field_offset_long(base, offset);
544201342Snyan  Copy::fill_to_memory_atomic(p, sz, value);
545201342SnyanUNSAFE_END
546201342Snyan
547201342SnyanUNSAFE_ENTRY(void, Unsafe_CopyMemory(JNIEnv *env, jobject unsafe, jlong srcAddr, jlong dstAddr, jlong size))
548201342Snyan  UnsafeWrapper("Unsafe_CopyMemory");
549201342Snyan  if (size == 0) {
550201342Snyan    return;
551201342Snyan  }
552201342Snyan  size_t sz = (size_t)size;
553201342Snyan  if (sz != (julong)size || size < 0) {
554201342Snyan    THROW(vmSymbols::java_lang_IllegalArgumentException());
555201342Snyan  }
556201342Snyan  void* src = addr_from_java(srcAddr);
557242863Snyan  void* dst = addr_from_java(dstAddr);
558242863Snyan  Copy::conjoint_memory_atomic(src, dst, sz);
559242863SnyanUNSAFE_END
560242863Snyan
561201342SnyanUNSAFE_ENTRY(void, Unsafe_CopyMemory2(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size))
562201342Snyan  UnsafeWrapper("Unsafe_CopyMemory");
563201342Snyan  if (size == 0) {
564201342Snyan    return;
565201342Snyan  }
566201342Snyan  size_t sz = (size_t)size;
567201342Snyan  if (sz != (julong)size || size < 0) {
568201342Snyan    THROW(vmSymbols::java_lang_IllegalArgumentException());
569201342Snyan  }
570201342Snyan  oop srcp = JNIHandles::resolve(srcObj);
571201342Snyan  oop dstp = JNIHandles::resolve(dstObj);
572201342Snyan  if (dstp != NULL && !dstp->is_typeArray()) {
573201342Snyan    // NYI:  This works only for non-oop arrays at present.
574201342Snyan    // Generalizing it would be reasonable, but requires card marking.
575201342Snyan    // Also, autoboxing a Long from 0L in copyMemory(x,y, 0L,z, n) would be bad.
576201342Snyan    THROW(vmSymbols::java_lang_IllegalArgumentException());
577201342Snyan  }
578201342Snyan  void* src = index_oop_from_field_offset_long(srcp, srcOffset);
579201342Snyan  void* dst = index_oop_from_field_offset_long(dstp, dstOffset);
580201342Snyan  Copy::conjoint_memory_atomic(src, dst, sz);
581201342SnyanUNSAFE_END
582201342Snyan
583201342Snyan
584201342Snyan////// Random queries
585201342Snyan
586254015Smarcel// See comment at file start about UNSAFE_LEAF
587201342Snyan//UNSAFE_LEAF(jint, Unsafe_AddressSize())
588201342SnyanUNSAFE_ENTRY(jint, Unsafe_AddressSize(JNIEnv *env, jobject unsafe))
589201342Snyan  UnsafeWrapper("Unsafe_AddressSize");
590201342Snyan  return sizeof(void*);
591201342SnyanUNSAFE_END
592201342Snyan
593201342Snyan// See comment at file start about UNSAFE_LEAF
594201342Snyan//UNSAFE_LEAF(jint, Unsafe_PageSize())
595201342SnyanUNSAFE_ENTRY(jint, Unsafe_PageSize(JNIEnv *env, jobject unsafe))
596201342Snyan  UnsafeWrapper("Unsafe_PageSize");
597201342Snyan  return os::vm_page_size();
598201342SnyanUNSAFE_END
599201342Snyan
600201342Snyanjint find_field_offset(jobject field, int must_be_static, TRAPS) {
601201342Snyan  if (field == NULL) {
602232784Snyan    THROW_0(vmSymbols::java_lang_NullPointerException());
603232784Snyan  }
604232784Snyan
605232784Snyan  oop reflected   = JNIHandles::resolve_non_null(field);
606232784Snyan  oop mirror      = java_lang_reflect_Field::clazz(reflected);
607232784Snyan  klassOop k      = java_lang_Class::as_klassOop(mirror);
608201342Snyan  int slot        = java_lang_reflect_Field::slot(reflected);
609201342Snyan  int modifiers   = java_lang_reflect_Field::modifiers(reflected);
610201342Snyan
611201342Snyan  if (must_be_static >= 0) {
612201342Snyan    int really_is_static = ((modifiers & JVM_ACC_STATIC) != 0);
613201342Snyan    if (must_be_static != really_is_static) {
614201342Snyan      THROW_0(vmSymbols::java_lang_IllegalArgumentException());
615201342Snyan    }
616201342Snyan  }
617201342Snyan
618201342Snyan  int offset = instanceKlass::cast(k)->offset_from_fields(slot);
619201342Snyan  return field_offset_from_byte_offset(offset);
620239063Snyan}
621239063Snyan
622201342SnyanUNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
623201342Snyan  UnsafeWrapper("Unsafe_ObjectFieldOffset");
624201342Snyan  return find_field_offset(field, 0, THREAD);
625201342SnyanUNSAFE_END
626201342Snyan
627201342SnyanUNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset(JNIEnv *env, jobject unsafe, jobject field))
628201342Snyan  UnsafeWrapper("Unsafe_StaticFieldOffset");
629254015Smarcel  return find_field_offset(field, 1, THREAD);
630201342SnyanUNSAFE_END
631254015Smarcel
632201342SnyanUNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsafe, jobject field))
633201342Snyan  UnsafeWrapper("Unsafe_StaticFieldBase");
634254015Smarcel  // Note:  In this VM implementation, a field address is always a short
635201342Snyan  // offset from the base of a a klass metaobject.  Thus, the full dynamic
636201342Snyan  // range of the return type is never used.  However, some implementations
637201342Snyan  // might put the static field inside an array shared by many classes,
638201342Snyan  // or even at a fixed address, in which case the address could be quite
639201342Snyan  // large.  In that last case, this function would return NULL, since
640201342Snyan  // the address would operate alone, without any base pointer.
641201342Snyan
642201342Snyan  if (field == NULL)  THROW_0(vmSymbols::java_lang_NullPointerException());
643201342Snyan
644201342Snyan  oop reflected   = JNIHandles::resolve_non_null(field);
645201342Snyan  oop mirror      = java_lang_reflect_Field::clazz(reflected);
646201342Snyan  int modifiers   = java_lang_reflect_Field::modifiers(reflected);
647201342Snyan
648201342Snyan  if ((modifiers & JVM_ACC_STATIC) == 0) {
649201342Snyan    THROW_0(vmSymbols::java_lang_IllegalArgumentException());
650201342Snyan  }
651201342Snyan
652201342Snyan  return JNIHandles::make_local(env, java_lang_Class::as_klassOop(mirror));
653201342SnyanUNSAFE_END
654201342Snyan
655201342Snyan//@deprecated
656201342SnyanUNSAFE_ENTRY(jint, Unsafe_FieldOffset(JNIEnv *env, jobject unsafe, jobject field))
657201342Snyan  UnsafeWrapper("Unsafe_FieldOffset");
658201342Snyan  // tries (but fails) to be polymorphic between static and non-static:
659201342Snyan  jlong offset = find_field_offset(field, -1, THREAD);
660201342Snyan  guarantee(offset == (jint)offset, "offset fits in 32 bits");
661201342Snyan  return (jint)offset;
662201342SnyanUNSAFE_END
663201342Snyan
664201342Snyan//@deprecated
665201342SnyanUNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromClass(JNIEnv *env, jobject unsafe, jobject clazz))
666201342Snyan  UnsafeWrapper("Unsafe_StaticFieldBase");
667201342Snyan  if (clazz == NULL) {
668201342Snyan    THROW_0(vmSymbols::java_lang_NullPointerException());
669201342Snyan  }
670201342Snyan  return JNIHandles::make_local(env, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz)));
671201342SnyanUNSAFE_END
672201342Snyan
673201342SnyanUNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jobject clazz))
674201342Snyan  UnsafeWrapper("Unsafe_EnsureClassInitialized");
675201342Snyan  if (clazz == NULL) {
676201342Snyan    THROW(vmSymbols::java_lang_NullPointerException());
677201342Snyan  }
678201342Snyan  oop mirror = JNIHandles::resolve_non_null(clazz);
679201342Snyan  instanceKlass* k = instanceKlass::cast(java_lang_Class::as_klassOop(mirror));
680219960Snyan  if (k != NULL) {
681201342Snyan    k->initialize(CHECK);
682201342Snyan  }
683201342SnyanUNSAFE_END
684201342Snyan
685201342Snyanstatic void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) {
686201342Snyan  if (acls == NULL) {
687201342Snyan    THROW(vmSymbols::java_lang_NullPointerException());
688201342Snyan  }
689201342Snyan  oop      mirror = JNIHandles::resolve_non_null(acls);
690201342Snyan  klassOop k      = java_lang_Class::as_klassOop(mirror);
691201342Snyan  if (k == NULL || !k->klass_part()->oop_is_array()) {
692201342Snyan    THROW(vmSymbols::java_lang_InvalidClassException());
693201342Snyan  } else if (k->klass_part()->oop_is_objArray()) {
694201342Snyan    base  = arrayOopDesc::base_offset_in_bytes(T_OBJECT);
695201342Snyan    scale = heapOopSize;
696201342Snyan  } else if (k->klass_part()->oop_is_typeArray()) {
697201342Snyan    typeArrayKlass* tak = typeArrayKlass::cast(k);
698201342Snyan    base  = tak->array_header_in_bytes();
699201342Snyan    assert(base == arrayOopDesc::base_offset_in_bytes(tak->element_type()), "array_header_size semantics ok");
700201342Snyan    scale = (1 << tak->log2_element_size());
701201342Snyan  } else {
702201342Snyan    ShouldNotReachHere();
703201342Snyan  }
704201342Snyan}
705201342Snyan
706201342SnyanUNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls))
707201342Snyan  UnsafeWrapper("Unsafe_ArrayBaseOffset");
708201342Snyan  int base, scale;
709201342Snyan  getBaseAndScale(base, scale, acls, CHECK_0);
710201342Snyan  return field_offset_from_byte_offset(base);
711201342SnyanUNSAFE_END
712201342Snyan
713201342Snyan
714201342SnyanUNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls))
715201342Snyan  UnsafeWrapper("Unsafe_ArrayIndexScale");
716201342Snyan  int base, scale;
717201342Snyan  getBaseAndScale(base, scale, acls, CHECK_0);
718201342Snyan  // This VM packs both fields and array elements down to the byte.
719201342Snyan  // But watch out:  If this changes, so that array references for
720201342Snyan  // a given primitive type (say, T_BOOLEAN) use different memory units
721201342Snyan  // than fields, this method MUST return zero for such arrays.
722201342Snyan  // For example, the VM used to store sub-word sized fields in full
723201342Snyan  // words in the object layout, so that accessors like getByte(Object,int)
724201342Snyan  // did not really do what one might expect for arrays.  Therefore,
725201342Snyan  // this function used to report a zero scale factor, so that the user
726201342Snyan  // would know not to attempt to access sub-word array elements.
727201342Snyan  // // Code for unpacked fields:
728201342Snyan  // if (scale < wordSize)  return 0;
729201342Snyan
730201342Snyan  // The following allows for a pretty general fieldOffset cookie scheme,
731201342Snyan  // but requires it to be linear in byte offset.
732201342Snyan  return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0);
733201342SnyanUNSAFE_END
734201342Snyan
735201342Snyan
736201342Snyanstatic inline void throw_new(JNIEnv *env, const char *ename) {
737201342Snyan  char buf[100];
738201342Snyan  strcpy(buf, "java/lang/");
739201342Snyan  strcat(buf, ename);
740201342Snyan  jclass cls = env->FindClass(buf);
741201342Snyan  char* msg = NULL;
742201342Snyan  env->ThrowNew(cls, msg);
743201342Snyan}
744201342Snyan
745201342Snyanstatic jclass Unsafe_DefineClass(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) {
746201342Snyan  {
747201342Snyan    // Code lifted from JDK 1.3 ClassLoader.c
748201342Snyan
749201342Snyan    jbyte *body;
750201342Snyan    char *utfName;
751201342Snyan    jclass result = 0;
752201342Snyan    char buf[128];
753201342Snyan
754201342Snyan    if (UsePerfData) {
755201342Snyan      ClassLoader::unsafe_defineClassCallCounter()->inc();
756201342Snyan    }
757201342Snyan
758201342Snyan    if (data == NULL) {
759201342Snyan        throw_new(env, "NullPointerException");
760201342Snyan        return 0;
761201342Snyan    }
762201342Snyan
763201342Snyan    /* Work around 4153825. malloc crashes on Solaris when passed a
764201342Snyan     * negative size.
765201342Snyan     */
766201342Snyan    if (length < 0) {
767201342Snyan        throw_new(env, "ArrayIndexOutOfBoundsException");
768201342Snyan        return 0;
769201342Snyan    }
770201342Snyan
771201342Snyan    body = NEW_C_HEAP_ARRAY(jbyte, length);
772201342Snyan
773201342Snyan    if (body == 0) {
774201342Snyan        throw_new(env, "OutOfMemoryError");
775201342Snyan        return 0;
776201342Snyan    }
777201342Snyan
778201342Snyan    env->GetByteArrayRegion(data, offset, length, body);
779201342Snyan
780201342Snyan    if (env->ExceptionOccurred())
781201342Snyan        goto free_body;
782201342Snyan
783201342Snyan    if (name != NULL) {
784201342Snyan        uint len = env->GetStringUTFLength(name);
785201342Snyan        int unicode_len = env->GetStringLength(name);
786201342Snyan        if (len >= sizeof(buf)) {
787201342Snyan            utfName = NEW_C_HEAP_ARRAY(char, len + 1);
788201342Snyan            if (utfName == NULL) {
789201342Snyan                throw_new(env, "OutOfMemoryError");
790201342Snyan                goto free_body;
791220685Snyan            }
792220685Snyan        } else {
793220685Snyan            utfName = buf;
794220685Snyan        }
795220685Snyan        env->GetStringUTFRegion(name, 0, unicode_len, utfName);
796220685Snyan        //VerifyFixClassname(utfName);
797220685Snyan        for (uint i = 0; i < len; i++) {
798220685Snyan          if (utfName[i] == '.')   utfName[i] = '/';
799220685Snyan        }
800220685Snyan    } else {
801220685Snyan        utfName = NULL;
802220685Snyan    }
803201342Snyan
804201342Snyan    result = JVM_DefineClass(env, utfName, loader, body, length, pd);
805201342Snyan
806201342Snyan    if (utfName && utfName != buf)
807201342Snyan        FREE_C_HEAP_ARRAY(char, utfName);
808201342Snyan
809201342Snyan free_body:
810201342Snyan    FREE_C_HEAP_ARRAY(jbyte, body);
811201342Snyan    return result;
812201342Snyan  }
813201342Snyan}
814201342Snyan
815201342Snyan
816UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length))
817  UnsafeWrapper("Unsafe_DefineClass");
818  {
819    ThreadToNativeFromVM ttnfv(thread);
820
821    int depthFromDefineClass0 = 1;
822    jclass  caller = JVM_GetCallerClass(env, depthFromDefineClass0);
823    jobject loader = (caller == NULL) ? NULL : JVM_GetClassLoader(env, caller);
824    jobject pd     = (caller == NULL) ? NULL : JVM_GetProtectionDomain(env, caller);
825
826    return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
827  }
828UNSAFE_END
829
830
831UNSAFE_ENTRY(jclass, Unsafe_DefineClass1(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd))
832  UnsafeWrapper("Unsafe_DefineClass");
833  {
834    ThreadToNativeFromVM ttnfv(thread);
835
836    return Unsafe_DefineClass(env, name, data, offset, length, loader, pd);
837  }
838UNSAFE_END
839
840
841UNSAFE_ENTRY(void, Unsafe_MonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
842  UnsafeWrapper("Unsafe_MonitorEnter");
843  {
844    if (jobj == NULL) {
845      THROW(vmSymbols::java_lang_NullPointerException());
846    }
847    Handle obj(thread, JNIHandles::resolve_non_null(jobj));
848    ObjectSynchronizer::jni_enter(obj, CHECK);
849  }
850UNSAFE_END
851
852
853UNSAFE_ENTRY(jboolean, Unsafe_TryMonitorEnter(JNIEnv *env, jobject unsafe, jobject jobj))
854  UnsafeWrapper("Unsafe_TryMonitorEnter");
855  {
856    if (jobj == NULL) {
857      THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
858    }
859    Handle obj(thread, JNIHandles::resolve_non_null(jobj));
860    bool res = ObjectSynchronizer::jni_try_enter(obj, CHECK_0);
861    return (res ? JNI_TRUE : JNI_FALSE);
862  }
863UNSAFE_END
864
865
866UNSAFE_ENTRY(void, Unsafe_MonitorExit(JNIEnv *env, jobject unsafe, jobject jobj))
867  UnsafeWrapper("Unsafe_MonitorExit");
868  {
869    if (jobj == NULL) {
870      THROW(vmSymbols::java_lang_NullPointerException());
871    }
872    Handle obj(THREAD, JNIHandles::resolve_non_null(jobj));
873    ObjectSynchronizer::jni_exit(obj(), CHECK);
874  }
875UNSAFE_END
876
877
878UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr))
879  UnsafeWrapper("Unsafe_ThrowException");
880  {
881    ThreadToNativeFromVM ttnfv(thread);
882    env->Throw(thr);
883  }
884UNSAFE_END
885
886// JSR166 ------------------------------------------------------------------
887
888UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h))
889  UnsafeWrapper("Unsafe_CompareAndSwapObject");
890  oop x = JNIHandles::resolve(x_h);
891  oop e = JNIHandles::resolve(e_h);
892  oop p = JNIHandles::resolve(obj);
893  HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset);
894  oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e);
895  jboolean success  = (res == e);
896  if (success)
897    update_barrier_set((void*)addr, x);
898  return success;
899UNSAFE_END
900
901UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x))
902  UnsafeWrapper("Unsafe_CompareAndSwapInt");
903  oop p = JNIHandles::resolve(obj);
904  jint* addr = (jint *) index_oop_from_field_offset_long(p, offset);
905  return (jint)(Atomic::cmpxchg(x, addr, e)) == e;
906UNSAFE_END
907
908UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x))
909  UnsafeWrapper("Unsafe_CompareAndSwapLong");
910  Handle p (THREAD, JNIHandles::resolve(obj));
911  jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset));
912  if (VM_Version::supports_cx8())
913    return (jlong)(Atomic::cmpxchg(x, addr, e)) == e;
914  else {
915    jboolean success = false;
916    ObjectLocker ol(p, THREAD);
917    if (*addr == e) { *addr = x; success = true; }
918    return success;
919  }
920UNSAFE_END
921
922UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time))
923  UnsafeWrapper("Unsafe_Park");
924  JavaThreadParkedState jtps(thread, time != 0);
925  thread->parker()->park(isAbsolute != 0, time);
926UNSAFE_END
927
928UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread))
929  UnsafeWrapper("Unsafe_Unpark");
930  Parker* p = NULL;
931  if (jthread != NULL) {
932    oop java_thread = JNIHandles::resolve_non_null(jthread);
933    if (java_thread != NULL) {
934      jlong lp = java_lang_Thread::park_event(java_thread);
935      if (lp != 0) {
936        // This cast is OK even though the jlong might have been read
937        // non-atomically on 32bit systems, since there, one word will
938        // always be zero anyway and the value set is always the same
939        p = (Parker*)addr_from_java(lp);
940      } else {
941        // Grab lock if apparently null or using older version of library
942        MutexLocker mu(Threads_lock);
943        java_thread = JNIHandles::resolve_non_null(jthread);
944        if (java_thread != NULL) {
945          JavaThread* thr = java_lang_Thread::thread(java_thread);
946          if (thr != NULL) {
947            p = thr->parker();
948            if (p != NULL) { // Bind to Java thread for next time.
949              java_lang_Thread::set_park_event(java_thread, addr_to_java(p));
950            }
951          }
952        }
953      }
954    }
955  }
956  if (p != NULL) {
957    p->unpark();
958  }
959UNSAFE_END
960
961UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem))
962  UnsafeWrapper("Unsafe_Loadavg");
963  const int max_nelem = 3;
964  double la[max_nelem];
965  jint ret;
966
967  typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(loadavg));
968  assert(a->is_typeArray(), "must be type array");
969
970  if (nelem < 0 || nelem > max_nelem || a->length() < nelem) {
971    ThreadToNativeFromVM ttnfv(thread);
972    throw_new(env, "ArrayIndexOutOfBoundsException");
973    return -1;
974  }
975
976  ret = os::loadavg(la, nelem);
977  if (ret == -1) return -1;
978
979  // if successful, ret is the number of samples actually retrieved.
980  assert(ret >= 0 && ret <= max_nelem, "Unexpected loadavg return value");
981  switch(ret) {
982    case 3: a->double_at_put(2, (jdouble)la[2]); // fall through
983    case 2: a->double_at_put(1, (jdouble)la[1]); // fall through
984    case 1: a->double_at_put(0, (jdouble)la[0]); break;
985  }
986  return ret;
987UNSAFE_END
988
989UNSAFE_ENTRY(void, Unsafe_PrefetchRead(JNIEnv* env, jclass ignored, jobject obj, jlong offset))
990  UnsafeWrapper("Unsafe_PrefetchRead");
991  oop p = JNIHandles::resolve(obj);
992  void* addr = index_oop_from_field_offset_long(p, 0);
993  Prefetch::read(addr, (intx)offset);
994UNSAFE_END
995
996UNSAFE_ENTRY(void, Unsafe_PrefetchWrite(JNIEnv* env, jclass ignored, jobject obj, jlong offset))
997  UnsafeWrapper("Unsafe_PrefetchWrite");
998  oop p = JNIHandles::resolve(obj);
999  void* addr = index_oop_from_field_offset_long(p, 0);
1000  Prefetch::write(addr, (intx)offset);
1001UNSAFE_END
1002
1003
1004/// JVM_RegisterUnsafeMethods
1005
1006#define ADR "J"
1007
1008#define LANG "Ljava/lang/"
1009
1010#define OBJ LANG"Object;"
1011#define CLS LANG"Class;"
1012#define CTR LANG"reflect/Constructor;"
1013#define FLD LANG"reflect/Field;"
1014#define MTH LANG"reflect/Method;"
1015#define THR LANG"Throwable;"
1016
1017#define DC0_Args LANG"String;[BII"
1018#define DC1_Args DC0_Args LANG"ClassLoader;" "Ljava/security/ProtectionDomain;"
1019
1020#define CC (char*)  /*cast a literal from (const char*)*/
1021#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f)
1022
1023// define deprecated accessors for compabitility with 1.4.0
1024#define DECLARE_GETSETOOP_140(Boolean, Z) \
1025    {CC"get"#Boolean,      CC"("OBJ"I)"#Z,      FN_PTR(Unsafe_Get##Boolean##140)}, \
1026    {CC"put"#Boolean,      CC"("OBJ"I"#Z")V",   FN_PTR(Unsafe_Set##Boolean##140)}
1027
1028// Note:  In 1.4.1, getObject and kin take both int and long offsets.
1029#define DECLARE_GETSETOOP_141(Boolean, Z) \
1030    {CC"get"#Boolean,      CC"("OBJ"J)"#Z,      FN_PTR(Unsafe_Get##Boolean)}, \
1031    {CC"put"#Boolean,      CC"("OBJ"J"#Z")V",   FN_PTR(Unsafe_Set##Boolean)}
1032
1033// Note:  In 1.5.0, there are volatile versions too
1034#define DECLARE_GETSETOOP(Boolean, Z) \
1035    {CC"get"#Boolean,      CC"("OBJ"J)"#Z,      FN_PTR(Unsafe_Get##Boolean)}, \
1036    {CC"put"#Boolean,      CC"("OBJ"J"#Z")V",   FN_PTR(Unsafe_Set##Boolean)}, \
1037    {CC"get"#Boolean"Volatile",      CC"("OBJ"J)"#Z,      FN_PTR(Unsafe_Get##Boolean##Volatile)}, \
1038    {CC"put"#Boolean"Volatile",      CC"("OBJ"J"#Z")V",   FN_PTR(Unsafe_Set##Boolean##Volatile)}
1039
1040
1041#define DECLARE_GETSETNATIVE(Byte, B) \
1042    {CC"get"#Byte,         CC"("ADR")"#B,       FN_PTR(Unsafe_GetNative##Byte)}, \
1043    {CC"put"#Byte,         CC"("ADR#B")V",      FN_PTR(Unsafe_SetNative##Byte)}
1044
1045
1046
1047// %%% These are temporarily supported until the SDK sources
1048// contain the necessarily updated Unsafe.java.
1049static JNINativeMethod methods_140[] = {
1050
1051    {CC"getObject",        CC"("OBJ"I)"OBJ"",   FN_PTR(Unsafe_GetObject140)},
1052    {CC"putObject",        CC"("OBJ"I"OBJ")V",  FN_PTR(Unsafe_SetObject140)},
1053
1054    DECLARE_GETSETOOP_140(Boolean, Z),
1055    DECLARE_GETSETOOP_140(Byte, B),
1056    DECLARE_GETSETOOP_140(Short, S),
1057    DECLARE_GETSETOOP_140(Char, C),
1058    DECLARE_GETSETOOP_140(Int, I),
1059    DECLARE_GETSETOOP_140(Long, J),
1060    DECLARE_GETSETOOP_140(Float, F),
1061    DECLARE_GETSETOOP_140(Double, D),
1062
1063    DECLARE_GETSETNATIVE(Byte, B),
1064    DECLARE_GETSETNATIVE(Short, S),
1065    DECLARE_GETSETNATIVE(Char, C),
1066    DECLARE_GETSETNATIVE(Int, I),
1067    DECLARE_GETSETNATIVE(Long, J),
1068    DECLARE_GETSETNATIVE(Float, F),
1069    DECLARE_GETSETNATIVE(Double, D),
1070
1071    {CC"getAddress",         CC"("ADR")"ADR,             FN_PTR(Unsafe_GetNativeAddress)},
1072    {CC"putAddress",         CC"("ADR""ADR")V",          FN_PTR(Unsafe_SetNativeAddress)},
1073
1074    {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
1075    {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
1076//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
1077//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
1078    {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
1079
1080    {CC"fieldOffset",        CC"("FLD")I",               FN_PTR(Unsafe_FieldOffset)}, //deprecated
1081    {CC"staticFieldBase",    CC"("CLS")"OBJ,             FN_PTR(Unsafe_StaticFieldBaseFromClass)}, //deprecated
1082    {CC"ensureClassInitialized",CC"("CLS")V",            FN_PTR(Unsafe_EnsureClassInitialized)},
1083    {CC"arrayBaseOffset",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayBaseOffset)},
1084    {CC"arrayIndexScale",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayIndexScale)},
1085    {CC"addressSize",        CC"()I",                    FN_PTR(Unsafe_AddressSize)},
1086    {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
1087
1088    {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
1089    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
1090    {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
1091    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
1092    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
1093    {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)}
1094};
1095
1096// These are the old methods prior to the JSR 166 changes in 1.5.0
1097static JNINativeMethod methods_141[] = {
1098
1099    {CC"getObject",        CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObject)},
1100    {CC"putObject",        CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObject)},
1101
1102    DECLARE_GETSETOOP_141(Boolean, Z),
1103    DECLARE_GETSETOOP_141(Byte, B),
1104    DECLARE_GETSETOOP_141(Short, S),
1105    DECLARE_GETSETOOP_141(Char, C),
1106    DECLARE_GETSETOOP_141(Int, I),
1107    DECLARE_GETSETOOP_141(Long, J),
1108    DECLARE_GETSETOOP_141(Float, F),
1109    DECLARE_GETSETOOP_141(Double, D),
1110
1111    DECLARE_GETSETNATIVE(Byte, B),
1112    DECLARE_GETSETNATIVE(Short, S),
1113    DECLARE_GETSETNATIVE(Char, C),
1114    DECLARE_GETSETNATIVE(Int, I),
1115    DECLARE_GETSETNATIVE(Long, J),
1116    DECLARE_GETSETNATIVE(Float, F),
1117    DECLARE_GETSETNATIVE(Double, D),
1118
1119    {CC"getAddress",         CC"("ADR")"ADR,             FN_PTR(Unsafe_GetNativeAddress)},
1120    {CC"putAddress",         CC"("ADR""ADR")V",          FN_PTR(Unsafe_SetNativeAddress)},
1121
1122    {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
1123    {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
1124//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
1125//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
1126    {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
1127
1128    {CC"objectFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_ObjectFieldOffset)},
1129    {CC"staticFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_StaticFieldOffset)},
1130    {CC"staticFieldBase",    CC"("FLD")"OBJ,             FN_PTR(Unsafe_StaticFieldBaseFromField)},
1131    {CC"ensureClassInitialized",CC"("CLS")V",            FN_PTR(Unsafe_EnsureClassInitialized)},
1132    {CC"arrayBaseOffset",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayBaseOffset)},
1133    {CC"arrayIndexScale",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayIndexScale)},
1134    {CC"addressSize",        CC"()I",                    FN_PTR(Unsafe_AddressSize)},
1135    {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
1136
1137    {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
1138    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
1139    {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
1140    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
1141    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
1142    {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)}
1143
1144};
1145
1146// These are the old methods prior to the JSR 166 changes in 1.6.0
1147static JNINativeMethod methods_15[] = {
1148
1149    {CC"getObject",        CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObject)},
1150    {CC"putObject",        CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObject)},
1151    {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObjectVolatile)},
1152    {CC"putObjectVolatile",CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObjectVolatile)},
1153
1154
1155    DECLARE_GETSETOOP(Boolean, Z),
1156    DECLARE_GETSETOOP(Byte, B),
1157    DECLARE_GETSETOOP(Short, S),
1158    DECLARE_GETSETOOP(Char, C),
1159    DECLARE_GETSETOOP(Int, I),
1160    DECLARE_GETSETOOP(Long, J),
1161    DECLARE_GETSETOOP(Float, F),
1162    DECLARE_GETSETOOP(Double, D),
1163
1164    DECLARE_GETSETNATIVE(Byte, B),
1165    DECLARE_GETSETNATIVE(Short, S),
1166    DECLARE_GETSETNATIVE(Char, C),
1167    DECLARE_GETSETNATIVE(Int, I),
1168    DECLARE_GETSETNATIVE(Long, J),
1169    DECLARE_GETSETNATIVE(Float, F),
1170    DECLARE_GETSETNATIVE(Double, D),
1171
1172    {CC"getAddress",         CC"("ADR")"ADR,             FN_PTR(Unsafe_GetNativeAddress)},
1173    {CC"putAddress",         CC"("ADR""ADR")V",          FN_PTR(Unsafe_SetNativeAddress)},
1174
1175    {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
1176    {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
1177//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
1178//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
1179    {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
1180
1181    {CC"objectFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_ObjectFieldOffset)},
1182    {CC"staticFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_StaticFieldOffset)},
1183    {CC"staticFieldBase",    CC"("FLD")"OBJ,             FN_PTR(Unsafe_StaticFieldBaseFromField)},
1184    {CC"ensureClassInitialized",CC"("CLS")V",            FN_PTR(Unsafe_EnsureClassInitialized)},
1185    {CC"arrayBaseOffset",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayBaseOffset)},
1186    {CC"arrayIndexScale",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayIndexScale)},
1187    {CC"addressSize",        CC"()I",                    FN_PTR(Unsafe_AddressSize)},
1188    {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
1189
1190    {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
1191    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
1192    {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
1193    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
1194    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
1195    {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)},
1196    {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z",  FN_PTR(Unsafe_CompareAndSwapObject)},
1197    {CC"compareAndSwapInt",  CC"("OBJ"J""I""I"")Z",      FN_PTR(Unsafe_CompareAndSwapInt)},
1198    {CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z",      FN_PTR(Unsafe_CompareAndSwapLong)},
1199    {CC"park",               CC"(ZJ)V",                  FN_PTR(Unsafe_Park)},
1200    {CC"unpark",             CC"("OBJ")V",               FN_PTR(Unsafe_Unpark)}
1201
1202};
1203
1204// These are the correct methods, moving forward:
1205static JNINativeMethod methods[] = {
1206
1207    {CC"getObject",        CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObject)},
1208    {CC"putObject",        CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObject)},
1209    {CC"getObjectVolatile",CC"("OBJ"J)"OBJ"",   FN_PTR(Unsafe_GetObjectVolatile)},
1210    {CC"putObjectVolatile",CC"("OBJ"J"OBJ")V",  FN_PTR(Unsafe_SetObjectVolatile)},
1211
1212
1213    DECLARE_GETSETOOP(Boolean, Z),
1214    DECLARE_GETSETOOP(Byte, B),
1215    DECLARE_GETSETOOP(Short, S),
1216    DECLARE_GETSETOOP(Char, C),
1217    DECLARE_GETSETOOP(Int, I),
1218    DECLARE_GETSETOOP(Long, J),
1219    DECLARE_GETSETOOP(Float, F),
1220    DECLARE_GETSETOOP(Double, D),
1221
1222    DECLARE_GETSETNATIVE(Byte, B),
1223    DECLARE_GETSETNATIVE(Short, S),
1224    DECLARE_GETSETNATIVE(Char, C),
1225    DECLARE_GETSETNATIVE(Int, I),
1226    DECLARE_GETSETNATIVE(Long, J),
1227    DECLARE_GETSETNATIVE(Float, F),
1228    DECLARE_GETSETNATIVE(Double, D),
1229
1230    {CC"getAddress",         CC"("ADR")"ADR,             FN_PTR(Unsafe_GetNativeAddress)},
1231    {CC"putAddress",         CC"("ADR""ADR")V",          FN_PTR(Unsafe_SetNativeAddress)},
1232
1233    {CC"allocateMemory",     CC"(J)"ADR,                 FN_PTR(Unsafe_AllocateMemory)},
1234    {CC"reallocateMemory",   CC"("ADR"J)"ADR,            FN_PTR(Unsafe_ReallocateMemory)},
1235//  {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
1236//  {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)},
1237    {CC"freeMemory",         CC"("ADR")V",               FN_PTR(Unsafe_FreeMemory)},
1238
1239    {CC"objectFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_ObjectFieldOffset)},
1240    {CC"staticFieldOffset",  CC"("FLD")J",               FN_PTR(Unsafe_StaticFieldOffset)},
1241    {CC"staticFieldBase",    CC"("FLD")"OBJ,             FN_PTR(Unsafe_StaticFieldBaseFromField)},
1242    {CC"ensureClassInitialized",CC"("CLS")V",            FN_PTR(Unsafe_EnsureClassInitialized)},
1243    {CC"arrayBaseOffset",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayBaseOffset)},
1244    {CC"arrayIndexScale",    CC"("CLS")I",               FN_PTR(Unsafe_ArrayIndexScale)},
1245    {CC"addressSize",        CC"()I",                    FN_PTR(Unsafe_AddressSize)},
1246    {CC"pageSize",           CC"()I",                    FN_PTR(Unsafe_PageSize)},
1247
1248    {CC"defineClass",        CC"("DC0_Args")"CLS,        FN_PTR(Unsafe_DefineClass0)},
1249    {CC"defineClass",        CC"("DC1_Args")"CLS,        FN_PTR(Unsafe_DefineClass1)},
1250    {CC"allocateInstance",   CC"("CLS")"OBJ,             FN_PTR(Unsafe_AllocateInstance)},
1251    {CC"monitorEnter",       CC"("OBJ")V",               FN_PTR(Unsafe_MonitorEnter)},
1252    {CC"monitorExit",        CC"("OBJ")V",               FN_PTR(Unsafe_MonitorExit)},
1253    {CC"tryMonitorEnter",    CC"("OBJ")Z",               FN_PTR(Unsafe_TryMonitorEnter)},
1254    {CC"throwException",     CC"("THR")V",               FN_PTR(Unsafe_ThrowException)},
1255    {CC"compareAndSwapObject", CC"("OBJ"J"OBJ""OBJ")Z",  FN_PTR(Unsafe_CompareAndSwapObject)},
1256    {CC"compareAndSwapInt",  CC"("OBJ"J""I""I"")Z",      FN_PTR(Unsafe_CompareAndSwapInt)},
1257    {CC"compareAndSwapLong", CC"("OBJ"J""J""J"")Z",      FN_PTR(Unsafe_CompareAndSwapLong)},
1258    {CC"putOrderedObject",   CC"("OBJ"J"OBJ")V",         FN_PTR(Unsafe_SetOrderedObject)},
1259    {CC"putOrderedInt",      CC"("OBJ"JI)V",             FN_PTR(Unsafe_SetOrderedInt)},
1260    {CC"putOrderedLong",     CC"("OBJ"JJ)V",             FN_PTR(Unsafe_SetOrderedLong)},
1261    {CC"park",               CC"(ZJ)V",                  FN_PTR(Unsafe_Park)},
1262    {CC"unpark",             CC"("OBJ")V",               FN_PTR(Unsafe_Unpark)}
1263
1264//    {CC"getLoadAverage",     CC"([DI)I",                 FN_PTR(Unsafe_Loadavg)},
1265
1266//    {CC"prefetchRead",       CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchRead)},
1267//    {CC"prefetchWrite",      CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchWrite)}
1268//    {CC"prefetchReadStatic", CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchRead)},
1269//    {CC"prefetchWriteStatic",CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchWrite)}
1270
1271};
1272
1273JNINativeMethod loadavg_method[] = {
1274    {CC"getLoadAverage",            CC"([DI)I",                 FN_PTR(Unsafe_Loadavg)}
1275};
1276
1277JNINativeMethod prefetch_methods[] = {
1278    {CC"prefetchRead",       CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchRead)},
1279    {CC"prefetchWrite",      CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchWrite)},
1280    {CC"prefetchReadStatic", CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchRead)},
1281    {CC"prefetchWriteStatic",CC"("OBJ"J)V",              FN_PTR(Unsafe_PrefetchWrite)}
1282};
1283
1284JNINativeMethod memcopy_methods[] = {
1285    {CC"copyMemory",         CC"("OBJ"J"OBJ"JJ)V",       FN_PTR(Unsafe_CopyMemory2)},
1286    {CC"setMemory",          CC"("OBJ"JJB)V",            FN_PTR(Unsafe_SetMemory2)}
1287};
1288
1289JNINativeMethod memcopy_methods_15[] = {
1290    {CC"setMemory",          CC"("ADR"JB)V",             FN_PTR(Unsafe_SetMemory)},
1291    {CC"copyMemory",         CC"("ADR ADR"J)V",          FN_PTR(Unsafe_CopyMemory)}
1292};
1293
1294
1295#undef CC
1296#undef FN_PTR
1297
1298#undef ADR
1299#undef LANG
1300#undef OBJ
1301#undef CLS
1302#undef CTR
1303#undef FLD
1304#undef MTH
1305#undef THR
1306#undef DC0_Args
1307#undef DC1_Args
1308
1309#undef DECLARE_GETSETOOP
1310#undef DECLARE_GETSETNATIVE
1311
1312
1313// This one function is exported, used by NativeLookup.
1314// The Unsafe_xxx functions above are called only from the interpreter.
1315// The optimizer looks at names and signatures to recognize
1316// individual functions.
1317
1318JVM_ENTRY(void, JVM_RegisterUnsafeMethods(JNIEnv *env, jclass unsafecls))
1319  UnsafeWrapper("JVM_RegisterUnsafeMethods");
1320  {
1321    ThreadToNativeFromVM ttnfv(thread);
1322    {
1323      env->RegisterNatives(unsafecls, loadavg_method, sizeof(loadavg_method)/sizeof(JNINativeMethod));
1324      if (env->ExceptionOccurred()) {
1325        if (PrintMiscellaneous && (Verbose || WizardMode)) {
1326          tty->print_cr("Warning:  SDK 1.6 Unsafe.loadavg not found.");
1327        }
1328        env->ExceptionClear();
1329      }
1330    }
1331    {
1332      env->RegisterNatives(unsafecls, prefetch_methods, sizeof(prefetch_methods)/sizeof(JNINativeMethod));
1333      if (env->ExceptionOccurred()) {
1334        if (PrintMiscellaneous && (Verbose || WizardMode)) {
1335          tty->print_cr("Warning:  SDK 1.6 Unsafe.prefetchRead/Write not found.");
1336        }
1337        env->ExceptionClear();
1338      }
1339    }
1340    {
1341      env->RegisterNatives(unsafecls, memcopy_methods, sizeof(memcopy_methods)/sizeof(JNINativeMethod));
1342      if (env->ExceptionOccurred()) {
1343        if (PrintMiscellaneous && (Verbose || WizardMode)) {
1344          tty->print_cr("Warning:  SDK 1.7 Unsafe.copyMemory not found.");
1345        }
1346        env->ExceptionClear();
1347        env->RegisterNatives(unsafecls, memcopy_methods_15, sizeof(memcopy_methods_15)/sizeof(JNINativeMethod));
1348        if (env->ExceptionOccurred()) {
1349          if (PrintMiscellaneous && (Verbose || WizardMode)) {
1350            tty->print_cr("Warning:  SDK 1.5 Unsafe.copyMemory not found.");
1351          }
1352          env->ExceptionClear();
1353        }
1354      }
1355    }
1356    int status = env->RegisterNatives(unsafecls, methods, sizeof(methods)/sizeof(JNINativeMethod));
1357    if (env->ExceptionOccurred()) {
1358      if (PrintMiscellaneous && (Verbose || WizardMode)) {
1359        tty->print_cr("Warning:  SDK 1.6 version of Unsafe not found.");
1360      }
1361      env->ExceptionClear();
1362      // %%% For now, be backward compatible with an older class:
1363      status = env->RegisterNatives(unsafecls, methods_15, sizeof(methods_15)/sizeof(JNINativeMethod));
1364    }
1365    if (env->ExceptionOccurred()) {
1366      if (PrintMiscellaneous && (Verbose || WizardMode)) {
1367        tty->print_cr("Warning:  SDK 1.5 version of Unsafe not found.");
1368      }
1369      env->ExceptionClear();
1370      // %%% For now, be backward compatible with an older class:
1371      status = env->RegisterNatives(unsafecls, methods_141, sizeof(methods_141)/sizeof(JNINativeMethod));
1372    }
1373    if (env->ExceptionOccurred()) {
1374      if (PrintMiscellaneous && (Verbose || WizardMode)) {
1375        tty->print_cr("Warning:  SDK 1.4.1 version of Unsafe not found.");
1376      }
1377      env->ExceptionClear();
1378      // %%% For now, be backward compatible with an older class:
1379      status = env->RegisterNatives(unsafecls, methods_140, sizeof(methods_140)/sizeof(JNINativeMethod));
1380    }
1381    guarantee(status == 0, "register unsafe natives");
1382  }
1383JVM_END
1384