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