1 /*
2 * Copyright (C) 2008 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 "sun_misc_Unsafe.h"
18 #include "common_throws.h"
19 #include "gc/accounting/card_table-inl.h"
20 #include "jni_internal.h"
21 #include "mirror/array.h"
22 #include "mirror/class-inl.h"
23 #include "mirror/object-inl.h"
24 #include "scoped_fast_native_object_access-inl.h"
25
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <atomic>
30
31 namespace art {
32
Unsafe_compareAndSwapInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint expectedValue,jint newValue)33 static jboolean Unsafe_compareAndSwapInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
34 jint expectedValue, jint newValue) {
35 ScopedFastNativeObjectAccess soa(env);
36 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
37 // JNI must use non transactional mode.
38 bool success = obj->CasFieldStrongSequentiallyConsistent32<false>(MemberOffset(offset),
39 expectedValue,
40 newValue);
41 return success ? JNI_TRUE : JNI_FALSE;
42 }
43
Unsafe_compareAndSwapLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong expectedValue,jlong newValue)44 static jboolean Unsafe_compareAndSwapLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
45 jlong expectedValue, jlong newValue) {
46 ScopedFastNativeObjectAccess soa(env);
47 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
48 // JNI must use non transactional mode.
49 bool success = obj->CasFieldStrongSequentiallyConsistent64<false>(MemberOffset(offset),
50 expectedValue,
51 newValue);
52 return success ? JNI_TRUE : JNI_FALSE;
53 }
54
Unsafe_compareAndSwapObject(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaExpectedValue,jobject javaNewValue)55 static jboolean Unsafe_compareAndSwapObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
56 jobject javaExpectedValue, jobject javaNewValue) {
57 ScopedFastNativeObjectAccess soa(env);
58 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
59 ObjPtr<mirror::Object> expectedValue = soa.Decode<mirror::Object>(javaExpectedValue);
60 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
61 // JNI must use non transactional mode.
62 if (kUseReadBarrier) {
63 // Need to make sure the reference stored in the field is a to-space one before attempting the
64 // CAS or the CAS could fail incorrectly.
65 mirror::HeapReference<mirror::Object>* field_addr =
66 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(
67 reinterpret_cast<uint8_t*>(obj.Ptr()) + static_cast<size_t>(offset));
68 ReadBarrier::Barrier<mirror::Object, kWithReadBarrier, /* kAlwaysUpdateField */ true>(
69 obj.Ptr(),
70 MemberOffset(offset),
71 field_addr);
72 }
73 bool success = obj->CasFieldStrongSequentiallyConsistentObject<false>(MemberOffset(offset),
74 expectedValue,
75 newValue);
76 return success ? JNI_TRUE : JNI_FALSE;
77 }
78
Unsafe_getInt(JNIEnv * env,jobject,jobject javaObj,jlong offset)79 static jint Unsafe_getInt(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
80 ScopedFastNativeObjectAccess soa(env);
81 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
82 return obj->GetField32(MemberOffset(offset));
83 }
84
Unsafe_getIntVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)85 static jint Unsafe_getIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
86 ScopedFastNativeObjectAccess soa(env);
87 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
88 return obj->GetField32Volatile(MemberOffset(offset));
89 }
90
Unsafe_putInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)91 static void Unsafe_putInt(JNIEnv* env, jobject, jobject javaObj, jlong offset, jint newValue) {
92 ScopedFastNativeObjectAccess soa(env);
93 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
94 // JNI must use non transactional mode.
95 obj->SetField32<false>(MemberOffset(offset), newValue);
96 }
97
Unsafe_putIntVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)98 static void Unsafe_putIntVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
99 jint newValue) {
100 ScopedFastNativeObjectAccess soa(env);
101 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
102 // JNI must use non transactional mode.
103 obj->SetField32Volatile<false>(MemberOffset(offset), newValue);
104 }
105
Unsafe_putOrderedInt(JNIEnv * env,jobject,jobject javaObj,jlong offset,jint newValue)106 static void Unsafe_putOrderedInt(JNIEnv* env, jobject, jobject javaObj, jlong offset,
107 jint newValue) {
108 ScopedFastNativeObjectAccess soa(env);
109 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
110 QuasiAtomic::ThreadFenceRelease();
111 // JNI must use non transactional mode.
112 obj->SetField32<false>(MemberOffset(offset), newValue);
113 }
114
Unsafe_getLong(JNIEnv * env,jobject,jobject javaObj,jlong offset)115 static jlong Unsafe_getLong(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
116 ScopedFastNativeObjectAccess soa(env);
117 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
118 return obj->GetField64(MemberOffset(offset));
119 }
120
Unsafe_getLongVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)121 static jlong Unsafe_getLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
122 ScopedFastNativeObjectAccess soa(env);
123 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
124 return obj->GetField64Volatile(MemberOffset(offset));
125 }
126
Unsafe_putLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)127 static void Unsafe_putLong(JNIEnv* env, jobject, jobject javaObj, jlong offset, jlong newValue) {
128 ScopedFastNativeObjectAccess soa(env);
129 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
130 // JNI must use non transactional mode.
131 obj->SetField64<false>(MemberOffset(offset), newValue);
132 }
133
Unsafe_putLongVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)134 static void Unsafe_putLongVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
135 jlong newValue) {
136 ScopedFastNativeObjectAccess soa(env);
137 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
138 // JNI must use non transactional mode.
139 obj->SetField64Volatile<false>(MemberOffset(offset), newValue);
140 }
141
Unsafe_putOrderedLong(JNIEnv * env,jobject,jobject javaObj,jlong offset,jlong newValue)142 static void Unsafe_putOrderedLong(JNIEnv* env, jobject, jobject javaObj, jlong offset,
143 jlong newValue) {
144 ScopedFastNativeObjectAccess soa(env);
145 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
146 QuasiAtomic::ThreadFenceRelease();
147 // JNI must use non transactional mode.
148 obj->SetField64<false>(MemberOffset(offset), newValue);
149 }
150
Unsafe_getObjectVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset)151 static jobject Unsafe_getObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
152 ScopedFastNativeObjectAccess soa(env);
153 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
154 ObjPtr<mirror::Object> value = obj->GetFieldObjectVolatile<mirror::Object>(MemberOffset(offset));
155 return soa.AddLocalReference<jobject>(value);
156 }
157
Unsafe_getObject(JNIEnv * env,jobject,jobject javaObj,jlong offset)158 static jobject Unsafe_getObject(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
159 ScopedFastNativeObjectAccess soa(env);
160 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
161 ObjPtr<mirror::Object> value = obj->GetFieldObject<mirror::Object>(MemberOffset(offset));
162 return soa.AddLocalReference<jobject>(value);
163 }
164
Unsafe_putObject(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)165 static void Unsafe_putObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
166 jobject javaNewValue) {
167 ScopedFastNativeObjectAccess soa(env);
168 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
169 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
170 // JNI must use non transactional mode.
171 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
172 }
173
Unsafe_putObjectVolatile(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)174 static void Unsafe_putObjectVolatile(JNIEnv* env, jobject, jobject javaObj, jlong offset,
175 jobject javaNewValue) {
176 ScopedFastNativeObjectAccess soa(env);
177 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
178 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
179 // JNI must use non transactional mode.
180 obj->SetFieldObjectVolatile<false>(MemberOffset(offset), newValue);
181 }
182
Unsafe_putOrderedObject(JNIEnv * env,jobject,jobject javaObj,jlong offset,jobject javaNewValue)183 static void Unsafe_putOrderedObject(JNIEnv* env, jobject, jobject javaObj, jlong offset,
184 jobject javaNewValue) {
185 ScopedFastNativeObjectAccess soa(env);
186 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
187 ObjPtr<mirror::Object> newValue = soa.Decode<mirror::Object>(javaNewValue);
188 QuasiAtomic::ThreadFenceRelease();
189 // JNI must use non transactional mode.
190 obj->SetFieldObject<false>(MemberOffset(offset), newValue);
191 }
192
Unsafe_getArrayBaseOffsetForComponentType(JNIEnv * env,jclass,jobject component_class)193 static jint Unsafe_getArrayBaseOffsetForComponentType(JNIEnv* env, jclass, jobject component_class) {
194 ScopedFastNativeObjectAccess soa(env);
195 ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
196 Primitive::Type primitive_type = component->GetPrimitiveType();
197 return mirror::Array::DataOffset(Primitive::ComponentSize(primitive_type)).Int32Value();
198 }
199
Unsafe_getArrayIndexScaleForComponentType(JNIEnv * env,jclass,jobject component_class)200 static jint Unsafe_getArrayIndexScaleForComponentType(JNIEnv* env, jclass, jobject component_class) {
201 ScopedFastNativeObjectAccess soa(env);
202 ObjPtr<mirror::Class> component = soa.Decode<mirror::Class>(component_class);
203 Primitive::Type primitive_type = component->GetPrimitiveType();
204 return Primitive::ComponentSize(primitive_type);
205 }
206
Unsafe_addressSize(JNIEnv * env ATTRIBUTE_UNUSED,jobject ob ATTRIBUTE_UNUSED)207 static jint Unsafe_addressSize(JNIEnv* env ATTRIBUTE_UNUSED, jobject ob ATTRIBUTE_UNUSED) {
208 return sizeof(void*);
209 }
210
Unsafe_pageSize(JNIEnv * env ATTRIBUTE_UNUSED,jobject ob ATTRIBUTE_UNUSED)211 static jint Unsafe_pageSize(JNIEnv* env ATTRIBUTE_UNUSED, jobject ob ATTRIBUTE_UNUSED) {
212 return sysconf(_SC_PAGESIZE);
213 }
214
Unsafe_allocateMemory(JNIEnv * env,jobject,jlong bytes)215 static jlong Unsafe_allocateMemory(JNIEnv* env, jobject, jlong bytes) {
216 ScopedFastNativeObjectAccess soa(env);
217 // bytes is nonnegative and fits into size_t
218 if (bytes < 0 || bytes != (jlong)(size_t) bytes) {
219 ThrowIllegalAccessException("wrong number of bytes");
220 return 0;
221 }
222 void* mem = malloc(bytes);
223 if (mem == nullptr) {
224 soa.Self()->ThrowOutOfMemoryError("native alloc");
225 return 0;
226 }
227 return (uintptr_t) mem;
228 }
229
Unsafe_freeMemory(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)230 static void Unsafe_freeMemory(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
231 free(reinterpret_cast<void*>(static_cast<uintptr_t>(address)));
232 }
233
Unsafe_setMemory(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jlong bytes,jbyte value)234 static void Unsafe_setMemory(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong bytes, jbyte value) {
235 memset(reinterpret_cast<void*>(static_cast<uintptr_t>(address)), value, bytes);
236 }
237
Unsafe_getByteJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)238 static jbyte Unsafe_getByteJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
239 return *reinterpret_cast<jbyte*>(address);
240 }
241
Unsafe_putByteJB(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jbyte value)242 static void Unsafe_putByteJB(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jbyte value) {
243 *reinterpret_cast<jbyte*>(address) = value;
244 }
245
Unsafe_getShortJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)246 static jshort Unsafe_getShortJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
247 return *reinterpret_cast<jshort*>(address);
248 }
249
Unsafe_putShortJS(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jshort value)250 static void Unsafe_putShortJS(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jshort value) {
251 *reinterpret_cast<jshort*>(address) = value;
252 }
253
Unsafe_getCharJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)254 static jchar Unsafe_getCharJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
255 return *reinterpret_cast<jchar*>(address);
256 }
257
Unsafe_putCharJC(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jchar value)258 static void Unsafe_putCharJC(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jchar value) {
259 *reinterpret_cast<jchar*>(address) = value;
260 }
261
Unsafe_getIntJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)262 static jint Unsafe_getIntJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
263 return *reinterpret_cast<jint*>(address);
264 }
265
Unsafe_putIntJI(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jint value)266 static void Unsafe_putIntJI(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jint value) {
267 *reinterpret_cast<jint*>(address) = value;
268 }
269
Unsafe_getLongJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)270 static jlong Unsafe_getLongJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
271 return *reinterpret_cast<jlong*>(address);
272 }
273
Unsafe_putLongJJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jlong value)274 static void Unsafe_putLongJJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jlong value) {
275 *reinterpret_cast<jlong*>(address) = value;
276 }
277
Unsafe_getFloatJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)278 static jfloat Unsafe_getFloatJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
279 return *reinterpret_cast<jfloat*>(address);
280 }
281
Unsafe_putFloatJF(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jfloat value)282 static void Unsafe_putFloatJF(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jfloat value) {
283 *reinterpret_cast<jfloat*>(address) = value;
284 }
Unsafe_getDoubleJ(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address)285 static jdouble Unsafe_getDoubleJ(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address) {
286 return *reinterpret_cast<jdouble*>(address);
287 }
288
Unsafe_putDoubleJD(JNIEnv * env ATTRIBUTE_UNUSED,jobject,jlong address,jdouble value)289 static void Unsafe_putDoubleJD(JNIEnv* env ATTRIBUTE_UNUSED, jobject, jlong address, jdouble value) {
290 *reinterpret_cast<jdouble*>(address) = value;
291 }
292
Unsafe_copyMemory(JNIEnv * env,jobject unsafe ATTRIBUTE_UNUSED,jlong src,jlong dst,jlong size)293 static void Unsafe_copyMemory(JNIEnv *env, jobject unsafe ATTRIBUTE_UNUSED, jlong src,
294 jlong dst, jlong size) {
295 if (size == 0) {
296 return;
297 }
298 // size is nonnegative and fits into size_t
299 if (size < 0 || size != (jlong)(size_t) size) {
300 ScopedFastNativeObjectAccess soa(env);
301 ThrowIllegalAccessException("wrong number of bytes");
302 }
303 size_t sz = (size_t)size;
304 memcpy(reinterpret_cast<void *>(dst), reinterpret_cast<void *>(src), sz);
305 }
306
307 template<typename T>
copyToArray(jlong srcAddr,ObjPtr<mirror::PrimitiveArray<T>> array,size_t array_offset,size_t size)308 static void copyToArray(jlong srcAddr,
309 ObjPtr<mirror::PrimitiveArray<T>> array,
310 size_t array_offset,
311 size_t size)
312 REQUIRES_SHARED(Locks::mutator_lock_) {
313 const T* src = reinterpret_cast<T*>(srcAddr);
314 size_t sz = size / sizeof(T);
315 size_t of = array_offset / sizeof(T);
316 for (size_t i = 0; i < sz; ++i) {
317 array->Set(i + of, *(src + i));
318 }
319 }
320
321 template<typename T>
copyFromArray(jlong dstAddr,ObjPtr<mirror::PrimitiveArray<T>> array,size_t array_offset,size_t size)322 static void copyFromArray(jlong dstAddr,
323 ObjPtr<mirror::PrimitiveArray<T>> array,
324 size_t array_offset,
325 size_t size)
326 REQUIRES_SHARED(Locks::mutator_lock_) {
327 T* dst = reinterpret_cast<T*>(dstAddr);
328 size_t sz = size / sizeof(T);
329 size_t of = array_offset / sizeof(T);
330 for (size_t i = 0; i < sz; ++i) {
331 *(dst + i) = array->Get(i + of);
332 }
333 }
334
Unsafe_copyMemoryToPrimitiveArray(JNIEnv * env,jobject unsafe ATTRIBUTE_UNUSED,jlong srcAddr,jobject dstObj,jlong dstOffset,jlong size)335 static void Unsafe_copyMemoryToPrimitiveArray(JNIEnv *env,
336 jobject unsafe ATTRIBUTE_UNUSED,
337 jlong srcAddr,
338 jobject dstObj,
339 jlong dstOffset,
340 jlong size) {
341 ScopedObjectAccess soa(env);
342 if (size == 0) {
343 return;
344 }
345 // size is nonnegative and fits into size_t
346 if (size < 0 || size != (jlong)(size_t) size) {
347 ThrowIllegalAccessException("wrong number of bytes");
348 }
349 size_t sz = (size_t)size;
350 size_t dst_offset = (size_t)dstOffset;
351 ObjPtr<mirror::Object> dst = soa.Decode<mirror::Object>(dstObj);
352 ObjPtr<mirror::Class> component_type = dst->GetClass()->GetComponentType();
353 if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
354 copyToArray(srcAddr, MakeObjPtr(dst->AsByteSizedArray()), dst_offset, sz);
355 } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
356 copyToArray(srcAddr, MakeObjPtr(dst->AsShortSizedArray()), dst_offset, sz);
357 } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
358 copyToArray(srcAddr, MakeObjPtr(dst->AsIntArray()), dst_offset, sz);
359 } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
360 copyToArray(srcAddr, MakeObjPtr(dst->AsLongArray()), dst_offset, sz);
361 } else {
362 ThrowIllegalAccessException("not a primitive array");
363 }
364 }
365
Unsafe_copyMemoryFromPrimitiveArray(JNIEnv * env,jobject unsafe ATTRIBUTE_UNUSED,jobject srcObj,jlong srcOffset,jlong dstAddr,jlong size)366 static void Unsafe_copyMemoryFromPrimitiveArray(JNIEnv *env,
367 jobject unsafe ATTRIBUTE_UNUSED,
368 jobject srcObj,
369 jlong srcOffset,
370 jlong dstAddr,
371 jlong size) {
372 ScopedObjectAccess soa(env);
373 if (size == 0) {
374 return;
375 }
376 // size is nonnegative and fits into size_t
377 if (size < 0 || size != (jlong)(size_t) size) {
378 ThrowIllegalAccessException("wrong number of bytes");
379 }
380 size_t sz = (size_t)size;
381 size_t src_offset = (size_t)srcOffset;
382 ObjPtr<mirror::Object> src = soa.Decode<mirror::Object>(srcObj);
383 ObjPtr<mirror::Class> component_type = src->GetClass()->GetComponentType();
384 if (component_type->IsPrimitiveByte() || component_type->IsPrimitiveBoolean()) {
385 copyFromArray(dstAddr, MakeObjPtr(src->AsByteSizedArray()), src_offset, sz);
386 } else if (component_type->IsPrimitiveShort() || component_type->IsPrimitiveChar()) {
387 copyFromArray(dstAddr, MakeObjPtr(src->AsShortSizedArray()), src_offset, sz);
388 } else if (component_type->IsPrimitiveInt() || component_type->IsPrimitiveFloat()) {
389 copyFromArray(dstAddr, MakeObjPtr(src->AsIntArray()), src_offset, sz);
390 } else if (component_type->IsPrimitiveLong() || component_type->IsPrimitiveDouble()) {
391 copyFromArray(dstAddr, MakeObjPtr(src->AsLongArray()), src_offset, sz);
392 } else {
393 ThrowIllegalAccessException("not a primitive array");
394 }
395 }
Unsafe_getBoolean(JNIEnv * env,jobject,jobject javaObj,jlong offset)396 static jboolean Unsafe_getBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
397 ScopedFastNativeObjectAccess soa(env);
398 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
399 return obj->GetFieldBoolean(MemberOffset(offset));
400 }
401
Unsafe_putBoolean(JNIEnv * env,jobject,jobject javaObj,jlong offset,jboolean newValue)402 static void Unsafe_putBoolean(JNIEnv* env, jobject, jobject javaObj, jlong offset, jboolean newValue) {
403 ScopedFastNativeObjectAccess soa(env);
404 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
405 // JNI must use non transactional mode (SetField8 is non-transactional).
406 obj->SetFieldBoolean<false>(MemberOffset(offset), newValue);
407 }
408
Unsafe_getByte(JNIEnv * env,jobject,jobject javaObj,jlong offset)409 static jbyte Unsafe_getByte(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
410 ScopedFastNativeObjectAccess soa(env);
411 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
412 return obj->GetFieldByte(MemberOffset(offset));
413 }
414
Unsafe_putByte(JNIEnv * env,jobject,jobject javaObj,jlong offset,jbyte newValue)415 static void Unsafe_putByte(JNIEnv* env, jobject, jobject javaObj, jlong offset, jbyte newValue) {
416 ScopedFastNativeObjectAccess soa(env);
417 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
418 // JNI must use non transactional mode.
419 obj->SetFieldByte<false>(MemberOffset(offset), newValue);
420 }
421
Unsafe_getChar(JNIEnv * env,jobject,jobject javaObj,jlong offset)422 static jchar Unsafe_getChar(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
423 ScopedFastNativeObjectAccess soa(env);
424 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
425 return obj->GetFieldChar(MemberOffset(offset));
426 }
427
Unsafe_putChar(JNIEnv * env,jobject,jobject javaObj,jlong offset,jchar newValue)428 static void Unsafe_putChar(JNIEnv* env, jobject, jobject javaObj, jlong offset, jchar newValue) {
429 ScopedFastNativeObjectAccess soa(env);
430 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
431 // JNI must use non transactional mode.
432 obj->SetFieldChar<false>(MemberOffset(offset), newValue);
433 }
434
Unsafe_getShort(JNIEnv * env,jobject,jobject javaObj,jlong offset)435 static jshort Unsafe_getShort(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
436 ScopedFastNativeObjectAccess soa(env);
437 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
438 return obj->GetFieldShort(MemberOffset(offset));
439 }
440
Unsafe_putShort(JNIEnv * env,jobject,jobject javaObj,jlong offset,jshort newValue)441 static void Unsafe_putShort(JNIEnv* env, jobject, jobject javaObj, jlong offset, jshort newValue) {
442 ScopedFastNativeObjectAccess soa(env);
443 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
444 // JNI must use non transactional mode.
445 obj->SetFieldShort<false>(MemberOffset(offset), newValue);
446 }
447
Unsafe_getFloat(JNIEnv * env,jobject,jobject javaObj,jlong offset)448 static jfloat Unsafe_getFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
449 ScopedFastNativeObjectAccess soa(env);
450 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
451 union {int32_t val; jfloat converted;} conv;
452 conv.val = obj->GetField32(MemberOffset(offset));
453 return conv.converted;
454 }
455
Unsafe_putFloat(JNIEnv * env,jobject,jobject javaObj,jlong offset,jfloat newValue)456 static void Unsafe_putFloat(JNIEnv* env, jobject, jobject javaObj, jlong offset, jfloat newValue) {
457 ScopedFastNativeObjectAccess soa(env);
458 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
459 union {int32_t converted; jfloat val;} conv;
460 conv.val = newValue;
461 // JNI must use non transactional mode.
462 obj->SetField32<false>(MemberOffset(offset), conv.converted);
463 }
464
Unsafe_getDouble(JNIEnv * env,jobject,jobject javaObj,jlong offset)465 static jdouble Unsafe_getDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset) {
466 ScopedFastNativeObjectAccess soa(env);
467 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
468 union {int64_t val; jdouble converted;} conv;
469 conv.val = obj->GetField64(MemberOffset(offset));
470 return conv.converted;
471 }
472
Unsafe_putDouble(JNIEnv * env,jobject,jobject javaObj,jlong offset,jdouble newValue)473 static void Unsafe_putDouble(JNIEnv* env, jobject, jobject javaObj, jlong offset, jdouble newValue) {
474 ScopedFastNativeObjectAccess soa(env);
475 ObjPtr<mirror::Object> obj = soa.Decode<mirror::Object>(javaObj);
476 union {int64_t converted; jdouble val;} conv;
477 conv.val = newValue;
478 // JNI must use non transactional mode.
479 obj->SetField64<false>(MemberOffset(offset), conv.converted);
480 }
481
Unsafe_loadFence(JNIEnv *,jobject)482 static void Unsafe_loadFence(JNIEnv*, jobject) {
483 std::atomic_thread_fence(std::memory_order_acquire);
484 }
485
Unsafe_storeFence(JNIEnv *,jobject)486 static void Unsafe_storeFence(JNIEnv*, jobject) {
487 std::atomic_thread_fence(std::memory_order_release);
488 }
489
Unsafe_fullFence(JNIEnv *,jobject)490 static void Unsafe_fullFence(JNIEnv*, jobject) {
491 std::atomic_thread_fence(std::memory_order_seq_cst);
492 }
493
494 static JNINativeMethod gMethods[] = {
495 FAST_NATIVE_METHOD(Unsafe, compareAndSwapInt, "(Ljava/lang/Object;JII)Z"),
496 FAST_NATIVE_METHOD(Unsafe, compareAndSwapLong, "(Ljava/lang/Object;JJJ)Z"),
497 FAST_NATIVE_METHOD(Unsafe, compareAndSwapObject, "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z"),
498 FAST_NATIVE_METHOD(Unsafe, getIntVolatile, "(Ljava/lang/Object;J)I"),
499 FAST_NATIVE_METHOD(Unsafe, putIntVolatile, "(Ljava/lang/Object;JI)V"),
500 FAST_NATIVE_METHOD(Unsafe, getLongVolatile, "(Ljava/lang/Object;J)J"),
501 FAST_NATIVE_METHOD(Unsafe, putLongVolatile, "(Ljava/lang/Object;JJ)V"),
502 FAST_NATIVE_METHOD(Unsafe, getObjectVolatile, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
503 FAST_NATIVE_METHOD(Unsafe, putObjectVolatile, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
504 FAST_NATIVE_METHOD(Unsafe, getInt, "(Ljava/lang/Object;J)I"),
505 FAST_NATIVE_METHOD(Unsafe, putInt, "(Ljava/lang/Object;JI)V"),
506 FAST_NATIVE_METHOD(Unsafe, putOrderedInt, "(Ljava/lang/Object;JI)V"),
507 FAST_NATIVE_METHOD(Unsafe, getLong, "(Ljava/lang/Object;J)J"),
508 FAST_NATIVE_METHOD(Unsafe, putLong, "(Ljava/lang/Object;JJ)V"),
509 FAST_NATIVE_METHOD(Unsafe, putOrderedLong, "(Ljava/lang/Object;JJ)V"),
510 FAST_NATIVE_METHOD(Unsafe, getObject, "(Ljava/lang/Object;J)Ljava/lang/Object;"),
511 FAST_NATIVE_METHOD(Unsafe, putObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
512 FAST_NATIVE_METHOD(Unsafe, putOrderedObject, "(Ljava/lang/Object;JLjava/lang/Object;)V"),
513 FAST_NATIVE_METHOD(Unsafe, getArrayBaseOffsetForComponentType, "(Ljava/lang/Class;)I"),
514 FAST_NATIVE_METHOD(Unsafe, getArrayIndexScaleForComponentType, "(Ljava/lang/Class;)I"),
515 FAST_NATIVE_METHOD(Unsafe, addressSize, "()I"),
516 FAST_NATIVE_METHOD(Unsafe, pageSize, "()I"),
517 FAST_NATIVE_METHOD(Unsafe, allocateMemory, "(J)J"),
518 FAST_NATIVE_METHOD(Unsafe, freeMemory, "(J)V"),
519 FAST_NATIVE_METHOD(Unsafe, setMemory, "(JJB)V"),
520 FAST_NATIVE_METHOD(Unsafe, copyMemory, "(JJJ)V"),
521 FAST_NATIVE_METHOD(Unsafe, copyMemoryToPrimitiveArray, "(JLjava/lang/Object;JJ)V"),
522 FAST_NATIVE_METHOD(Unsafe, copyMemoryFromPrimitiveArray, "(Ljava/lang/Object;JJJ)V"),
523 FAST_NATIVE_METHOD(Unsafe, getBoolean, "(Ljava/lang/Object;J)Z"),
524
525 FAST_NATIVE_METHOD(Unsafe, getByte, "(Ljava/lang/Object;J)B"),
526 FAST_NATIVE_METHOD(Unsafe, getChar, "(Ljava/lang/Object;J)C"),
527 FAST_NATIVE_METHOD(Unsafe, getShort, "(Ljava/lang/Object;J)S"),
528 FAST_NATIVE_METHOD(Unsafe, getFloat, "(Ljava/lang/Object;J)F"),
529 FAST_NATIVE_METHOD(Unsafe, getDouble, "(Ljava/lang/Object;J)D"),
530 FAST_NATIVE_METHOD(Unsafe, putBoolean, "(Ljava/lang/Object;JZ)V"),
531 FAST_NATIVE_METHOD(Unsafe, putByte, "(Ljava/lang/Object;JB)V"),
532 FAST_NATIVE_METHOD(Unsafe, putChar, "(Ljava/lang/Object;JC)V"),
533 FAST_NATIVE_METHOD(Unsafe, putShort, "(Ljava/lang/Object;JS)V"),
534 FAST_NATIVE_METHOD(Unsafe, putFloat, "(Ljava/lang/Object;JF)V"),
535 FAST_NATIVE_METHOD(Unsafe, putDouble, "(Ljava/lang/Object;JD)V"),
536
537 // Each of the getFoo variants are overloaded with a call that operates
538 // directively on a native pointer.
539 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getByte, "(J)B", getByteJ),
540 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getChar, "(J)C", getCharJ),
541 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getShort, "(J)S", getShortJ),
542 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getInt, "(J)I", getIntJ),
543 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getLong, "(J)J", getLongJ),
544 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getFloat, "(J)F", getFloatJ),
545 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, getDouble, "(J)D", getDoubleJ),
546 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putByte, "(JB)V", putByteJB),
547 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putChar, "(JC)V", putCharJC),
548 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putShort, "(JS)V", putShortJS),
549 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putInt, "(JI)V", putIntJI),
550 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putLong, "(JJ)V", putLongJJ),
551 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putFloat, "(JF)V", putFloatJF),
552 OVERLOADED_FAST_NATIVE_METHOD(Unsafe, putDouble, "(JD)V", putDoubleJD),
553
554 // CAS
555 FAST_NATIVE_METHOD(Unsafe, loadFence, "()V"),
556 FAST_NATIVE_METHOD(Unsafe, storeFence, "()V"),
557 FAST_NATIVE_METHOD(Unsafe, fullFence, "()V"),
558 };
559
register_sun_misc_Unsafe(JNIEnv * env)560 void register_sun_misc_Unsafe(JNIEnv* env) {
561 REGISTER_NATIVE_METHODS("sun/misc/Unsafe");
562 }
563
564 } // namespace art
565