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 "base/callee_save_type.h" 22 #include "callee_save_frame.h" 23 #include "dex/dex_file-inl.h" 24 #include "entrypoints/entrypoint_utils-inl.h" 25 #include "gc_root-inl.h" 26 #include "mirror/class-inl.h" 27 #include "mirror/object_reference.h" 28 29 namespace art { 30 31 inline constexpr bool FindFieldTypeIsRead(FindFieldType type) { 32 return type == InstanceObjectRead || 33 type == InstancePrimitiveRead || 34 type == StaticObjectRead || 35 type == StaticPrimitiveRead; 36 } 37 38 // Helper function to do a null check after trying to resolve the field. Not for statics since obj 39 // does not exist there. There is a suspend check, object is a double pointer to update the value 40 // in the caller in case it moves. 41 template<FindFieldType type, bool kAccessCheck> 42 ALWAYS_INLINE static inline ArtField* FindInstanceField(uint32_t field_idx, 43 ArtMethod* referrer, 44 Thread* self, 45 size_t size, 46 mirror::Object** obj) 47 REQUIRES(!Roles::uninterruptible_) 48 REQUIRES_SHARED(Locks::mutator_lock_) { 49 StackHandleScope<1> hs(self); 50 HandleWrapper<mirror::Object> h(hs.NewHandleWrapper(obj)); 51 ArtField* field = FindFieldFromCode<type, kAccessCheck>(field_idx, referrer, self, size); 52 if (LIKELY(field != nullptr) && UNLIKELY(h == nullptr)) { 53 ThrowNullPointerExceptionForFieldAccess(field, /*is_read*/FindFieldTypeIsRead(type)); 54 return nullptr; 55 } 56 return field; 57 } 58 59 static ArtMethod* GetReferrer(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) { 60 if (kIsDebugBuild) { 61 // stub_test doesn't call this code with a proper frame, so get the outer, and if 62 // it does not have compiled code return it. 63 ArtMethod* outer = GetCalleeSaveOuterMethod(self, CalleeSaveType::kSaveRefsOnly); 64 if (outer->GetEntryPointFromQuickCompiledCode() == nullptr) { 65 return outer; 66 } 67 } 68 return GetCalleeSaveMethodCallerAndOuterMethod(self, CalleeSaveType::kSaveRefsOnly).caller; 69 } 70 71 // Macro used to define this set of functions: 72 // 73 // art{Get,Set}<Kind>{Static,Instance}FromCode 74 // art{Get,Set}<Kind>{Static,Instance}FromCompiledCode 75 // 76 #define ART_GET_FIELD_FROM_CODE(Kind, PrimitiveType, RetType, SetType, \ 77 PrimitiveOrObject, IsObject, Ptr) \ 78 extern "C" RetType artGet ## Kind ## StaticFromCode(uint32_t field_idx, \ 79 ArtMethod* referrer, \ 80 Thread* self) \ 81 REQUIRES_SHARED(Locks::mutator_lock_) { \ 82 ScopedQuickEntrypointChecks sqec(self); \ 83 ArtField* field = FindFieldFast( \ 84 field_idx, referrer, Static ## PrimitiveOrObject ## Read, \ 85 sizeof(PrimitiveType)); \ 86 if (LIKELY(field != nullptr)) { \ 87 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \ 88 } \ 89 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Read, true>( \ 90 field_idx, referrer, self, sizeof(PrimitiveType)); \ 91 if (LIKELY(field != nullptr)) { \ 92 return field->Get ## Kind (field->GetDeclaringClass())Ptr; /* NOLINT */ \ 93 } \ 94 /* Will throw exception by checking with Thread::Current. */ \ 95 return 0; \ 96 } \ 97 \ 98 extern "C" RetType artGet ## Kind ## InstanceFromCode(uint32_t field_idx, \ 99 mirror::Object* obj, \ 100 ArtMethod* referrer, \ 101 Thread* self) \ 102 REQUIRES_SHARED(Locks::mutator_lock_) { \ 103 ScopedQuickEntrypointChecks sqec(self); \ 104 ArtField* field = FindFieldFast( \ 105 field_idx, referrer, Instance ## PrimitiveOrObject ## Read, \ 106 sizeof(PrimitiveType)); \ 107 if (LIKELY(field != nullptr) && obj != nullptr) { \ 108 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \ 109 } \ 110 field = FindInstanceField<Instance ## PrimitiveOrObject ## Read, true>( \ 111 field_idx, referrer, self, sizeof(PrimitiveType), &obj); \ 112 if (LIKELY(field != nullptr)) { \ 113 return field->Get ## Kind (obj)Ptr; /* NOLINT */ \ 114 } \ 115 /* Will throw exception by checking with Thread::Current. */ \ 116 return 0; \ 117 } \ 118 \ 119 extern "C" int artSet ## Kind ## StaticFromCode(uint32_t field_idx, \ 120 SetType new_value, \ 121 ArtMethod* referrer, \ 122 Thread* self) \ 123 REQUIRES_SHARED(Locks::mutator_lock_) { \ 124 ScopedQuickEntrypointChecks sqec(self); \ 125 ArtField* field = FindFieldFast( \ 126 field_idx, referrer, Static ## PrimitiveOrObject ## Write, \ 127 sizeof(PrimitiveType)); \ 128 if (LIKELY(field != nullptr)) { \ 129 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \ 130 return 0; \ 131 } \ 132 if (IsObject) { \ 133 StackHandleScope<1> hs(self); \ 134 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \ 135 reinterpret_cast<mirror::Object**>(&new_value))); \ 136 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \ 137 field_idx, referrer, self, sizeof(PrimitiveType)); \ 138 } else { \ 139 field = FindFieldFromCode<Static ## PrimitiveOrObject ## Write, true>( \ 140 field_idx, referrer, self, sizeof(PrimitiveType)); \ 141 } \ 142 if (LIKELY(field != nullptr)) { \ 143 field->Set ## Kind <false>(field->GetDeclaringClass(), new_value); \ 144 return 0; \ 145 } \ 146 return -1; \ 147 } \ 148 \ 149 extern "C" int artSet ## Kind ## InstanceFromCode(uint32_t field_idx, \ 150 mirror::Object* obj, \ 151 SetType new_value, \ 152 ArtMethod* referrer, \ 153 Thread* self) \ 154 REQUIRES_SHARED(Locks::mutator_lock_) { \ 155 ScopedQuickEntrypointChecks sqec(self); \ 156 ArtField* field = FindFieldFast( \ 157 field_idx, referrer, Instance ## PrimitiveOrObject ## Write, \ 158 sizeof(PrimitiveType)); \ 159 if (LIKELY(field != nullptr && obj != nullptr)) { \ 160 field->Set ## Kind <false>(obj, new_value); \ 161 return 0; \ 162 } \ 163 if (IsObject) { \ 164 StackHandleScope<1> hs(self); \ 165 HandleWrapper<mirror::Object> h_obj(hs.NewHandleWrapper( \ 166 reinterpret_cast<mirror::Object**>(&new_value))); \ 167 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \ 168 field_idx, \ 169 referrer, \ 170 self, \ 171 sizeof(PrimitiveType), \ 172 &obj); \ 173 } else { \ 174 field = FindInstanceField<Instance ## PrimitiveOrObject ## Write, true>( \ 175 field_idx, \ 176 referrer, \ 177 self, \ 178 sizeof(PrimitiveType), \ 179 &obj); \ 180 } \ 181 if (LIKELY(field != nullptr)) { \ 182 field->Set ## Kind<false>(obj, new_value); \ 183 return 0; \ 184 } \ 185 return -1; \ 186 } \ 187 \ 188 extern "C" RetType artGet ## Kind ## StaticFromCompiledCode( \ 189 uint32_t field_idx, \ 190 Thread* self) \ 191 REQUIRES_SHARED(Locks::mutator_lock_) { \ 192 return artGet ## Kind ## StaticFromCode( \ 193 field_idx, GetReferrer(self), self); \ 194 } \ 195 \ 196 extern "C" RetType artGet ## Kind ## InstanceFromCompiledCode( \ 197 uint32_t field_idx, \ 198 mirror::Object* obj, \ 199 Thread* self) \ 200 REQUIRES_SHARED(Locks::mutator_lock_) { \ 201 return artGet ## Kind ## InstanceFromCode( \ 202 field_idx, obj, GetReferrer(self), self); \ 203 } \ 204 \ 205 extern "C" int artSet ## Kind ## StaticFromCompiledCode( \ 206 uint32_t field_idx, \ 207 SetType new_value, \ 208 Thread* self) \ 209 REQUIRES_SHARED(Locks::mutator_lock_) { \ 210 return artSet ## Kind ## StaticFromCode( \ 211 field_idx, new_value, GetReferrer(self), self); \ 212 } \ 213 \ 214 extern "C" int artSet ## Kind ## InstanceFromCompiledCode( \ 215 uint32_t field_idx, \ 216 mirror::Object* obj, \ 217 SetType new_value, \ 218 Thread* self) \ 219 REQUIRES_SHARED(Locks::mutator_lock_) { \ 220 return artSet ## Kind ## InstanceFromCode( \ 221 field_idx, obj, new_value, GetReferrer(self), self); \ 222 } 223 224 // Define these functions: 225 // 226 // artGetByteStaticFromCode 227 // artGetByteInstanceFromCode 228 // artSetByteStaticFromCode 229 // artSetByteInstanceFromCode 230 // artGetByteStaticFromCompiledCode 231 // artGetByteInstanceFromCompiledCode 232 // artSetByteStaticFromCompiledCode 233 // artSetByteInstanceFromCompiledCode 234 // 235 ART_GET_FIELD_FROM_CODE(Byte, int8_t, ssize_t, uint32_t, Primitive, false, ) 236 237 // Define these functions: 238 // 239 // artGetBooleanStaticFromCode 240 // artGetBooleanInstanceFromCode 241 // artSetBooleanStaticFromCode 242 // artSetBooleanInstanceFromCode 243 // artGetBooleanStaticFromCompiledCode 244 // artGetBooleanInstanceFromCompiledCode 245 // artSetBooleanStaticFromCompiledCode 246 // artSetBooleanInstanceFromCompiledCode 247 // 248 ART_GET_FIELD_FROM_CODE(Boolean, int8_t, size_t, uint32_t, Primitive, false, ) 249 250 // Define these functions: 251 // 252 // artGetShortStaticFromCode 253 // artGetShortInstanceFromCode 254 // artSetShortStaticFromCode 255 // artSetShortInstanceFromCode 256 // artGetShortStaticFromCompiledCode 257 // artGetShortInstanceFromCompiledCode 258 // artSetShortStaticFromCompiledCode 259 // artSetShortInstanceFromCompiledCode 260 // 261 ART_GET_FIELD_FROM_CODE(Short, int16_t, ssize_t, uint16_t, Primitive, false, ) 262 263 // Define these functions: 264 // 265 // artGetCharStaticFromCode 266 // artGetCharInstanceFromCode 267 // artSetCharStaticFromCode 268 // artSetCharInstanceFromCode 269 // artGetCharStaticFromCompiledCode 270 // artGetCharInstanceFromCompiledCode 271 // artSetCharStaticFromCompiledCode 272 // artSetCharInstanceFromCompiledCode 273 // 274 ART_GET_FIELD_FROM_CODE(Char, int16_t, size_t, uint16_t, Primitive, false, ) 275 276 // Define these functions: 277 // 278 // artGet32StaticFromCode 279 // artGet32InstanceFromCode 280 // artSet32StaticFromCode 281 // artSet32InstanceFromCode 282 // artGet32StaticFromCompiledCode 283 // artGet32InstanceFromCompiledCode 284 // artSet32StaticFromCompiledCode 285 // artSet32InstanceFromCompiledCode 286 // 287 ART_GET_FIELD_FROM_CODE(32, int32_t, size_t, uint32_t, Primitive, false, ) 288 289 // Define these functions: 290 // 291 // artGet64StaticFromCode 292 // artGet64InstanceFromCode 293 // artSet64StaticFromCode 294 // artSet64InstanceFromCode 295 // artGet64StaticFromCompiledCode 296 // artGet64InstanceFromCompiledCode 297 // artSet64StaticFromCompiledCode 298 // artSet64InstanceFromCompiledCode 299 // 300 ART_GET_FIELD_FROM_CODE(64, int64_t, uint64_t, uint64_t, Primitive, false, ) 301 302 // Define these functions: 303 // 304 // artGetObjStaticFromCode 305 // artGetObjInstanceFromCode 306 // artSetObjStaticFromCode 307 // artSetObjInstanceFromCode 308 // artGetObjStaticFromCompiledCode 309 // artGetObjInstanceFromCompiledCode 310 // artSetObjStaticFromCompiledCode 311 // artSetObjInstanceFromCompiledCode 312 // 313 ART_GET_FIELD_FROM_CODE(Obj, mirror::HeapReference<mirror::Object>, mirror::Object*, 314 mirror::Object*, Object, true, .Ptr()) 315 316 #undef ART_GET_FIELD_FROM_CODE 317 318 319 // To cut on the number of entrypoints, we have shared entries for 320 // byte/boolean and char/short for setting an instance or static field. We just 321 // forward those to the unsigned variant. 322 extern "C" int artSet8StaticFromCompiledCode(uint32_t field_idx, 323 uint32_t new_value, 324 Thread* self) 325 REQUIRES_SHARED(Locks::mutator_lock_) { 326 return artSetBooleanStaticFromCode(field_idx, new_value, GetReferrer(self), self); 327 } 328 329 extern "C" int artSet16StaticFromCompiledCode(uint32_t field_idx, 330 uint16_t new_value, 331 Thread* self) 332 REQUIRES_SHARED(Locks::mutator_lock_) { 333 return artSetCharStaticFromCode(field_idx, new_value, GetReferrer(self), self); 334 } 335 336 extern "C" int artSet8InstanceFromCompiledCode(uint32_t field_idx, 337 mirror::Object* obj, 338 uint8_t new_value, 339 Thread* self) 340 REQUIRES_SHARED(Locks::mutator_lock_) { 341 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self); 342 } 343 344 extern "C" int artSet16InstanceFromCompiledCode(uint32_t field_idx, 345 mirror::Object* obj, 346 uint16_t new_value, 347 Thread* self) 348 REQUIRES_SHARED(Locks::mutator_lock_) { 349 return artSetCharInstanceFromCode(field_idx, obj, new_value, GetReferrer(self), self); 350 } 351 352 extern "C" int artSet8StaticFromCode(uint32_t field_idx, 353 uint32_t new_value, 354 ArtMethod* referrer, 355 Thread* self) 356 REQUIRES_SHARED(Locks::mutator_lock_) { 357 return artSetBooleanStaticFromCode(field_idx, new_value, referrer, self); 358 } 359 360 extern "C" int artSet16StaticFromCode(uint32_t field_idx, 361 uint16_t new_value, 362 ArtMethod* referrer, 363 Thread* self) 364 REQUIRES_SHARED(Locks::mutator_lock_) { 365 return artSetCharStaticFromCode(field_idx, new_value, referrer, self); 366 } 367 368 extern "C" int artSet8InstanceFromCode(uint32_t field_idx, 369 mirror::Object* obj, 370 uint8_t new_value, 371 ArtMethod* referrer, 372 Thread* self) 373 REQUIRES_SHARED(Locks::mutator_lock_) { 374 return artSetBooleanInstanceFromCode(field_idx, obj, new_value, referrer, self); 375 } 376 377 extern "C" int artSet16InstanceFromCode(uint32_t field_idx, 378 mirror::Object* obj, 379 uint16_t new_value, 380 ArtMethod* referrer, 381 Thread* self) 382 REQUIRES_SHARED(Locks::mutator_lock_) { 383 return artSetCharInstanceFromCode(field_idx, obj, new_value, referrer, self); 384 } 385 386 extern "C" mirror::Object* artReadBarrierMark(mirror::Object* obj) { 387 DCHECK(kEmitCompilerReadBarrier); 388 return ReadBarrier::Mark(obj); 389 } 390 391 extern "C" mirror::Object* artReadBarrierSlow(mirror::Object* ref ATTRIBUTE_UNUSED, 392 mirror::Object* obj, 393 uint32_t offset) { 394 // Used only in connection with non-volatile loads. 395 DCHECK(kEmitCompilerReadBarrier); 396 uint8_t* raw_addr = reinterpret_cast<uint8_t*>(obj) + offset; 397 mirror::HeapReference<mirror::Object>* ref_addr = 398 reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr); 399 constexpr ReadBarrierOption kReadBarrierOption = 400 kUseReadBarrier ? kWithReadBarrier : kWithoutReadBarrier; 401 mirror::Object* result = 402 ReadBarrier::Barrier<mirror::Object, /* kIsVolatile */ false, kReadBarrierOption>( 403 obj, 404 MemberOffset(offset), 405 ref_addr); 406 return result; 407 } 408 409 extern "C" mirror::Object* artReadBarrierForRootSlow(GcRoot<mirror::Object>* root) { 410 DCHECK(kEmitCompilerReadBarrier); 411 return root->Read(); 412 } 413 414 } // namespace art 415