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