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