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