blob: 307a2fa8b9a9fdca7317dbc0c5513f860e2d02d6 [file] [log] [blame]
Sorin Basca2f01e8e2021-06-18 06:44:07 +00001/*
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.h"
38
39namespace art {
40
Sorin Bascab6bb6032021-10-26 13:38:54 +000041namespace {
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).
44 bool ValidJniSizeArgument(jlong size) REQUIRES_SHARED(Locks::mutator_lock_) {
45 const jlong maybe_truncated_size = static_cast<jlong>(static_cast<size_t>(size));
Sorin Basca91c795f2021-11-02 22:23:06 +000046 // size is nonnegative and fits into size_t
Sorin Bascab6bb6032021-10-26 13:38:54 +000047 if (LIKELY(size >= 0 && size == maybe_truncated_size)) {
48 return true;
49 }
50 ThrowRuntimeException("Bad size: %" PRIu64, size);
51 return false;
52 }
Sorin Bascab6bb6032021-10-26 13:38:54 +000053} // namespace
54
Sorin Basca0069ad72021-09-17 17:33:09 +000055static jboolean Unsafe_compareAndSetInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
Sorin Basca507cf902021-10-06 12:04:56 +000056 jint expectedValue, jint newValue) {
Sorin Basca0069ad72021-09-17 17:33:09 +000057 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
Sorin Basca507cf902021-10-06 12:04:56 +000068static 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
76static jboolean Unsafe_compareAndSetLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
77 jlong expectedValue, jlong newValue) {
Sorin Basca2f01e8e2021-06-18 06:44:07 +000078 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
Sorin Basca507cf902021-10-06 12:04:56 +000087static 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
95static jboolean Unsafe_compareAndSetObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
96 jobject javaExpectedValue, jobject javaNewValue) {
Sorin Basca2f01e8e2021-06-18 06:44:07 +000097 ScopedFastNativeObjectAccess soa(env);
98 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
99 ObjPtr<mirror::Object> expectedValue = soa.Decode<mirror::Object>(javaExpectedValue);
100 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
101 // JNI must use non transactional mode.
102 if (kUseReadBarrier) {
103 // Need to make sure the reference stored in the field is a to-space one before attempting the
104 // CAS or the CAS could fail incorrectly.
105 // Note that the read barrier load does NOT need to be volatile.
106 mirror::HeapReference<mirror::Object>* field_addr =
107 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
108 reinterpret_cast<uint8_t*>(obj.Ptr()) + static_cast<size_t>(offset));
Sorin Basca507cf902021-10-06 12:04:56 +0000109 ReadBarrier::Barrier<mirror::Object, /*kIsVolatile=*/ false, kWithReadBarrier,
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000110 /* kAlwaysUpdateField= */ true>(
111 obj.Ptr(),
112 MemberOffset(offset),
113 field_addr);
114 }
115 bool success = obj->CasFieldObject<false>(MemberOffset(offset),
116 expectedValue,
117 newValue,
118 CASMode::kStrong,
119 std::memory_order_seq_cst);
120 return success ? JNI_TRUE : JNI_FALSE;
121}
122
Sorin Basca507cf902021-10-06 12:04:56 +0000123static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject obj, jobject javaObj, jlong offset,
124 jobject javaExpectedValue, jobject javaNewValue) {
125 // compareAndSetObject has the same semantics as compareAndSwapObject, except for
126 // being strict (volatile). Since this was implemented in a strict mode it can
127 // just call the volatile version unless it gets relaxed.
128 return Unsafe_compareAndSetObject(env, obj, javaObj, offset, javaExpectedValue, javaNewValue);
129}
130
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000131static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
132 ScopedFastNativeObjectAccess soa(env);
133 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
134 return obj->GetField32(MemberOffset(offset));
135}
136
137static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
138 ScopedFastNativeObjectAccess soa(env);
139 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
140 return obj->GetField32Volatile(MemberOffset(offset));
141}
142
143static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
144 ScopedFastNativeObjectAccess soa(env);
145 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
146 // JNI must use non transactional mode.
147 obj->SetField32<false>(MemberOffset(offset), newValue);
148}
149
150static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
151 jint newValue) {
152 ScopedFastNativeObjectAccess soa(env);
153 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
154 // JNI must use non transactional mode.
155 obj->SetField32Volatile<false>(MemberOffset(offset), newValue);
156}
157
158static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
159 jint newValue) {
160 ScopedFastNativeObjectAccess soa(env);
161 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
162 // TODO: A release store is likely to be faster on future processors.
163 std::atomic_thread_fence(std::memory_order_release);
164 // JNI must use non transactional mode.
165 obj->SetField32<false>(MemberOffset(offset), newValue);
166}
167
168static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
169 ScopedFastNativeObjectAccess soa(env);
170 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
171 return obj->GetField64(MemberOffset(offset));
172}
173
174static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
175 ScopedFastNativeObjectAccess soa(env);
176 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
177 return obj->GetField64Volatile(MemberOffset(offset));
178}
179
180static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
181 ScopedFastNativeObjectAccess soa(env);
182 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
183 // JNI must use non transactional mode.
184 obj->SetField64<false>(MemberOffset(offset), newValue);
185}
186
187static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
188 jlong newValue) {
189 ScopedFastNativeObjectAccess soa(env);
190 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
191 // JNI must use non transactional mode.
192 obj->SetField64Volatile<false>(MemberOffset(offset), newValue);
193}
194
195static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
196 jlong newValue) {
197 ScopedFastNativeObjectAccess soa(env);
198 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
199 std::atomic_thread_fence(std::memory_order_release);
200 // JNI must use non transactional mode.
201 obj->SetField64<false>(MemberOffset(offset), newValue);
202}
203
204static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
205 ScopedFastNativeObjectAccess soa(env);
206 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
207 ObjPtr<mirror::Object> value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
208 return soa.AddLocalReference<jobject>(value);
209}
210
211static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
212 ScopedFastNativeObjectAccess soa(env);
213 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
214 ObjPtr<mirror::Object> value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
215 return soa.AddLocalReference<jobject>(value);
216}
217
218static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
219 jobject javaNewValue) {
220 ScopedFastNativeObjectAccess soa(env);
221 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
222 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
223 // JNI must use non transactional mode.
224 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
225}
226
227static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
228 jobject javaNewValue) {
229 ScopedFastNativeObjectAccess soa(env);
230 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
231 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
232 // JNI must use non transactional mode.
233 obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue);
234}
235
236static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
237 jobject javaNewValue) {
238 ScopedFastNativeObjectAccess soa(env);
239 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
240 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
241 std::atomic_thread_fence(std::memory_order_release);
242 // JNI must use non transactional mode.
243 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
244}
245
246static jint Unsafe_getArrayBaseOffsetForComponentType(JNIEnv* env, jclass, jclass component_class) {
247 ScopedFastNativeObjectAccess soa(env);
248 ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
249 Primitive::Type primitive_type = component->GetPrimitiveType();
250 return mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value();
251}
252
253static jint Unsafe_getArrayIndexScaleForComponentType(JNIEnv* env, jclass, jclass component_class) {
254 ScopedFastNativeObjectAccess soa(env);
255 ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
256 Primitive::Type primitive_type = component->GetPrimitiveType();
257 return Primitive::ComponentSize(primitive_type);
258}
259
260static jint Unsafe_addressSize(JNIEnv* env ATTRIBUTE_UNUSED, jobject ob ATTRIBUTE_UNUSED) {
261 return sizeof(void*);
262}
263
264static jint Unsafe_pageSize(JNIEnv* env ATTRIBUTE_UNUSED, jobject ob ATTRIBUTE_UNUSED) {
265 return sysconf(_SC_PAGESIZE);
266}
267
268static jlong Unsafe_allocateMemory(JNIEnv* env, jobject, jlong bytes) {
269 ScopedFastNativeObjectAccess soa(env);
Sorin Bascab6bb6032021-10-26 13:38:54 +0000270 if (bytes == 0) {
Orion Hodson0a126312021-10-19 08:23:42 +0000271 return 0;
272 }
Sorin Bascab6bb6032021-10-26 13:38:54 +0000273 // bytes is nonnegative and fits into size_t
274 if (!ValidJniSizeArgument(bytes)) {
275 DCHECK(soa.Self()->IsExceptionPending());
276 return 0;
277 }
278 const size_t malloc_bytes = static_cast<size_t>(bytes);
279 void* mem = malloc(malloc_bytes);
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000280 if (mem == nullptr) {
281 soa.Self()->ThrowOutOfMemoryError("native alloc");
282 return 0;
283 }
Sorin Bascab6bb6032021-10-26 13:38:54 +0000284 return reinterpret_cast<uintptr_t>(mem);
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000285}
286
287static void Unsafe_freeMemory(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
288 free(reinterpret_cast<void*>(static_cast<uintptr_t>(address)));
289}
290
291static void Unsafe_setMemory(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong bytes, jbyte value) {
292 memset(reinterpret_cast<void*>(static_cast<uintptr_t>(address)), value, bytes);
293}
294
295static jbyte Unsafe_getByteJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
296 return *reinterpret_cast<jbyte*>(address);
297}
298
299static void Unsafe_putByteJB(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jbyte value) {
300 *reinterpret_cast<jbyte*>(address) = value;
301}
302
303static jshort Unsafe_getShortJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
304 return *reinterpret_cast<jshort*>(address);
305}
306
307static void Unsafe_putShortJS(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jshort value) {
308 *reinterpret_cast<jshort*>(address) = value;
309}
310
311static jchar Unsafe_getCharJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
312 return *reinterpret_cast<jchar*>(address);
313}
314
315static void Unsafe_putCharJC(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jchar value) {
316 *reinterpret_cast<jchar*>(address) = value;
317}
318
319static jint Unsafe_getIntJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
320 return *reinterpret_cast<jint*>(address);
321}
322
323static void Unsafe_putIntJI(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jint value) {
324 *reinterpret_cast<jint*>(address) = value;
325}
326
327static jlong Unsafe_getLongJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
328 return *reinterpret_cast<jlong*>(address);
329}
330
331static void Unsafe_putLongJJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong value) {
332 *reinterpret_cast<jlong*>(address) = value;
333}
334
335static jfloat Unsafe_getFloatJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
336 return *reinterpret_cast<jfloat*>(address);
337}
338
339static void Unsafe_putFloatJF(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jfloat value) {
340 *reinterpret_cast<jfloat*>(address) = value;
341}
342static jdouble Unsafe_getDoubleJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
343 return *reinterpret_cast<jdouble*>(address);
344}
345
346static void Unsafe_putDoubleJD(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jdouble value) {
347 *reinterpret_cast<jdouble*>(address) = value;
348}
349
Sorin Basca91c795f2021-11-02 22:23:06 +0000350static void Unsafe_copyMemory0(JNIEnv *env, jobject unsafe ATTRIBUTE_UNUSED,
351 jobject srcObj, jlong srcOffset,
352 jobject dstObj, jlong dstOffset,
353 jlong size) {
Sorin Bascab6bb6032021-10-26 13:38:54 +0000354 ScopedFastNativeObjectAccess soa(env);
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000355 if (size == 0) {
356 return;
357 }
Sorin Bascab6bb6032021-10-26 13:38:54 +0000358 if (!ValidJniSizeArgument(size)) {
359 DCHECK(soa.Self()->IsExceptionPending());
360 return;
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000361 }
Sorin Bascab6bb6032021-10-26 13:38:54 +0000362 const size_t memcpy_size = static_cast<size_t>(size);
Sorin Basca91c795f2021-11-02 22:23:06 +0000363 const size_t src_offset = static_cast<size_t>(srcOffset);
364 ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
365 const size_t dst_offset = static_cast<size_t>(dstOffset);
366 ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
367 memcpy(reinterpret_cast<uint8_t*>(dst.Ptr()) + dst_offset,
368 reinterpret_cast<uint8_t*>(src.Ptr()) + src_offset,
369 memcpy_size);
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000370}
371
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000372static jboolean Unsafe_getBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
373 ScopedFastNativeObjectAccess soa(env);
374 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
375 return obj->GetFieldBoolean(MemberOffset(offset));
376}
377
378static void Unsafe_putBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset, jboolean newValue) {
379 ScopedFastNativeObjectAccess soa(env);
380 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
381 // JNI must use non transactional mode (SetField8 is non-transactional).
382 obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
383}
384
385static jbyte Unsafe_getByte(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
386 ScopedFastNativeObjectAccess soa(env);
387 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
388 return obj->GetFieldByte(MemberOffset(offset));
389}
390
391static void Unsafe_putByte(JNIEnv* env, jobject, jobject javaObj, jlong offset, jbyte newValue) {
392 ScopedFastNativeObjectAccess soa(env);
393 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
394 // JNI must use non transactional mode.
395 obj->SetFieldByte<false>(MemberOffset(offset), newValue);
396}
397
398static jchar Unsafe_getChar(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
399 ScopedFastNativeObjectAccess soa(env);
400 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
401 return obj->GetFieldChar(MemberOffset(offset));
402}
403
404static void Unsafe_putChar(JNIEnv* env, jobject, jobject javaObj, jlong offset, jchar newValue) {
405 ScopedFastNativeObjectAccess soa(env);
406 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
407 // JNI must use non transactional mode.
408 obj->SetFieldChar<false>(MemberOffset(offset), newValue);
409}
410
411static jshort Unsafe_getShort(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
412 ScopedFastNativeObjectAccess soa(env);
413 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
414 return obj->GetFieldShort(MemberOffset(offset));
415}
416
417static void Unsafe_putShort(JNIEnv* env, jobject, jobject javaObj, jlong offset, jshort newValue) {
418 ScopedFastNativeObjectAccess soa(env);
419 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
420 // JNI must use non transactional mode.
421 obj->SetFieldShort<false>(MemberOffset(offset), newValue);
422}
423
424static jfloat Unsafe_getFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
425 ScopedFastNativeObjectAccess soa(env);
426 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
427 union {int32_t val; jfloat converted;} conv;
428 conv.val = obj->GetField32(MemberOffset(offset));
429 return conv.converted;
430}
431
432static void Unsafe_putFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset, jfloat newValue) {
433 ScopedFastNativeObjectAccess soa(env);
434 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
435 union {int32_t converted; jfloat val;} conv;
436 conv.val = newValue;
437 // JNI must use non transactional mode.
438 obj->SetField32<false>(MemberOffset(offset), conv.converted);
439}
440
441static jdouble Unsafe_getDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
442 ScopedFastNativeObjectAccess soa(env);
443 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
444 union {int64_t val; jdouble converted;} conv;
445 conv.val = obj->GetField64(MemberOffset(offset));
446 return conv.converted;
447}
448
449static void Unsafe_putDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset, jdouble newValue) {
450 ScopedFastNativeObjectAccess soa(env);
451 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
452 union {int64_t converted; jdouble val;} conv;
453 conv.val = newValue;
454 // JNI must use non transactional mode.
455 obj->SetField64<false>(MemberOffset(offset), conv.converted);
456}
457
458static void Unsafe_loadFence(JNIEnv*, jobject) {
459 std::atomic_thread_fence(std::memory_order_acquire);
460}
461
462static void Unsafe_storeFence(JNIEnv*, jobject) {
463 std::atomic_thread_fence(std::memory_order_release);
464}
465
466static void Unsafe_fullFence(JNIEnv*, jobject) {
467 std::atomic_thread_fence(std::memory_order_seq_cst);
468}
469
470static void Unsafe_park(JNIEnv* env, jobject, jboolean isAbsolute, jlong time) {
471 ScopedObjectAccess soa(env);
472 Thread::Current()->Park(isAbsolute, time);
473}
474
475static void Unsafe_unpark(JNIEnv* env, jobject, jobject jthread) {
476 art::ScopedFastNativeObjectAccess soa(env);
477 if (jthread == nullptr || !env->IsInstanceOf(jthread, WellKnownClasses::java_lang_Thread)) {
478 ThrowIllegalArgumentException("Argument to unpark() was not a Thread");
479 return;
480 }
481 art::MutexLock mu(soa.Self(), *art::Locks::thread_list_lock_);
482 art::Thread* thread = art::Thread::FromManagedThread(soa, jthread);
483 if (thread != nullptr) {
484 thread->Unpark();
485 } else {
486 // If thread is null, that means that either the thread is not started yet,
487 // or the thread has already terminated. Setting the field to true will be
488 // respected when the thread does start, and is harmless if the thread has
489 // already terminated.
490 ArtField* unparked =
491 jni::DecodeArtField(WellKnownClasses::java_lang_Thread_unparkedBeforeStart);
492 // JNI must use non transactional mode.
493 unparked->SetBoolean<false>(soa.Decode<mirror::Object>(jthread), JNI_TRUE);
494 }
495}
496
497static JNINativeMethod gMethods[] = {
498 FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
499 FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
500 FAST_NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
Sorin Basca0069ad72021-09-17 17:33:09 +0000501 FAST_NATIVE_METHOD(Unsafe, compareAndSetInt, "(Ljava/lang/Object;JII)Z"),
Sorin Basca507cf902021-10-06 12:04:56 +0000502 FAST_NATIVE_METHOD(Unsafe, compareAndSetLong, "(Ljava/lang/Object;JJJ)Z"),
503 FAST_NATIVE_METHOD(Unsafe, compareAndSetObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000504 FAST_NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"),
505 FAST_NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"),
506 FAST_NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"),
507 FAST_NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"),
508 FAST_NATIVE_METHOD(Unsafe, getObjectVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
509 FAST_NATIVE_METHOD(Unsafe, putObjectVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
510 FAST_NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"),
511 FAST_NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"),
512 FAST_NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"),
513 FAST_NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"),
514 FAST_NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"),
515 FAST_NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"),
516 FAST_NATIVE_METHOD(Unsafe, getObject, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
517 FAST_NATIVE_METHOD(Unsafe, putObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
518 FAST_NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
519 FAST_NATIVE_METHOD(Unsafe, getArrayBaseOffsetForComponentType, "(Ljava/lang/Class;)I"),
520 FAST_NATIVE_METHOD(Unsafe, getArrayIndexScaleForComponentType, "(Ljava/lang/Class;)I"),
521 FAST_NATIVE_METHOD(Unsafe, addressSize, "()I"),
522 FAST_NATIVE_METHOD(Unsafe, pageSize, "()I"),
523 FAST_NATIVE_METHOD(Unsafe, allocateMemory, "(J)J"),
524 FAST_NATIVE_METHOD(Unsafe, freeMemory, "(J)V"),
525 FAST_NATIVE_METHOD(Unsafe, setMemory, "(JJB)V"),
Sorin Basca91c795f2021-11-02 22:23:06 +0000526 FAST_NATIVE_METHOD(Unsafe, copyMemory0, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V"),
Sorin Basca2f01e8e2021-06-18 06:44:07 +0000527 FAST_NATIVE_METHOD(Unsafe, getBoolean, "(Ljava/lang/Object;J)Z"),
528
529 FAST_NATIVE_METHOD(Unsafe, getByte, "(Ljava/lang/Object;J)B"),
530 FAST_NATIVE_METHOD(Unsafe, getChar, "(Ljava/lang/Object;J)C"),
531 FAST_NATIVE_METHOD(Unsafe, getShort, "(Ljava/lang/Object;J)S"),
532 FAST_NATIVE_METHOD(Unsafe, getFloat, "(Ljava/lang/Object;J)F"),
533 FAST_NATIVE_METHOD(Unsafe, getDouble, "(Ljava/lang/Object;J)D"),
534 FAST_NATIVE_METHOD(Unsafe, putBoolean, "(Ljava/lang/Object;JZ)V"),
535 FAST_NATIVE_METHOD(Unsafe, putByte, "(Ljava/lang/Object;JB)V"),
536 FAST_NATIVE_METHOD(Unsafe, putChar, "(Ljava/lang/Object;JC)V"),
537 FAST_NATIVE_METHOD(Unsafe, putShort, "(Ljava/lang/Object;JS)V"),
538 FAST_NATIVE_METHOD(Unsafe, putFloat, "(Ljava/lang/Object;JF)V"),
539 FAST_NATIVE_METHOD(Unsafe, putDouble, "(Ljava/lang/Object;JD)V"),
540 FAST_NATIVE_METHOD(Unsafe, unpark, "(Ljava/lang/Object;)V"),
541 NATIVE_METHOD(Unsafe, park, "(ZJ)V"),
542
543 // Each of the getFoo variants are overloaded with a call that operates
544 // directively on a native pointer.
545 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getByte, "(J)B", getByteJ),
546 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getChar, "(J)C", getCharJ),
547 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getShort, "(J)S", getShortJ),
548 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getInt, "(J)I", getIntJ),
549 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getLong, "(J)J", getLongJ),
550 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getFloat, "(J)F", getFloatJ),
551 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getDouble, "(J)D", getDoubleJ),
552 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putByte, "(JB)V", putByteJB),
553 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putChar, "(JC)V", putCharJC),
554 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putShort, "(JS)V", putShortJS),
555 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putInt, "(JI)V", putIntJI),
556 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putLong, "(JJ)V", putLongJJ),
557 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putFloat, "(JF)V", putFloatJF),
558 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putDouble, "(JD)V", putDoubleJD),
559
560 // CAS
561 FAST_NATIVE_METHOD(Unsafe, loadFence, "()V"),
562 FAST_NATIVE_METHOD(Unsafe, storeFence, "()V"),
563 FAST_NATIVE_METHOD(Unsafe, fullFence, "()V"),
564};
565
566void register_jdk_internal_misc_Unsafe(JNIEnv* env) {
567 REGISTER_NATIVE_METHODS("jdk/internal/misc/Unsafe");
568}
569
570} // namespace art