xref: /aosp_15_r20/art/runtime/native/jdk_internal_misc_Unsafe.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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 HIDDEN {
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_compareAndExchangeLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong expectedValue,jlong newValue)87 static jlong Unsafe_compareAndExchangeLong(
88     JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong expectedValue, jlong newValue) {
89   ScopedFastNativeObjectAccess soa(env);
90   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
91   // JNI must use non transactional mode.
92   return obj->CaeFieldStrongSequentiallyConsistent64<false>(
93       MemberOffset(offset), expectedValue, newValue);
94 }
95 
Unsafe_compareAndSwapLong(JNIEnv * env,jobject obj,jobject javaObj,jlong offset,jlong expectedValue,jlong newValue)96 static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject obj, jobject javaObj, jlong offset,
97                                           jlong expectedValue, jlong newValue) {
98   // compareAndSetLong has the same semantics as compareAndSwapLong, except for
99   // being strict (volatile). Since this was implemented in a strict mode it can
100   // just call the volatile version unless it gets relaxed.
101   return Unsafe_compareAndSetLong(env, obj, javaObj, offset, expectedValue, newValue);
102 }
103 
Unsafe_compareAndSetReference(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaExpectedValue,jobject javaNewValue)104 static jboolean Unsafe_compareAndSetReference(JNIEnv* env,
105                                               jobject,
106                                               jobject javaObj,
107                                               jlong offset,
108                                               jobject javaExpectedValue,
109                                               jobject javaNewValue) {
110   ScopedFastNativeObjectAccess soa(env);
111   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
112   ObjPtr<mirror::Object> expectedValue = soa.Decode<mirror::Object>(javaExpectedValue);
113   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
114   // JNI must use non transactional mode.
115   if (gUseReadBarrier) {
116     // Need to make sure the reference stored in the field is a to-space one before attempting the
117     // CAS or the CAS could fail incorrectly.
118     // Note that the read barrier load does NOT need to be volatile.
119     mirror::HeapReference<mirror::Object>* field_addr =
120         reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
121             reinterpret_cast<uint8_t*>(obj.Ptr()) + static_cast<size_t>(offset));
122     ReadBarrier::Barrier<mirror::Object, /*kIsVolatile=*/ false, kWithReadBarrier,
123         /* kAlwaysUpdateField= */ true>(
124         obj.Ptr(),
125         MemberOffset(offset),
126         field_addr);
127   }
128   bool success = obj->CasFieldObject<false>(MemberOffset(offset),
129                                             expectedValue,
130                                             newValue,
131                                             CASMode::kStrong,
132                                             std::memory_order_seq_cst);
133   return success ? JNI_TRUE : JNI_FALSE;
134 }
135 
Unsafe_compareAndSwapObject(JNIEnv * env,jobject obj,jobject javaObj,jlong offset,jobject javaExpectedValue,jobject javaNewValue)136 static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject obj, jobject javaObj, jlong offset,
137                                             jobject javaExpectedValue, jobject javaNewValue) {
138   // compareAndSetReference has the same semantics as compareAndSwapObject, except for
139   // being strict (volatile). Since this was implemented in a strict mode it can
140   // just call the volatile version unless it gets relaxed.
141   return Unsafe_compareAndSetReference(env, obj, javaObj, offset, javaExpectedValue, javaNewValue);
142 }
143 
Unsafe_getInt(JNIEnv * env,jobject,jobject javaObj,jlong offset)144 static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
145   ScopedFastNativeObjectAccess soa(env);
146   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
147   return obj->GetField32(MemberOffset(offset));
148 }
149 
Unsafe_getIntVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)150 static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
151   ScopedFastNativeObjectAccess soa(env);
152   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
153   return obj->GetField32Volatile(MemberOffset(offset));
154 }
155 
Unsafe_putInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)156 static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
157   ScopedFastNativeObjectAccess soa(env);
158   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
159   // JNI must use non transactional mode.
160   obj->SetField32<false>(MemberOffset(offset), newValue);
161 }
162 
Unsafe_putIntVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)163 static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
164                                   jint newValue) {
165   ScopedFastNativeObjectAccess soa(env);
166   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
167   // JNI must use non transactional mode.
168   obj->SetField32Volatile<false>(MemberOffset(offset), newValue);
169 }
170 
Unsafe_putOrderedInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)171 static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
172                                  jint newValue) {
173   ScopedFastNativeObjectAccess soa(env);
174   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
175   // TODO: A release store is likely to be faster on future processors.
176   std::atomic_thread_fence(std::memory_order_release);
177   // JNI must use non transactional mode.
178   obj->SetField32<false>(MemberOffset(offset), newValue);
179 }
180 
Unsafe_getLong(JNIEnv * env,jobject,jobject javaObj,jlong offset)181 static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
182   ScopedFastNativeObjectAccess soa(env);
183   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
184   return obj->GetField64(MemberOffset(offset));
185 }
186 
Unsafe_getLongVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)187 static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
188   ScopedFastNativeObjectAccess soa(env);
189   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
190   return obj->GetField64Volatile(MemberOffset(offset));
191 }
192 
Unsafe_putLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)193 static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
194   ScopedFastNativeObjectAccess soa(env);
195   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
196   // JNI must use non transactional mode.
197   obj->SetField64<false>(MemberOffset(offset), newValue);
198 }
199 
Unsafe_putLongVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)200 static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
201                                    jlong newValue) {
202   ScopedFastNativeObjectAccess soa(env);
203   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
204   // JNI must use non transactional mode.
205   obj->SetField64Volatile<false>(MemberOffset(offset), newValue);
206 }
207 
Unsafe_putOrderedLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)208 static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
209                                   jlong newValue) {
210   ScopedFastNativeObjectAccess soa(env);
211   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
212   std::atomic_thread_fence(std::memory_order_release);
213   // JNI must use non transactional mode.
214   obj->SetField64<false>(MemberOffset(offset), newValue);
215 }
216 
Unsafe_getReferenceVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)217 static jobject Unsafe_getReferenceVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
218   ScopedFastNativeObjectAccess soa(env);
219   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
220   ObjPtr<mirror::Object> value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
221   return soa.AddLocalReference<jobject>(value);
222 }
223 
Unsafe_getReference(JNIEnv * env,jobject,jobject javaObj,jlong offset)224 static jobject Unsafe_getReference(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
225   ScopedFastNativeObjectAccess soa(env);
226   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
227   ObjPtr<mirror::Object> value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
228   return soa.AddLocalReference<jobject>(value);
229 }
230 
Unsafe_putReference(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)231 static void Unsafe_putReference(
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->SetFieldObject<false>(MemberOffset(offset), newValue);
238 }
239 
Unsafe_putReferenceVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)240 static void Unsafe_putReferenceVolatile(
241     JNIEnv* env, jobject, jobject javaObj, jlong offset, 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   // JNI must use non transactional mode.
246   obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue);
247 }
248 
Unsafe_putOrderedObject(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)249 static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
250                                     jobject javaNewValue) {
251   ScopedFastNativeObjectAccess soa(env);
252   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
253   ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
254   std::atomic_thread_fence(std::memory_order_release);
255   // JNI must use non transactional mode.
256   obj->SetFieldObject<false>(MemberOffset(offset), newValue);
257 }
258 
Unsafe_getArrayBaseOffsetForComponentType(JNIEnv * env,jclass,jclass component_class)259 static jint Unsafe_getArrayBaseOffsetForComponentType(JNIEnv* env, jclass, jclass component_class) {
260   ScopedFastNativeObjectAccess soa(env);
261   ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
262   Primitive::Type primitive_type = component->GetPrimitiveType();
263   return mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value();
264 }
265 
Unsafe_getArrayIndexScaleForComponentType(JNIEnv * env,jclass,jclass component_class)266 static jint Unsafe_getArrayIndexScaleForComponentType(JNIEnv* env, jclass, jclass component_class) {
267   ScopedFastNativeObjectAccess soa(env);
268   ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
269   Primitive::Type primitive_type = component->GetPrimitiveType();
270   return Primitive::ComponentSize(primitive_type);
271 }
272 
Unsafe_addressSize(JNIEnv * env,jobject ob)273 static jint Unsafe_addressSize([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject ob) {
274   return sizeof(void*);
275 }
276 
Unsafe_pageSize(JNIEnv * env,jobject ob)277 static jint Unsafe_pageSize([[maybe_unused]] JNIEnv* env, [[maybe_unused]] jobject ob) {
278   return sysconf(_SC_PAGESIZE);
279 }
280 
Unsafe_allocateMemory(JNIEnv * env,jobject,jlong bytes)281 static jlong Unsafe_allocateMemory(JNIEnv* env, jobject, jlong bytes) {
282   ScopedFastNativeObjectAccess soa(env);
283   if (bytes == 0) {
284     return 0;
285   }
286   // bytes is nonnegative and fits into size_t
287   if (!ValidJniSizeArgument(bytes)) {
288     DCHECK(soa.Self()->IsExceptionPending());
289     return 0;
290   }
291   const size_t malloc_bytes = static_cast<size_t>(bytes);
292   void* mem = malloc(malloc_bytes);
293   if (mem == nullptr) {
294     soa.Self()->ThrowOutOfMemoryError("native alloc");
295     return 0;
296   }
297   return reinterpret_cast<uintptr_t>(mem);
298 }
299 
Unsafe_freeMemory(JNIEnv * env,jobject,jlong address)300 static void Unsafe_freeMemory([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
301   free(reinterpret_cast<void*>(static_cast<uintptr_t>(address)));
302 }
303 
Unsafe_setMemory(JNIEnv * env,jobject,jlong address,jlong bytes,jbyte value)304 static void Unsafe_setMemory(
305     [[maybe_unused]] JNIEnv* env, jobject, jlong address, jlong bytes, jbyte value) {
306   memset(reinterpret_cast<void*>(static_cast<uintptr_t>(address)), value, bytes);
307 }
308 
Unsafe_getByteJ(JNIEnv * env,jobject,jlong address)309 static jbyte Unsafe_getByteJ([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
310   return *reinterpret_cast<jbyte*>(address);
311 }
312 
Unsafe_putByteJB(JNIEnv * env,jobject,jlong address,jbyte value)313 static void Unsafe_putByteJB([[maybe_unused]] JNIEnv* env, jobject, jlong address, jbyte value) {
314   *reinterpret_cast<jbyte*>(address) = value;
315 }
316 
Unsafe_getShortJ(JNIEnv * env,jobject,jlong address)317 static jshort Unsafe_getShortJ([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
318   return *reinterpret_cast<jshort*>(address);
319 }
320 
Unsafe_putShortJS(JNIEnv * env,jobject,jlong address,jshort value)321 static void Unsafe_putShortJS([[maybe_unused]] JNIEnv* env, jobject, jlong address, jshort value) {
322   *reinterpret_cast<jshort*>(address) = value;
323 }
324 
Unsafe_getCharJ(JNIEnv * env,jobject,jlong address)325 static jchar Unsafe_getCharJ([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
326   return *reinterpret_cast<jchar*>(address);
327 }
328 
Unsafe_putCharJC(JNIEnv * env,jobject,jlong address,jchar value)329 static void Unsafe_putCharJC([[maybe_unused]] JNIEnv* env, jobject, jlong address, jchar value) {
330   *reinterpret_cast<jchar*>(address) = value;
331 }
332 
Unsafe_getIntJ(JNIEnv * env,jobject,jlong address)333 static jint Unsafe_getIntJ([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
334   return *reinterpret_cast<jint*>(address);
335 }
336 
Unsafe_putIntJI(JNIEnv * env,jobject,jlong address,jint value)337 static void Unsafe_putIntJI([[maybe_unused]] JNIEnv* env, jobject, jlong address, jint value) {
338   *reinterpret_cast<jint*>(address) = value;
339 }
340 
Unsafe_getLongJ(JNIEnv * env,jobject,jlong address)341 static jlong Unsafe_getLongJ([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
342   return *reinterpret_cast<jlong*>(address);
343 }
344 
Unsafe_putLongJJ(JNIEnv * env,jobject,jlong address,jlong value)345 static void Unsafe_putLongJJ([[maybe_unused]] JNIEnv* env, jobject, jlong address, jlong value) {
346   *reinterpret_cast<jlong*>(address) = value;
347 }
348 
Unsafe_getFloatJ(JNIEnv * env,jobject,jlong address)349 static jfloat Unsafe_getFloatJ([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
350   return *reinterpret_cast<jfloat*>(address);
351 }
352 
Unsafe_putFloatJF(JNIEnv * env,jobject,jlong address,jfloat value)353 static void Unsafe_putFloatJF([[maybe_unused]] JNIEnv* env, jobject, jlong address, jfloat value) {
354   *reinterpret_cast<jfloat*>(address) = value;
355 }
Unsafe_getDoubleJ(JNIEnv * env,jobject,jlong address)356 static jdouble Unsafe_getDoubleJ([[maybe_unused]] JNIEnv* env, jobject, jlong address) {
357   return *reinterpret_cast<jdouble*>(address);
358 }
359 
Unsafe_putDoubleJD(JNIEnv * env,jobject,jlong address,jdouble value)360 static void Unsafe_putDoubleJD([[maybe_unused]] JNIEnv* env,
361                                jobject,
362                                jlong address,
363                                jdouble value) {
364   *reinterpret_cast<jdouble*>(address) = value;
365 }
366 
Unsafe_copyMemory0(JNIEnv * env,jobject unsafe,jobject srcObj,jlong srcOffset,jobject dstObj,jlong dstOffset,jlong size)367 static void Unsafe_copyMemory0(JNIEnv* env,
368                                [[maybe_unused]] jobject unsafe,
369                                jobject srcObj,
370                                jlong srcOffset,
371                                jobject dstObj,
372                                jlong dstOffset,
373                                jlong size) {
374   ScopedFastNativeObjectAccess soa(env);
375   if (size == 0) {
376     return;
377   }
378   if (!ValidJniSizeArgument(size)) {
379     DCHECK(soa.Self()->IsExceptionPending());
380     return;
381   }
382   const size_t memcpy_size = static_cast<size_t>(size);
383   const size_t src_offset = static_cast<size_t>(srcOffset);
384   ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
385   const size_t dst_offset = static_cast<size_t>(dstOffset);
386   ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
387   memcpy(reinterpret_cast<uint8_t*>(dst.Ptr()) + dst_offset,
388          reinterpret_cast<uint8_t*>(src.Ptr()) + src_offset,
389          memcpy_size);
390 }
391 
Unsafe_getBoolean(JNIEnv * env,jobject,jobject javaObj,jlong offset)392 static jboolean Unsafe_getBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
393   ScopedFastNativeObjectAccess soa(env);
394   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
395   return obj->GetFieldBoolean(MemberOffset(offset));
396 }
397 
Unsafe_getBooleanVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)398 static jboolean Unsafe_getBooleanVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
399   ScopedFastNativeObjectAccess soa(env);
400   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
401   return obj->GetFieldBooleanVolatile(MemberOffset(offset));
402 }
403 
Unsafe_putBoolean(JNIEnv * env,jobject,jobject javaObj,jlong offset,jboolean newValue)404 static void Unsafe_putBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset,
405                               jboolean newValue) {
406   ScopedFastNativeObjectAccess soa(env);
407   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
408   // JNI must use non transactional mode (SetField8 is non-transactional).
409   obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
410 }
411 
Unsafe_putBooleanVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jboolean newValue)412 static void Unsafe_putBooleanVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
413                                       jboolean newValue) {
414   ScopedFastNativeObjectAccess soa(env);
415   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
416   // JNI must use non transactional mode (SetField8 is non-transactional).
417   obj->SetFieldBooleanVolatile<false>(MemberOffset(offset), newValue);
418 }
419 
Unsafe_getByte(JNIEnv * env,jobject,jobject javaObj,jlong offset)420 static jbyte Unsafe_getByte(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
421   ScopedFastNativeObjectAccess soa(env);
422   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
423   return obj->GetFieldByte(MemberOffset(offset));
424 }
425 
Unsafe_getByteVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)426 static jbyte Unsafe_getByteVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
427   ScopedFastNativeObjectAccess soa(env);
428   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
429   return obj->GetFieldByteVolatile(MemberOffset(offset));
430 }
431 
Unsafe_putByte(JNIEnv * env,jobject,jobject javaObj,jlong offset,jbyte newValue)432 static void Unsafe_putByte(JNIEnv* env, jobject, jobject javaObj, jlong offset, jbyte newValue) {
433   ScopedFastNativeObjectAccess soa(env);
434   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
435   // JNI must use non transactional mode.
436   obj->SetFieldByte<false>(MemberOffset(offset), newValue);
437 }
438 
Unsafe_putByteVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jbyte newValue)439 static void Unsafe_putByteVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
440                                    jbyte newValue) {
441   ScopedFastNativeObjectAccess soa(env);
442   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
443   // JNI must use non transactional mode.
444   obj->SetFieldByteVolatile<false>(MemberOffset(offset), newValue);
445 }
446 
Unsafe_getChar(JNIEnv * env,jobject,jobject javaObj,jlong offset)447 static jchar Unsafe_getChar(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
448   ScopedFastNativeObjectAccess soa(env);
449   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
450   return obj->GetFieldChar(MemberOffset(offset));
451 }
452 
Unsafe_getCharVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)453 static jchar Unsafe_getCharVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
454   ScopedFastNativeObjectAccess soa(env);
455   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
456   return obj->GetFieldCharVolatile(MemberOffset(offset));
457 }
458 
Unsafe_putChar(JNIEnv * env,jobject,jobject javaObj,jlong offset,jchar newValue)459 static void Unsafe_putChar(JNIEnv* env, jobject, jobject javaObj, jlong offset, jchar newValue) {
460   ScopedFastNativeObjectAccess soa(env);
461   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
462   // JNI must use non transactional mode.
463   obj->SetFieldChar<false>(MemberOffset(offset), newValue);
464 }
465 
Unsafe_putCharVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jchar newValue)466 static void Unsafe_putCharVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jchar newValue) {
467   ScopedFastNativeObjectAccess soa(env);
468   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
469   // JNI must use non transactional mode.
470   obj->SetFieldCharVolatile<false>(MemberOffset(offset), newValue);
471 }
472 
Unsafe_getShort(JNIEnv * env,jobject,jobject javaObj,jlong offset)473 static jshort Unsafe_getShort(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
474   ScopedFastNativeObjectAccess soa(env);
475   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
476   return obj->GetFieldShort(MemberOffset(offset));
477 }
478 
Unsafe_getShortVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)479 static jshort Unsafe_getShortVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
480   ScopedFastNativeObjectAccess soa(env);
481   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
482   return obj->GetFieldShortVolatile(MemberOffset(offset));
483 }
484 
Unsafe_putShort(JNIEnv * env,jobject,jobject javaObj,jlong offset,jshort newValue)485 static void Unsafe_putShort(JNIEnv* env, jobject, jobject javaObj, jlong offset, jshort newValue) {
486   ScopedFastNativeObjectAccess soa(env);
487   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
488   // JNI must use non transactional mode.
489   obj->SetFieldShort<false>(MemberOffset(offset), newValue);
490 }
491 
Unsafe_putShortVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jshort newValue)492 static void Unsafe_putShortVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
493                                     jshort newValue) {
494   ScopedFastNativeObjectAccess soa(env);
495   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
496   // JNI must use non transactional mode.
497   obj->SetFieldShortVolatile<false>(MemberOffset(offset), newValue);
498 }
499 
Unsafe_getFloat(JNIEnv * env,jobject,jobject javaObj,jlong offset)500 static jfloat Unsafe_getFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
501   ScopedFastNativeObjectAccess soa(env);
502   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
503   union {int32_t val; jfloat converted;} conv;
504   conv.val = obj->GetField32(MemberOffset(offset));
505   return conv.converted;
506 }
507 
Unsafe_getFloatVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)508 static jfloat Unsafe_getFloatVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
509   ScopedFastNativeObjectAccess soa(env);
510   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
511   union {int32_t val; jfloat converted;} conv;
512   conv.val = obj->GetField32Volatile(MemberOffset(offset));
513   return conv.converted;
514 }
515 
Unsafe_putFloat(JNIEnv * env,jobject,jobject javaObj,jlong offset,jfloat newValue)516 static void Unsafe_putFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset, jfloat newValue) {
517   ScopedFastNativeObjectAccess soa(env);
518   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
519   union {int32_t converted; jfloat val;} conv;
520   conv.val = newValue;
521   // JNI must use non transactional mode.
522   obj->SetField32<false>(MemberOffset(offset), conv.converted);
523 }
524 
Unsafe_putFloatVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jfloat newValue)525 static void Unsafe_putFloatVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
526                                     jfloat newValue) {
527   ScopedFastNativeObjectAccess soa(env);
528   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
529   union {int32_t converted; jfloat val;} conv;
530   conv.val = newValue;
531   // JNI must use non transactional mode.
532   obj->SetField32Volatile<false>(MemberOffset(offset), conv.converted);
533 }
534 
Unsafe_getDouble(JNIEnv * env,jobject,jobject javaObj,jlong offset)535 static jdouble Unsafe_getDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
536   ScopedFastNativeObjectAccess soa(env);
537   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
538   union {int64_t val; jdouble converted;} conv;
539   conv.val = obj->GetField64(MemberOffset(offset));
540   return conv.converted;
541 }
542 
Unsafe_getDoubleVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)543 static jdouble Unsafe_getDoubleVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
544   ScopedFastNativeObjectAccess soa(env);
545   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
546   union {int64_t val; jdouble converted;} conv;
547   conv.val = obj->GetField64Volatile(MemberOffset(offset));
548   return conv.converted;
549 }
550 
Unsafe_putDouble(JNIEnv * env,jobject,jobject javaObj,jlong offset,jdouble newValue)551 static void Unsafe_putDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset, jdouble newValue) {
552   ScopedFastNativeObjectAccess soa(env);
553   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
554   union {int64_t converted; jdouble val;} conv;
555   conv.val = newValue;
556   // JNI must use non transactional mode.
557   obj->SetField64<false>(MemberOffset(offset), conv.converted);
558 }
559 
Unsafe_putDoubleVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jdouble newValue)560 static void Unsafe_putDoubleVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset, jdouble newValue) {
561   ScopedFastNativeObjectAccess soa(env);
562   ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
563   union {int64_t converted; jdouble val;} conv;
564   conv.val = newValue;
565   // JNI must use non transactional mode.
566   obj->SetField64Volatile<false>(MemberOffset(offset), conv.converted);
567 }
568 
Unsafe_loadFence(JNIEnv *,jobject)569 static void Unsafe_loadFence(JNIEnv*, jobject) {
570   std::atomic_thread_fence(std::memory_order_acquire);
571 }
572 
Unsafe_storeFence(JNIEnv *,jobject)573 static void Unsafe_storeFence(JNIEnv*, jobject) {
574   std::atomic_thread_fence(std::memory_order_release);
575 }
576 
Unsafe_fullFence(JNIEnv *,jobject)577 static void Unsafe_fullFence(JNIEnv*, jobject) {
578   std::atomic_thread_fence(std::memory_order_seq_cst);
579 }
580 
Unsafe_park(JNIEnv * env,jobject,jboolean isAbsolute,jlong time)581 static void Unsafe_park(JNIEnv* env, jobject, jboolean isAbsolute, jlong time) {
582   ScopedObjectAccess soa(env);
583   Thread::Current()->Park(isAbsolute, time);
584 }
585 
Unsafe_unpark(JNIEnv * env,jobject,jobject jthread)586 static void Unsafe_unpark(JNIEnv* env, jobject, jobject jthread) {
587   art::ScopedFastNativeObjectAccess soa(env);
588   ObjPtr<mirror::Object> mirror_thread = soa.Decode<mirror::Object>(jthread);
589   if (mirror_thread == nullptr ||
590       !mirror_thread->InstanceOf(WellKnownClasses::java_lang_Thread.Get())) {
591     ThrowIllegalArgumentException("Argument to unpark() was not a Thread");
592     return;
593   }
594   Thread* self = soa.Self();
595   art::MutexLock mu(self, *art::Locks::thread_list_lock_);
596   art::Thread* thread = art::Thread::FromManagedThread(self, mirror_thread);
597   if (thread != nullptr) {
598     thread->Unpark();
599   } else {
600     // If thread is null, that means that either the thread is not started yet,
601     // or the thread has already terminated. Setting the field to true will be
602     // respected when the thread does start, and is harmless if the thread has
603     // already terminated.
604     ArtField* unparked = WellKnownClasses::java_lang_Thread_unparkedBeforeStart;
605     // JNI must use non transactional mode.
606     unparked->SetBoolean<false>(mirror_thread, JNI_TRUE);
607   }
608 }
609 
610 static JNINativeMethod gMethods[] = {
611     FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
612     FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
613     FAST_NATIVE_METHOD(
614         Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
615     FAST_NATIVE_METHOD(Unsafe, compareAndSetInt, "(Ljava/lang/Object;JII)Z"),
616     FAST_NATIVE_METHOD(Unsafe, compareAndSetLong, "(Ljava/lang/Object;JJJ)Z"),
617     FAST_NATIVE_METHOD(Unsafe, compareAndExchangeLong, "(Ljava/lang/Object;JJJ)J"),
618     FAST_NATIVE_METHOD(Unsafe,
619                        compareAndSetReference,
620                        "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
621     FAST_NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"),
622     FAST_NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"),
623     FAST_NATIVE_METHOD(Unsafe, getBooleanVolatile, "(Ljava/lang/Object;J)Z"),
624     FAST_NATIVE_METHOD(Unsafe, putBooleanVolatile, "(Ljava/lang/Object;JZ)V"),
625     FAST_NATIVE_METHOD(Unsafe, getByteVolatile, "(Ljava/lang/Object;J)B"),
626     FAST_NATIVE_METHOD(Unsafe, putByteVolatile, "(Ljava/lang/Object;JB)V"),
627     FAST_NATIVE_METHOD(Unsafe, getShortVolatile, "(Ljava/lang/Object;J)S"),
628     FAST_NATIVE_METHOD(Unsafe, putShortVolatile, "(Ljava/lang/Object;JS)V"),
629     FAST_NATIVE_METHOD(Unsafe, getCharVolatile, "(Ljava/lang/Object;J)C"),
630     FAST_NATIVE_METHOD(Unsafe, putCharVolatile, "(Ljava/lang/Object;JC)V"),
631     FAST_NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"),
632     FAST_NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"),
633     FAST_NATIVE_METHOD(Unsafe, getFloatVolatile, "(Ljava/lang/Object;J)F"),
634     FAST_NATIVE_METHOD(Unsafe, putFloatVolatile, "(Ljava/lang/Object;JF)V"),
635     FAST_NATIVE_METHOD(Unsafe, getDoubleVolatile, "(Ljava/lang/Object;J)D"),
636     FAST_NATIVE_METHOD(Unsafe, putDoubleVolatile, "(Ljava/lang/Object;JD)V"),
637     FAST_NATIVE_METHOD(Unsafe, getReferenceVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
638     FAST_NATIVE_METHOD(Unsafe, putReferenceVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
639     FAST_NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"),
640     FAST_NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"),
641     FAST_NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"),
642     FAST_NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"),
643     FAST_NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"),
644     FAST_NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"),
645     FAST_NATIVE_METHOD(Unsafe, getReference, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
646     FAST_NATIVE_METHOD(Unsafe, putReference, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
647     FAST_NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
648     FAST_NATIVE_METHOD(Unsafe, getArrayBaseOffsetForComponentType, "(Ljava/lang/Class;)I"),
649     FAST_NATIVE_METHOD(Unsafe, getArrayIndexScaleForComponentType, "(Ljava/lang/Class;)I"),
650     FAST_NATIVE_METHOD(Unsafe, addressSize, "()I"),
651     FAST_NATIVE_METHOD(Unsafe, pageSize, "()I"),
652     FAST_NATIVE_METHOD(Unsafe, allocateMemory, "(J)J"),
653     FAST_NATIVE_METHOD(Unsafe, freeMemory, "(J)V"),
654     FAST_NATIVE_METHOD(Unsafe, setMemory, "(JJB)V"),
655     FAST_NATIVE_METHOD(Unsafe, copyMemory0, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V"),
656     FAST_NATIVE_METHOD(Unsafe, getBoolean, "(Ljava/lang/Object;J)Z"),
657 
658     FAST_NATIVE_METHOD(Unsafe, getByte, "(Ljava/lang/Object;J)B"),
659     FAST_NATIVE_METHOD(Unsafe, getChar, "(Ljava/lang/Object;J)C"),
660     FAST_NATIVE_METHOD(Unsafe, getShort, "(Ljava/lang/Object;J)S"),
661     FAST_NATIVE_METHOD(Unsafe, getFloat, "(Ljava/lang/Object;J)F"),
662     FAST_NATIVE_METHOD(Unsafe, getDouble, "(Ljava/lang/Object;J)D"),
663     FAST_NATIVE_METHOD(Unsafe, putBoolean, "(Ljava/lang/Object;JZ)V"),
664     FAST_NATIVE_METHOD(Unsafe, putByte, "(Ljava/lang/Object;JB)V"),
665     FAST_NATIVE_METHOD(Unsafe, putChar, "(Ljava/lang/Object;JC)V"),
666     FAST_NATIVE_METHOD(Unsafe, putShort, "(Ljava/lang/Object;JS)V"),
667     FAST_NATIVE_METHOD(Unsafe, putFloat, "(Ljava/lang/Object;JF)V"),
668     FAST_NATIVE_METHOD(Unsafe, putDouble, "(Ljava/lang/Object;JD)V"),
669     FAST_NATIVE_METHOD(Unsafe, unpark, "(Ljava/lang/Object;)V"),
670     NATIVE_METHOD(Unsafe, park, "(ZJ)V"),
671 
672     // Each of the getFoo variants are overloaded with a call that operates
673     // directively on a native pointer.
674     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getByte, "(J)B", getByteJ),
675     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getChar, "(J)C", getCharJ),
676     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getShort, "(J)S", getShortJ),
677     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getInt, "(J)I", getIntJ),
678     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getLong, "(J)J", getLongJ),
679     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getFloat, "(J)F", getFloatJ),
680     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getDouble, "(J)D", getDoubleJ),
681     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putByte, "(JB)V", putByteJB),
682     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putChar, "(JC)V", putCharJC),
683     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putShort, "(JS)V", putShortJS),
684     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putInt, "(JI)V", putIntJI),
685     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putLong, "(JJ)V", putLongJJ),
686     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putFloat, "(JF)V", putFloatJF),
687     OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putDouble, "(JD)V", putDoubleJD),
688 
689     // CAS
690     FAST_NATIVE_METHOD(Unsafe, loadFence, "()V"),
691     FAST_NATIVE_METHOD(Unsafe, storeFence, "()V"),
692     FAST_NATIVE_METHOD(Unsafe, fullFence, "()V"),
693 };
694 
register_jdk_internal_misc_Unsafe(JNIEnv * env)695 void register_jdk_internal_misc_Unsafe(JNIEnv* env) {
696   REGISTER_NATIVE_METHODS("jdk/internal/misc/Unsafe");
697 }
698 
699 }  // namespace art
700