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