• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "jdk_internal_misc_Unsafe.h"
18 
19 #include <unistd.h>
20 
21 #include <cstdlib>
22 #include <cstring>
23 #include <atomic>
24 
25 #include "nativehelper/jni_macros.h"
26 
27 #include "base/quasi_atomic.h"
28 #include "common_throws.h"
29 #include "gc/accounting/card_table-inl.h"
30 #include "jni/jni_internal.h"
31 #include "mirror/array.h"
32 #include "mirror/class-inl.h"
33 #include "mirror/object-inl.h"
34 #include "art_field-inl.h"
35 #include "native_util.h"
36 #include "scoped_fast_native_object_access-inl.h"
37 #include "well_known_classes-inl.h"
38 
39 namespace art {
40 
41 namespace {
42   // Checks a JNI argument `size` fits inside a size_t and throws a RuntimeException if not (see
43   // jdk/internal/misc/Unsafe.java comments).
ValidJniSizeArgument(jlong size)44   bool ValidJniSizeArgument(jlong size) REQUIRES_SHARED(Locks::mutator_lock_) {
45     const jlong maybe_truncated_size = static_cast<jlong>(static_cast<size_t>(size));
46     // size is nonnegative and fits into size_t
47     if (LIKELY(size >= 0 && size == maybe_truncated_size)) {
48       return true;
49     }
50     ThrowRuntimeException("Bad size: %" PRIu64, size);
51     return false;
52   }
53 }  // namespace
54 
Unsafe_compareAndSetInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint expectedValue,jint newValue)55 static jboolean Unsafe_compareAndSetInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
56                                         jint expectedValue, jint newValue) {
57   ScopedFastNativeObjectAccess soa(env);
58   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
59   // JNI must use non transactional mode.
60   bool success = obj->CasField32<false>(MemberOffset(offset),
61                                         expectedValue,
62                                         newValue,
63                                         CASMode::kStrong,
64                                         std::memory_order_seq_cst);
65   return success ? JNI_TRUE : JNI_FALSE;
66 }
67 
Unsafe_compareAndSwapInt(JNIEnv * env,jobject obj,jobject javaObj,jlong offset,jint expectedValue,jint newValue)68 static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject obj, jobject javaObj, jlong offset,
69                                          jint expectedValue, jint newValue) {
70   // compareAndSetInt has the same semantics as compareAndSwapInt, except for
71   // being strict (volatile). Since this was implemented in a strict mode it can
72   // just call the volatile version unless it gets relaxed.
73   return Unsafe_compareAndSetInt(env, obj, javaObj, offset, expectedValue, newValue);
74 }
75 
Unsafe_compareAndSetLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong expectedValue,jlong newValue)76 static jboolean Unsafe_compareAndSetLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
77                                          jlong expectedValue, jlong newValue) {
78   ScopedFastNativeObjectAccess soa(env);
79   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
80   // JNI must use non transactional mode.
81   bool success = obj->CasFieldStrongSequentiallyConsistent64<false>(MemberOffset(offset),
82                                                                     expectedValue,
83                                                                     newValue);
84   return success ? JNI_TRUE : JNI_FALSE;
85 }
86 
Unsafe_compareAndSwapLong(JNIEnv * env,jobject obj,jobject javaObj,jlong offset,jlong expectedValue,jlong newValue)87 static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject obj, jobject javaObj, jlong offset,
88                                           jlong expectedValue, jlong newValue) {
89   // compareAndSetLong has the same semantics as compareAndSwapLong, except for
90   // being strict (volatile). Since this was implemented in a strict mode it can
91   // just call the volatile version unless it gets relaxed.
92   return Unsafe_compareAndSetLong(env, obj, javaObj, offset, expectedValue, newValue);
93 }
94 
Unsafe_compareAndSetReference(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaExpectedValue,jobject javaNewValue)95 static jboolean Unsafe_compareAndSetReference(JNIEnv* env,
96                                               jobject,
97                                               jobject javaObj,
98                                               jlong offset,
99                                               jobject javaExpectedValue,
100                                               jobject javaNewValue) {
101   ScopedFastNativeObjectAccess soa(env);
102   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
103   ObjPtr<mirror::Object> expectedValue = soa.Decode<mirror::Object>(javaExpectedValue);
104   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
105   // JNI must use non transactional mode.
106   if (gUseReadBarrier) {
107     // Need to make sure the reference stored in the field is a to-space one before attempting the
108     // CAS or the CAS could fail incorrectly.
109     // Note that the read barrier load does NOT need to be volatile.
110     mirror::HeapReference<mirror::Object>* field_addr =
111         reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
112             reinterpret_cast<uint8_t*>(obj.Ptr()) + static_cast<size_t>(offset));
113     ReadBarrier::Barrier<mirror::Object, /*kIsVolatile=*/ false, kWithReadBarrier,
114         /* kAlwaysUpdateField= */ true>(
115         obj.Ptr(),
116         MemberOffset(offset),
117         field_addr);
118   }
119   bool success = obj->CasFieldObject<false>(MemberOffset(offset),
120                                             expectedValue,
121                                             newValue,
122                                             CASMode::kStrong,
123                                             std::memory_order_seq_cst);
124   return success ? JNI_TRUE : JNI_FALSE;
125 }
126 
Unsafe_compareAndSwapObject(JNIEnv * env,jobject obj,jobject javaObj,jlong offset,jobject javaExpectedValue,jobject javaNewValue)127 static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject obj, jobject javaObj, jlong offset,
128                                             jobject javaExpectedValue, jobject javaNewValue) {
129   // compareAndSetReference has the same semantics as compareAndSwapObject, except for
130   // being strict (volatile). Since this was implemented in a strict mode it can
131   // just call the volatile version unless it gets relaxed.
132   return Unsafe_compareAndSetReference(env, obj, javaObj, offset, javaExpectedValue, javaNewValue);
133 }
134 
Unsafe_getInt(JNIEnv * env,jobject,jobject javaObj,jlong offset)135 static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
136   ScopedFastNativeObjectAccess soa(env);
137   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
138   return obj->GetField32(MemberOffset(offset));
139 }
140 
Unsafe_getIntVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)141 static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
142   ScopedFastNativeObjectAccess soa(env);
143   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
144   return obj->GetField32Volatile(MemberOffset(offset));
145 }
146 
Unsafe_putInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)147 static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
148   ScopedFastNativeObjectAccess soa(env);
149   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
150   // JNI must use non transactional mode.
151   obj->SetField32<false>(MemberOffset(offset), newValue);
152 }
153 
Unsafe_putIntVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)154 static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
155                                   jint newValue) {
156   ScopedFastNativeObjectAccess soa(env);
157   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
158   // JNI must use non transactional mode.
159   obj->SetField32Volatile<false>(MemberOffset(offset), newValue);
160 }
161 
Unsafe_putOrderedInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)162 static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
163                                  jint newValue) {
164   ScopedFastNativeObjectAccess soa(env);
165   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
166   // TODO: A release store is likely to be faster on future processors.
167   std::atomic_thread_fence(std::memory_order_release);
168   // JNI must use non transactional mode.
169   obj->SetField32<false>(MemberOffset(offset), newValue);
170 }
171 
Unsafe_getLong(JNIEnv * env,jobject,jobject javaObj,jlong offset)172 static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
173   ScopedFastNativeObjectAccess soa(env);
174   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
175   return obj->GetField64(MemberOffset(offset));
176 }
177 
Unsafe_getLongVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)178 static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
179   ScopedFastNativeObjectAccess soa(env);
180   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
181   return obj->GetField64Volatile(MemberOffset(offset));
182 }
183 
Unsafe_putLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)184 static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
185   ScopedFastNativeObjectAccess soa(env);
186   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
187   // JNI must use non transactional mode.
188   obj->SetField64<false>(MemberOffset(offset), newValue);
189 }
190 
Unsafe_putLongVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)191 static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
192                                    jlong newValue) {
193   ScopedFastNativeObjectAccess soa(env);
194   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
195   // JNI must use non transactional mode.
196   obj->SetField64Volatile<false>(MemberOffset(offset), newValue);
197 }
198 
Unsafe_putOrderedLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)199 static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
200                                   jlong newValue) {
201   ScopedFastNativeObjectAccess soa(env);
202   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
203   std::atomic_thread_fence(std::memory_order_release);
204   // JNI must use non transactional mode.
205   obj->SetField64<false>(MemberOffset(offset), newValue);
206 }
207 
Unsafe_getReferenceVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)208 static jobject Unsafe_getReferenceVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
209   ScopedFastNativeObjectAccess soa(env);
210   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
211   ObjPtr<mirror::Object> value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
212   return soa.AddLocalReference<jobject>(value);
213 }
214 
Unsafe_getReference(JNIEnv * env,jobject,jobject javaObj,jlong offset)215 static jobject Unsafe_getReference(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
216   ScopedFastNativeObjectAccess soa(env);
217   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
218   ObjPtr<mirror::Object> value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
219   return soa.AddLocalReference<jobject>(value);
220 }
221 
Unsafe_putReference(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)222 static void Unsafe_putReference(
223     JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
224   ScopedFastNativeObjectAccess soa(env);
225   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
226   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
227   // JNI must use non transactional mode.
228   obj->SetFieldObject<false>(MemberOffset(offset), newValue);
229 }
230 
Unsafe_putReferenceVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)231 static void Unsafe_putReferenceVolatile(
232     JNIEnv* env, jobject, jobject javaObj, jlong offset, jobject javaNewValue) {
233   ScopedFastNativeObjectAccess soa(env);
234   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
235   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
236   // JNI must use non transactional mode.
237   obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue);
238 }
239 
Unsafe_putOrderedObject(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)240 static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
241                                     jobject javaNewValue) {
242   ScopedFastNativeObjectAccess soa(env);
243   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
244   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
245   std::atomic_thread_fence(std::memory_order_release);
246   // JNI must use non transactional mode.
247   obj->SetFieldObject<false>(MemberOffset(offset), newValue);
248 }
249 
Unsafe_getArrayBaseOffsetForComponentType(JNIEnv * env,jclass,jclass component_class)250 static jint Unsafe_getArrayBaseOffsetForComponentType(JNIEnv* env, jclass, jclass component_class) {
251   ScopedFastNativeObjectAccess soa(env);
252   ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
253   Primitive::Type primitive_type = component->GetPrimitiveType();
254   return mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value();
255 }
256 
Unsafe_getArrayIndexScaleForComponentType(JNIEnv * env,jclass,jclass component_class)257 static jint Unsafe_getArrayIndexScaleForComponentType(JNIEnv* env, jclass, jclass component_class) {
258   ScopedFastNativeObjectAccess soa(env);
259   ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
260   Primitive::Type primitive_type = component->GetPrimitiveType();
261   return Primitive::ComponentSize(primitive_type);
262 }
263 
Unsafe_addressSize(JNIEnv * env ATTRIBUTE_UNUSED,jobject ob ATTRIBUTE_UNUSED)264 static jint Unsafe_addressSize(JNIEnv* env ATTRIBUTE_UNUSED, jobject ob ATTRIBUTE_UNUSED) {
265   return sizeof(void*);
266 }
267 
Unsafe_pageSize(JNIEnv * env ATTRIBUTE_UNUSED,jobject ob ATTRIBUTE_UNUSED)268 static jint Unsafe_pageSize(JNIEnv* env ATTRIBUTE_UNUSED, jobject ob ATTRIBUTE_UNUSED) {
269   return sysconf(_SC_PAGESIZE);
270 }
271 
Unsafe_allocateMemory(JNIEnv * env,jobject,jlong bytes)272 static jlong Unsafe_allocateMemory(JNIEnv* env, jobject, jlong bytes) {
273   ScopedFastNativeObjectAccess soa(env);
274   if (bytes == 0) {
275     return 0;
276   }
277   // bytes is nonnegative and fits into size_t
278   if (!ValidJniSizeArgument(bytes)) {
279     DCHECK(soa.Self()->IsExceptionPending());
280     return 0;
281   }
282   const size_t malloc_bytes = static_cast<size_t>(bytes);
283   void* mem = malloc(malloc_bytes);
284   if (mem == nullptr) {
285     soa.Self()->ThrowOutOfMemoryError("native alloc");
286     return 0;
287   }
288   return reinterpret_cast<uintptr_t>(mem);
289 }
290 
Unsafe_freeMemory(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)291 static void Unsafe_freeMemory(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
292   free(reinterpret_cast<void*>(static_cast<uintptr_t>(address)));
293 }
294 
Unsafe_setMemory(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jlong bytes,jbyte value)295 static void Unsafe_setMemory(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong bytes, jbyte value) {
296   memset(reinterpret_cast<void*>(static_cast<uintptr_t>(address)), value, bytes);
297 }
298 
Unsafe_getByteJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)299 static jbyte Unsafe_getByteJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
300   return *reinterpret_cast<jbyte*>(address);
301 }
302 
Unsafe_putByteJB(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jbyte value)303 static void Unsafe_putByteJB(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jbyte value) {
304   *reinterpret_cast<jbyte*>(address) = value;
305 }
306 
Unsafe_getShortJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)307 static jshort Unsafe_getShortJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
308   return *reinterpret_cast<jshort*>(address);
309 }
310 
Unsafe_putShortJS(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jshort value)311 static void Unsafe_putShortJS(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jshort value) {
312   *reinterpret_cast<jshort*>(address) = value;
313 }
314 
Unsafe_getCharJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)315 static jchar Unsafe_getCharJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
316   return *reinterpret_cast<jchar*>(address);
317 }
318 
Unsafe_putCharJC(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jchar value)319 static void Unsafe_putCharJC(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jchar value) {
320   *reinterpret_cast<jchar*>(address) = value;
321 }
322 
Unsafe_getIntJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)323 static jint Unsafe_getIntJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
324   return *reinterpret_cast<jint*>(address);
325 }
326 
Unsafe_putIntJI(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jint value)327 static void Unsafe_putIntJI(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jint value) {
328   *reinterpret_cast<jint*>(address) = value;
329 }
330 
Unsafe_getLongJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)331 static jlong Unsafe_getLongJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
332   return *reinterpret_cast<jlong*>(address);
333 }
334 
Unsafe_putLongJJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jlong value)335 static void Unsafe_putLongJJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong value) {
336   *reinterpret_cast<jlong*>(address) = value;
337 }
338 
Unsafe_getFloatJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)339 static jfloat Unsafe_getFloatJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
340   return *reinterpret_cast<jfloat*>(address);
341 }
342 
Unsafe_putFloatJF(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jfloat value)343 static void Unsafe_putFloatJF(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jfloat value) {
344   *reinterpret_cast<jfloat*>(address) = value;
345 }
Unsafe_getDoubleJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)346 static jdouble Unsafe_getDoubleJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
347   return *reinterpret_cast<jdouble*>(address);
348 }
349 
Unsafe_putDoubleJD(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jdouble value)350 static void Unsafe_putDoubleJD(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jdouble value) {
351   *reinterpret_cast<jdouble*>(address) = value;
352 }
353 
Unsafe_copyMemory0(JNIEnv * env,jobject unsafe ATTRIBUTE_UNUSED,jobject srcObj,jlong srcOffset,jobject dstObj,jlong dstOffset,jlong size)354 static void Unsafe_copyMemory0(JNIEnv *env, jobject unsafe ATTRIBUTE_UNUSED,
355                               jobject srcObj, jlong srcOffset,
356                               jobject dstObj, jlong dstOffset,
357                               jlong size) {
358   ScopedFastNativeObjectAccess soa(env);
359   if (size == 0) {
360     return;
361   }
362   if (!ValidJniSizeArgument(size)) {
363     DCHECK(soa.Self()->IsExceptionPending());
364     return;
365   }
366   const size_t memcpy_size = static_cast<size_t>(size);
367   const size_t src_offset = static_cast<size_t>(srcOffset);
368   ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
369   const size_t dst_offset = static_cast<size_t>(dstOffset);
370   ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
371   memcpy(reinterpret_cast<uint8_t*>(dst.Ptr()) + dst_offset,
372          reinterpret_cast<uint8_t*>(src.Ptr()) + src_offset,
373          memcpy_size);
374 }
375 
Unsafe_getBoolean(JNIEnv * env,jobject,jobject javaObj,jlong offset)376 static jboolean Unsafe_getBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
377   ScopedFastNativeObjectAccess soa(env);
378   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
379   return obj->GetFieldBoolean(MemberOffset(offset));
380 }
381 
Unsafe_putBoolean(JNIEnv * env,jobject,jobject javaObj,jlong offset,jboolean newValue)382 static void Unsafe_putBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset, jboolean newValue) {
383   ScopedFastNativeObjectAccess soa(env);
384   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
385   // JNI must use non transactional mode (SetField8 is non-transactional).
386   obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
387 }
388 
Unsafe_getByte(JNIEnv * env,jobject,jobject javaObj,jlong offset)389 static jbyte Unsafe_getByte(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
390   ScopedFastNativeObjectAccess soa(env);
391   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
392   return obj->GetFieldByte(MemberOffset(offset));
393 }
394 
Unsafe_putByte(JNIEnv * env,jobject,jobject javaObj,jlong offset,jbyte newValue)395 static void Unsafe_putByte(JNIEnv* env, jobject, jobject javaObj, jlong offset, jbyte newValue) {
396   ScopedFastNativeObjectAccess soa(env);
397   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
398   // JNI must use non transactional mode.
399   obj->SetFieldByte<false>(MemberOffset(offset), newValue);
400 }
401 
Unsafe_getChar(JNIEnv * env,jobject,jobject javaObj,jlong offset)402 static jchar Unsafe_getChar(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
403   ScopedFastNativeObjectAccess soa(env);
404   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
405   return obj->GetFieldChar(MemberOffset(offset));
406 }
407 
Unsafe_putChar(JNIEnv * env,jobject,jobject javaObj,jlong offset,jchar newValue)408 static void Unsafe_putChar(JNIEnv* env, jobject, jobject javaObj, jlong offset, jchar newValue) {
409   ScopedFastNativeObjectAccess soa(env);
410   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
411   // JNI must use non transactional mode.
412   obj->SetFieldChar<false>(MemberOffset(offset), newValue);
413 }
414 
Unsafe_getShort(JNIEnv * env,jobject,jobject javaObj,jlong offset)415 static jshort Unsafe_getShort(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
416   ScopedFastNativeObjectAccess soa(env);
417   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
418   return obj->GetFieldShort(MemberOffset(offset));
419 }
420 
Unsafe_putShort(JNIEnv * env,jobject,jobject javaObj,jlong offset,jshort newValue)421 static void Unsafe_putShort(JNIEnv* env, jobject, jobject javaObj, jlong offset, jshort newValue) {
422   ScopedFastNativeObjectAccess soa(env);
423   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
424   // JNI must use non transactional mode.
425   obj->SetFieldShort<false>(MemberOffset(offset), newValue);
426 }
427 
Unsafe_getFloat(JNIEnv * env,jobject,jobject javaObj,jlong offset)428 static jfloat Unsafe_getFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
429   ScopedFastNativeObjectAccess soa(env);
430   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
431   union {int32_t val; jfloat converted;} conv;
432   conv.val = obj->GetField32(MemberOffset(offset));
433   return conv.converted;
434 }
435 
Unsafe_putFloat(JNIEnv * env,jobject,jobject javaObj,jlong offset,jfloat newValue)436 static void Unsafe_putFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset, jfloat newValue) {
437   ScopedFastNativeObjectAccess soa(env);
438   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
439   union {int32_t converted; jfloat val;} conv;
440   conv.val = newValue;
441   // JNI must use non transactional mode.
442   obj->SetField32<false>(MemberOffset(offset), conv.converted);
443 }
444 
Unsafe_getDouble(JNIEnv * env,jobject,jobject javaObj,jlong offset)445 static jdouble Unsafe_getDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
446   ScopedFastNativeObjectAccess soa(env);
447   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
448   union {int64_t val; jdouble converted;} conv;
449   conv.val = obj->GetField64(MemberOffset(offset));
450   return conv.converted;
451 }
452 
Unsafe_putDouble(JNIEnv * env,jobject,jobject javaObj,jlong offset,jdouble newValue)453 static void Unsafe_putDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset, jdouble newValue) {
454   ScopedFastNativeObjectAccess soa(env);
455   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
456   union {int64_t converted; jdouble val;} conv;
457   conv.val = newValue;
458   // JNI must use non transactional mode.
459   obj->SetField64<false>(MemberOffset(offset), conv.converted);
460 }
461 
Unsafe_loadFence(JNIEnv *,jobject)462 static void Unsafe_loadFence(JNIEnv*, jobject) {
463   std::atomic_thread_fence(std::memory_order_acquire);
464 }
465 
Unsafe_storeFence(JNIEnv *,jobject)466 static void Unsafe_storeFence(JNIEnv*, jobject) {
467   std::atomic_thread_fence(std::memory_order_release);
468 }
469 
Unsafe_fullFence(JNIEnv *,jobject)470 static void Unsafe_fullFence(JNIEnv*, jobject) {
471   std::atomic_thread_fence(std::memory_order_seq_cst);
472 }
473 
Unsafe_park(JNIEnv * env,jobject,jboolean isAbsolute,jlong time)474 static void Unsafe_park(JNIEnv* env, jobject, jboolean isAbsolute, jlong time) {
475   ScopedObjectAccess soa(env);
476   Thread::Current()->Park(isAbsolute, time);
477 }
478 
Unsafe_unpark(JNIEnv * env,jobject,jobject jthread)479 static void Unsafe_unpark(JNIEnv* env, jobject, jobject jthread) {
480   art::ScopedFastNativeObjectAccess soa(env);
481   ObjPtr<mirror::Object> mirror_thread = soa.Decode<mirror::Object>(jthread);
482   if (mirror_thread == nullptr ||
483       !mirror_thread->InstanceOf(WellKnownClasses::java_lang_Thread.Get())) {
484     ThrowIllegalArgumentException("Argument to unpark() was not a Thread");
485     return;
486   }
487   art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
488   art::Thread* thread = art::Thread::FromManagedThread(soa, mirror_thread);
489   if (thread != nullptr) {
490     thread->Unpark();
491   } else {
492     // If thread is null, that means that either the thread is not started yet,
493     // or the thread has already terminated. Setting the field to true will be
494     // respected when the thread does start, and is harmless if the thread has
495     // already terminated.
496     ArtField* unparked = WellKnownClasses::java_lang_Thread_unparkedBeforeStart;
497     // JNI must use non transactional mode.
498     unparked->SetBoolean<false>(mirror_thread, JNI_TRUE);
499   }
500 }
501 
502 static JNINativeMethod gMethods[] = {
503     FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
504     FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
505     FAST_NATIVE_METHOD(
506         Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
507     FAST_NATIVE_METHOD(Unsafe, compareAndSetInt, "(Ljava/lang/Object;JII)Z"),
508     FAST_NATIVE_METHOD(Unsafe, compareAndSetLong, "(Ljava/lang/Object;JJJ)Z"),
509     FAST_NATIVE_METHOD(Unsafe,
510                        compareAndSetReference,
511                        "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
512     FAST_NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"),
513     FAST_NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"),
514     FAST_NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"),
515     FAST_NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"),
516     FAST_NATIVE_METHOD(Unsafe, getReferenceVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
517     FAST_NATIVE_METHOD(Unsafe, putReferenceVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
518     FAST_NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"),
519     FAST_NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"),
520     FAST_NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"),
521     FAST_NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"),
522     FAST_NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"),
523     FAST_NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"),
524     FAST_NATIVE_METHOD(Unsafe, getReference, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
525     FAST_NATIVE_METHOD(Unsafe, putReference, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
526     FAST_NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
527     FAST_NATIVE_METHOD(Unsafe, getArrayBaseOffsetForComponentType, "(Ljava/lang/Class;)I"),
528     FAST_NATIVE_METHOD(Unsafe, getArrayIndexScaleForComponentType, "(Ljava/lang/Class;)I"),
529     FAST_NATIVE_METHOD(Unsafe, addressSize, "()I"),
530     FAST_NATIVE_METHOD(Unsafe, pageSize, "()I"),
531     FAST_NATIVE_METHOD(Unsafe, allocateMemory, "(J)J"),
532     FAST_NATIVE_METHOD(Unsafe, freeMemory, "(J)V"),
533     FAST_NATIVE_METHOD(Unsafe, setMemory, "(JJB)V"),
534     FAST_NATIVE_METHOD(Unsafe, copyMemory0, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V"),
535     FAST_NATIVE_METHOD(Unsafe, getBoolean, "(Ljava/lang/Object;J)Z"),
536 
537     FAST_NATIVE_METHOD(Unsafe, getByte, "(Ljava/lang/Object;J)B"),
538     FAST_NATIVE_METHOD(Unsafe, getChar, "(Ljava/lang/Object;J)C"),
539     FAST_NATIVE_METHOD(Unsafe, getShort, "(Ljava/lang/Object;J)S"),
540     FAST_NATIVE_METHOD(Unsafe, getFloat, "(Ljava/lang/Object;J)F"),
541     FAST_NATIVE_METHOD(Unsafe, getDouble, "(Ljava/lang/Object;J)D"),
542     FAST_NATIVE_METHOD(Unsafe, putBoolean, "(Ljava/lang/Object;JZ)V"),
543     FAST_NATIVE_METHOD(Unsafe, putByte, "(Ljava/lang/Object;JB)V"),
544     FAST_NATIVE_METHOD(Unsafe, putChar, "(Ljava/lang/Object;JC)V"),
545     FAST_NATIVE_METHOD(Unsafe, putShort, "(Ljava/lang/Object;JS)V"),
546     FAST_NATIVE_METHOD(Unsafe, putFloat, "(Ljava/lang/Object;JF)V"),
547     FAST_NATIVE_METHOD(Unsafe, putDouble, "(Ljava/lang/Object;JD)V"),
548     FAST_NATIVE_METHOD(Unsafe, unpark, "(Ljava/lang/Object;)V"),
549     NATIVE_METHOD(Unsafe, park, "(ZJ)V"),
550 
551     // Each of the getFoo variants are overloaded with a call that operates
552     // directively on a native pointer.
553     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getByte, "(J)B", getByteJ),
554     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getChar, "(J)C", getCharJ),
555     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getShort, "(J)S", getShortJ),
556     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getInt, "(J)I", getIntJ),
557     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getLong, "(J)J", getLongJ),
558     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getFloat, "(J)F", getFloatJ),
559     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getDouble, "(J)D", getDoubleJ),
560     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putByte, "(JB)V", putByteJB),
561     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putChar, "(JC)V", putCharJC),
562     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putShort, "(JS)V", putShortJS),
563     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putInt, "(JI)V", putIntJI),
564     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putLong, "(JJ)V", putLongJJ),
565     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putFloat, "(JF)V", putFloatJF),
566     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putDouble, "(JD)V", putDoubleJD),
567 
568     // CAS
569     FAST_NATIVE_METHOD(Unsafe, loadFence, "()V"),
570     FAST_NATIVE_METHOD(Unsafe, storeFence, "()V"),
571     FAST_NATIVE_METHOD(Unsafe, fullFence, "()V"),
572 };
573 
register_jdk_internal_misc_Unsafe(JNIEnv * env)574 void register_jdk_internal_misc_Unsafe(JNIEnv* env) {
575   REGISTER_NATIVE_METHODS("jdk/internal/misc/Unsafe");
576 }
577 
578 }  // namespace art
579