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