1 /* 2 * Copyright (C) 2012 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 <stdint.h> 18 19 #include "art_field-inl.h" 20 #include "art_method-inl.h" 21 #include "callee_save_frame.h" 22 #include "dex_file-inl.h" 23 #include "entrypoints/entrypoint_utils-inl.h" 24 #include "gc_root-inl.h" 25 #include "mirror/class-inl.h" 26 #include "mirror/object_reference.h" 27 28 namespace art { 29 30 inline constexpr bool FindFieldTypeIsRead(FindFieldType type) { 31 return type == InstanceObjectRead || 32 type == InstancePrimitiveRead || 33 type == StaticObjectRead || 34 type == StaticPrimitiveRead; 35 } 36 37 // Helper function to do a null check after trying to resolve the field. Not for statics since obj 38 // does not exist there. There is a suspend check, object is a double pointer to update the value 39 // in the caller in case it moves. 40 template<FindFieldType type, bool kAccessCheck> 41 ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx, 42 ArtMethod* referrer, 43 Thread* self, 44 size_t size, 45 mirror::Object** obj) 46 REQUIRES(!Roles::uninterruptible_) 47 SHARED_REQUIRES(Locks::mutator_lock_) { 48 StackHandleScope<1> hs(self); 49 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj)); 50 ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size); 51 if (LIKELY(field != nullptr) && UNLIKELY(h.Get() == nullptr)) { 52 ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type)); 53 return nullptr; 54 } 55 return field; 56 } 57 58 extern "C" int8_t artGetByteStaticFromCode(uint32_t field_idx, 59 ArtMethod* referrer, 60 Thread* self) 61 SHARED_REQUIRES(Locks::mutator_lock_) { 62 ScopedQuickEntrypointChecks sqec(self); 63 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t)); 64 if (LIKELY(field != nullptr)) { 65 return field->GetByte(field->GetDeclaringClass()); 66 } 67 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t)); 68 if (LIKELY(field != nullptr)) { 69 return field->GetByte(field->GetDeclaringClass()); 70 } 71 return 0; // Will throw exception by checking with Thread::Current. 72 } 73 74 extern "C" uint8_t artGetBooleanStaticFromCode(uint32_t field_idx, 75 ArtMethod* referrer, 76 Thread* self) 77 SHARED_REQUIRES(Locks::mutator_lock_) { 78 ScopedQuickEntrypointChecks sqec(self); 79 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int8_t)); 80 if (LIKELY(field != nullptr)) { 81 return field->GetBoolean(field->GetDeclaringClass()); 82 } 83 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int8_t)); 84 if (LIKELY(field != nullptr)) { 85 return field->GetBoolean(field->GetDeclaringClass()); 86 } 87 return 0; // Will throw exception by checking with Thread::Current. 88 } 89 90 extern "C" int16_t artGetShortStaticFromCode(uint32_t field_idx, 91 ArtMethod* referrer, 92 Thread* self) 93 SHARED_REQUIRES(Locks::mutator_lock_) { 94 ScopedQuickEntrypointChecks sqec(self); 95 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t)); 96 if (LIKELY(field != nullptr)) { 97 return field->GetShort(field->GetDeclaringClass()); 98 } 99 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t)); 100 if (LIKELY(field != nullptr)) { 101 return field->GetShort(field->GetDeclaringClass()); 102 } 103 return 0; // Will throw exception by checking with Thread::Current. 104 } 105 106 extern "C" uint16_t artGetCharStaticFromCode(uint32_t field_idx, 107 ArtMethod* referrer, 108 Thread* self) 109 SHARED_REQUIRES(Locks::mutator_lock_) { 110 ScopedQuickEntrypointChecks sqec(self); 111 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int16_t)); 112 if (LIKELY(field != nullptr)) { 113 return field->GetChar(field->GetDeclaringClass()); 114 } 115 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int16_t)); 116 if (LIKELY(field != nullptr)) { 117 return field->GetChar(field->GetDeclaringClass()); 118 } 119 return 0; // Will throw exception by checking with Thread::Current. 120 } 121 122 extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, 123 ArtMethod* referrer, 124 Thread* self) 125 SHARED_REQUIRES(Locks::mutator_lock_) { 126 ScopedQuickEntrypointChecks sqec(self); 127 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int32_t)); 128 if (LIKELY(field != nullptr)) { 129 return field->Get32(field->GetDeclaringClass()); 130 } 131 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int32_t)); 132 if (LIKELY(field != nullptr)) { 133 return field->Get32(field->GetDeclaringClass()); 134 } 135 return 0; // Will throw exception by checking with Thread::Current. 136 } 137 138 extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, 139 ArtMethod* referrer, 140 Thread* self) 141 SHARED_REQUIRES(Locks::mutator_lock_) { 142 ScopedQuickEntrypointChecks sqec(self); 143 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveRead, sizeof(int64_t)); 144 if (LIKELY(field != nullptr)) { 145 return field->Get64(field->GetDeclaringClass()); 146 } 147 field = FindFieldFromCode<StaticPrimitiveRead, true>(field_idx, referrer, self, sizeof(int64_t)); 148 if (LIKELY(field != nullptr)) { 149 return field->Get64(field->GetDeclaringClass()); 150 } 151 return 0; // Will throw exception by checking with Thread::Current. 152 } 153 154 extern "C" mirror::Object* artGetObjStaticFromCode(uint32_t field_idx, 155 ArtMethod* referrer, 156 Thread* self) 157 SHARED_REQUIRES(Locks::mutator_lock_) { 158 ScopedQuickEntrypointChecks sqec(self); 159 ArtField* field = FindFieldFast(field_idx, 160 referrer, 161 StaticObjectRead, 162 sizeof(mirror::HeapReference<mirror::Object>)); 163 if (LIKELY(field != nullptr)) { 164 return field->GetObj(field->GetDeclaringClass()); 165 } 166 field = FindFieldFromCode<StaticObjectRead, true>(field_idx, 167 referrer, 168 self, 169 sizeof(mirror::HeapReference<mirror::Object>)); 170 if (LIKELY(field != nullptr)) { 171 return field->GetObj(field->GetDeclaringClass()); 172 } 173 return nullptr; // Will throw exception by checking with Thread::Current. 174 } 175 176 extern "C" int8_t artGetByteInstanceFromCode(uint32_t field_idx, 177 mirror::Object* obj, 178 ArtMethod* referrer, 179 Thread* self) 180 SHARED_REQUIRES(Locks::mutator_lock_) { 181 ScopedQuickEntrypointChecks sqec(self); 182 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t)); 183 if (LIKELY(field != nullptr && obj != nullptr)) { 184 return field->GetByte(obj); 185 } 186 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx, 187 referrer, 188 self, 189 sizeof(int8_t), 190 &obj); 191 if (LIKELY(field != nullptr)) { 192 return field->GetByte(obj); 193 } 194 return 0; // Will throw exception by checking with Thread::Current. 195 } 196 197 extern "C" uint8_t artGetBooleanInstanceFromCode(uint32_t field_idx, 198 mirror::Object* obj, 199 ArtMethod* referrer, 200 Thread* self) 201 SHARED_REQUIRES(Locks::mutator_lock_) { 202 ScopedQuickEntrypointChecks sqec(self); 203 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int8_t)); 204 if (LIKELY(field != nullptr && obj != nullptr)) { 205 return field->GetBoolean(obj); 206 } 207 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx, 208 referrer, 209 self, 210 sizeof(int8_t), 211 &obj); 212 if (LIKELY(field != nullptr)) { 213 return field->GetBoolean(obj); 214 } 215 return 0; // Will throw exception by checking with Thread::Current. 216 } 217 extern "C" int16_t artGetShortInstanceFromCode(uint32_t field_idx, 218 mirror::Object* obj, 219 ArtMethod* referrer, 220 Thread* self) 221 SHARED_REQUIRES(Locks::mutator_lock_) { 222 ScopedQuickEntrypointChecks sqec(self); 223 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t)); 224 if (LIKELY(field != nullptr && obj != nullptr)) { 225 return field->GetShort(obj); 226 } 227 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx, 228 referrer, 229 self, 230 sizeof(int16_t), 231 &obj); 232 if (LIKELY(field != nullptr)) { 233 return field->GetShort(obj); 234 } 235 return 0; // Will throw exception by checking with Thread::Current. 236 } 237 238 extern "C" uint16_t artGetCharInstanceFromCode(uint32_t field_idx, 239 mirror::Object* obj, 240 ArtMethod* referrer, 241 Thread* self) 242 SHARED_REQUIRES(Locks::mutator_lock_) { 243 ScopedQuickEntrypointChecks sqec(self); 244 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int16_t)); 245 if (LIKELY(field != nullptr && obj != nullptr)) { 246 return field->GetChar(obj); 247 } 248 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx, 249 referrer, 250 self, 251 sizeof(int16_t), 252 &obj); 253 if (LIKELY(field != nullptr)) { 254 return field->GetChar(obj); 255 } 256 return 0; // Will throw exception by checking with Thread::Current. 257 } 258 259 extern "C" uint32_t artGet32InstanceFromCode(uint32_t field_idx, 260 mirror::Object* obj, 261 ArtMethod* referrer, 262 Thread* self) 263 SHARED_REQUIRES(Locks::mutator_lock_) { 264 ScopedQuickEntrypointChecks sqec(self); 265 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int32_t)); 266 if (LIKELY(field != nullptr && obj != nullptr)) { 267 return field->Get32(obj); 268 } 269 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx, 270 referrer, 271 self, 272 sizeof(int32_t), 273 &obj); 274 if (LIKELY(field != nullptr)) { 275 return field->Get32(obj); 276 } 277 return 0; // Will throw exception by checking with Thread::Current. 278 } 279 280 extern "C" uint64_t artGet64InstanceFromCode(uint32_t field_idx, 281 mirror::Object* obj, 282 ArtMethod* referrer, 283 Thread* self) 284 SHARED_REQUIRES(Locks::mutator_lock_) { 285 ScopedQuickEntrypointChecks sqec(self); 286 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveRead, sizeof(int64_t)); 287 if (LIKELY(field != nullptr && obj != nullptr)) { 288 return field->Get64(obj); 289 } 290 field = FindInstanceField<InstancePrimitiveRead, true>(field_idx, 291 referrer, 292 self, 293 sizeof(int64_t), 294 &obj); 295 if (LIKELY(field != nullptr)) { 296 return field->Get64(obj); 297 } 298 return 0; // Will throw exception by checking with Thread::Current. 299 } 300 301 extern "C" mirror::Object* artGetObjInstanceFromCode(uint32_t field_idx, 302 mirror::Object* obj, 303 ArtMethod* referrer, 304 Thread* self) 305 SHARED_REQUIRES(Locks::mutator_lock_) { 306 ScopedQuickEntrypointChecks sqec(self); 307 ArtField* field = FindFieldFast(field_idx, 308 referrer, 309 InstanceObjectRead, 310 sizeof(mirror::HeapReference<mirror::Object>)); 311 if (LIKELY(field != nullptr && obj != nullptr)) { 312 return field->GetObj(obj); 313 } 314 field = FindInstanceField<InstanceObjectRead, true>(field_idx, 315 referrer, 316 self, 317 sizeof(mirror::HeapReference<mirror::Object>), 318 &obj); 319 if (LIKELY(field != nullptr)) { 320 return field->GetObj(obj); 321 } 322 return nullptr; // Will throw exception by checking with Thread::Current. 323 } 324 325 extern "C" int artSet8StaticFromCode(uint32_t field_idx, 326 uint32_t new_value, 327 ArtMethod* referrer, 328 Thread* self) 329 SHARED_REQUIRES(Locks::mutator_lock_) { 330 ScopedQuickEntrypointChecks sqec(self); 331 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int8_t)); 332 if (LIKELY(field != nullptr)) { 333 Primitive::Type type = field->GetTypeAsPrimitiveType(); 334 // Compiled code can't use transactional mode. 335 if (type == Primitive::kPrimBoolean) { 336 field->SetBoolean<false>(field->GetDeclaringClass(), new_value); 337 } else { 338 DCHECK_EQ(Primitive::kPrimByte, type); 339 field->SetByte<false>(field->GetDeclaringClass(), new_value); 340 } 341 return 0; // success 342 } 343 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int8_t)); 344 if (LIKELY(field != nullptr)) { 345 Primitive::Type type = field->GetTypeAsPrimitiveType(); 346 // Compiled code can't use transactional mode. 347 if (type == Primitive::kPrimBoolean) { 348 field->SetBoolean<false>(field->GetDeclaringClass(), new_value); 349 } else { 350 DCHECK_EQ(Primitive::kPrimByte, type); 351 field->SetByte<false>(field->GetDeclaringClass(), new_value); 352 } 353 return 0; // success 354 } 355 return -1; // failure 356 } 357 358 extern "C" int artSet16StaticFromCode(uint32_t field_idx, 359 uint16_t new_value, 360 ArtMethod* referrer, 361 Thread* self) 362 SHARED_REQUIRES(Locks::mutator_lock_) { 363 ScopedQuickEntrypointChecks sqec(self); 364 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int16_t)); 365 if (LIKELY(field != nullptr)) { 366 Primitive::Type type = field->GetTypeAsPrimitiveType(); 367 // Compiled code can't use transactional mode. 368 if (type == Primitive::kPrimChar) { 369 field->SetChar<false>(field->GetDeclaringClass(), new_value); 370 } else { 371 DCHECK_EQ(Primitive::kPrimShort, type); 372 field->SetShort<false>(field->GetDeclaringClass(), new_value); 373 } 374 return 0; // success 375 } 376 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int16_t)); 377 if (LIKELY(field != nullptr)) { 378 Primitive::Type type = field->GetTypeAsPrimitiveType(); 379 // Compiled code can't use transactional mode. 380 if (type == Primitive::kPrimChar) { 381 field->SetChar<false>(field->GetDeclaringClass(), new_value); 382 } else { 383 DCHECK_EQ(Primitive::kPrimShort, type); 384 field->SetShort<false>(field->GetDeclaringClass(), new_value); 385 } 386 return 0; // success 387 } 388 return -1; // failure 389 } 390 391 extern "C" int artSet32StaticFromCode(uint32_t field_idx, 392 uint32_t new_value, 393 ArtMethod* referrer, 394 Thread* self) 395 SHARED_REQUIRES(Locks::mutator_lock_) { 396 ScopedQuickEntrypointChecks sqec(self); 397 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int32_t)); 398 if (LIKELY(field != nullptr)) { 399 // Compiled code can't use transactional mode. 400 field->Set32<false>(field->GetDeclaringClass(), new_value); 401 return 0; // success 402 } 403 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int32_t)); 404 if (LIKELY(field != nullptr)) { 405 // Compiled code can't use transactional mode. 406 field->Set32<false>(field->GetDeclaringClass(), new_value); 407 return 0; // success 408 } 409 return -1; // failure 410 } 411 412 extern "C" int artSet64StaticFromCode(uint32_t field_idx, 413 ArtMethod* referrer, 414 uint64_t new_value, 415 Thread* self) 416 SHARED_REQUIRES(Locks::mutator_lock_) { 417 ScopedQuickEntrypointChecks sqec(self); 418 ArtField* field = FindFieldFast(field_idx, referrer, StaticPrimitiveWrite, sizeof(int64_t)); 419 if (LIKELY(field != nullptr)) { 420 // Compiled code can't use transactional mode. 421 field->Set64<false>(field->GetDeclaringClass(), new_value); 422 return 0; // success 423 } 424 field = FindFieldFromCode<StaticPrimitiveWrite, true>(field_idx, referrer, self, sizeof(int64_t)); 425 if (LIKELY(field != nullptr)) { 426 // Compiled code can't use transactional mode. 427 field->Set64<false>(field->GetDeclaringClass(), new_value); 428 return 0; // success 429 } 430 return -1; // failure 431 } 432 433 extern "C" int artSetObjStaticFromCode(uint32_t field_idx, 434 mirror::Object* new_value, 435 ArtMethod* referrer, 436 Thread* self) 437 SHARED_REQUIRES(Locks::mutator_lock_) { 438 ScopedQuickEntrypointChecks sqec(self); 439 ArtField* field = FindFieldFast(field_idx, 440 referrer, 441 StaticObjectWrite, 442 sizeof(mirror::HeapReference<mirror::Object>)); 443 if (LIKELY(field != nullptr)) { 444 if (LIKELY(!field->IsPrimitiveType())) { 445 // Compiled code can't use transactional mode. 446 field->SetObj<false>(field->GetDeclaringClass(), new_value); 447 return 0; // success 448 } 449 } 450 { 451 StackHandleScope<1> hs(self); 452 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&new_value)); 453 field = FindFieldFromCode<StaticObjectWrite, true>( 454 field_idx, 455 referrer, 456 self, 457 sizeof(mirror::HeapReference<mirror::Object>)); 458 } 459 if (LIKELY(field != nullptr)) { 460 // Compiled code can't use transactional mode. 461 field->SetObj<false>(field->GetDeclaringClass(), new_value); 462 return 0; // success 463 } 464 return -1; // failure 465 } 466 467 extern "C" int artSet8InstanceFromCode(uint32_t field_idx, 468 mirror::Object* obj, 469 uint8_t new_value, 470 ArtMethod* referrer, 471 Thread* self) 472 SHARED_REQUIRES(Locks::mutator_lock_) { 473 ScopedQuickEntrypointChecks sqec(self); 474 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int8_t)); 475 if (LIKELY(field != nullptr && obj != nullptr)) { 476 Primitive::Type type = field->GetTypeAsPrimitiveType(); 477 // Compiled code can't use transactional mode. 478 if (type == Primitive::kPrimBoolean) { 479 field->SetBoolean<false>(obj, new_value); 480 } else { 481 DCHECK_EQ(Primitive::kPrimByte, type); 482 field->SetByte<false>(obj, new_value); 483 } 484 return 0; // success 485 } 486 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx, 487 referrer, 488 self, 489 sizeof(int8_t), 490 &obj); 491 if (LIKELY(field != nullptr)) { 492 Primitive::Type type = field->GetTypeAsPrimitiveType(); 493 // Compiled code can't use transactional mode. 494 if (type == Primitive::kPrimBoolean) { 495 field->SetBoolean<false>(obj, new_value); 496 } else { 497 field->SetByte<false>(obj, new_value); 498 } 499 return 0; // success 500 } 501 return -1; // failure 502 } 503 504 extern "C" int artSet16InstanceFromCode(uint32_t field_idx, 505 mirror::Object* obj, 506 uint16_t new_value, 507 ArtMethod* referrer, 508 Thread* self) 509 SHARED_REQUIRES(Locks::mutator_lock_) { 510 ScopedQuickEntrypointChecks sqec(self); 511 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int16_t)); 512 if (LIKELY(field != nullptr && obj != nullptr)) { 513 Primitive::Type type = field->GetTypeAsPrimitiveType(); 514 // Compiled code can't use transactional mode. 515 if (type == Primitive::kPrimChar) { 516 field->SetChar<false>(obj, new_value); 517 } else { 518 DCHECK_EQ(Primitive::kPrimShort, type); 519 field->SetShort<false>(obj, new_value); 520 } 521 return 0; // success 522 } 523 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx, 524 referrer, 525 self, 526 sizeof(int16_t), 527 &obj); 528 if (LIKELY(field != nullptr)) { 529 Primitive::Type type = field->GetTypeAsPrimitiveType(); 530 // Compiled code can't use transactional mode. 531 if (type == Primitive::kPrimChar) { 532 field->SetChar<false>(obj, new_value); 533 } else { 534 DCHECK_EQ(Primitive::kPrimShort, type); 535 field->SetShort<false>(obj, new_value); 536 } 537 return 0; // success 538 } 539 return -1; // failure 540 } 541 542 extern "C" int artSet32InstanceFromCode(uint32_t field_idx, 543 mirror::Object* obj, 544 uint32_t new_value, 545 ArtMethod* referrer, 546 Thread* self) 547 SHARED_REQUIRES(Locks::mutator_lock_) { 548 ScopedQuickEntrypointChecks sqec(self); 549 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int32_t)); 550 if (LIKELY(field != nullptr && obj != nullptr)) { 551 // Compiled code can't use transactional mode. 552 field->Set32<false>(obj, new_value); 553 return 0; // success 554 } 555 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx, 556 referrer, 557 self, 558 sizeof(int32_t), 559 &obj); 560 if (LIKELY(field != nullptr)) { 561 // Compiled code can't use transactional mode. 562 field->Set32<false>(obj, new_value); 563 return 0; // success 564 } 565 return -1; // failure 566 } 567 568 extern "C" int artSet64InstanceFromCode(uint32_t field_idx, 569 mirror::Object* obj, 570 uint64_t new_value, 571 ArtMethod* referrer, 572 Thread* self) 573 SHARED_REQUIRES(Locks::mutator_lock_) { 574 ScopedQuickEntrypointChecks sqec(self); 575 ArtField* field = FindFieldFast(field_idx, referrer, InstancePrimitiveWrite, sizeof(int64_t)); 576 if (LIKELY(field != nullptr && obj != nullptr)) { 577 // Compiled code can't use transactional mode. 578 field->Set64<false>(obj, new_value); 579 return 0; // success 580 } 581 field = FindInstanceField<InstancePrimitiveWrite, true>(field_idx, 582 referrer, 583 self, 584 sizeof(int64_t), 585 &obj); 586 if (LIKELY(field != nullptr)) { 587 // Compiled code can't use transactional mode. 588 field->Set64<false>(obj, new_value); 589 return 0; 590 } 591 return -1; // failure 592 } 593 594 extern "C" int artSetObjInstanceFromCode(uint32_t field_idx, 595 mirror::Object* obj, 596 mirror::Object* new_value, 597 ArtMethod* referrer, 598 Thread* self) 599 SHARED_REQUIRES(Locks::mutator_lock_) { 600 ScopedQuickEntrypointChecks sqec(self); 601 ArtField* field = FindFieldFast(field_idx, 602 referrer, 603 InstanceObjectWrite, 604 sizeof(mirror::HeapReference<mirror::Object>)); 605 if (LIKELY(field != nullptr && obj != nullptr)) { 606 // Compiled code can't use transactional mode. 607 field->SetObj<false>(obj, new_value); 608 return 0; // success 609 } 610 { 611 StackHandleScope<2> hs(self); 612 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper(&obj)); 613 HandleWrapper<mirror::Object> h_new_value(hs.NewHandleWrapper(&new_value)); 614 field = FindFieldFromCode<InstanceObjectWrite, true>( 615 field_idx, 616 referrer, 617 self, 618 sizeof(mirror::HeapReference<mirror::Object>)); 619 } 620 if (LIKELY(field != nullptr)) { 621 if (UNLIKELY(obj == nullptr)) { 622 ThrowNullPointerExceptionForFieldAccess(field, false); 623 } else { 624 // Compiled code can't use transactional mode. 625 field->SetObj<false>(obj, new_value); 626 return 0; // success 627 } 628 } 629 return -1; // failure 630 } 631 632 extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) { 633 DCHECK(kEmitCompilerReadBarrier); 634 return ReadBarrier::Mark(obj); 635 } 636 637 extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED, 638 mirror::Object* obj, 639 uint32_t offset) { 640 DCHECK(kEmitCompilerReadBarrier); 641 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset; 642 mirror::HeapReference<mirror::Object>* ref_addr = 643 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr); 644 constexpr ReadBarrierOption kReadBarrierOption = 645 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier; 646 mirror::Object* result = 647 ReadBarrier::Barrier<mirror::Object, kReadBarrierOption>(obj, 648 MemberOffset(offset), 649 ref_addr); 650 return result; 651 } 652 653 extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) { 654 DCHECK(kEmitCompilerReadBarrier); 655 return root->Read(); 656 } 657 658 } // namespace art 659