1 /* 2 * Copyright (C) 2011 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 #ifndef ART_RUNTIME_ART_FIELD_INL_H_ 18 #define ART_RUNTIME_ART_FIELD_INL_H_ 19 20 #include "art_field.h" 21 22 #include <android-base/logging.h> 23 24 #include "class_linker-inl.h" 25 #include "dex/dex_file-inl.h" 26 #include "dex/primitive.h" 27 #include "gc/accounting/card_table-inl.h" 28 #include "gc_root-inl.h" 29 #include "jvalue.h" 30 #include "mirror/dex_cache-inl.h" 31 #include "mirror/object-inl.h" 32 #include "obj_ptr-inl.h" 33 #include "thread-current-inl.h" 34 35 namespace art { 36 37 inline bool ArtField::IsProxyField() { 38 // No read barrier needed, we're reading the constant declaring class only to read 39 // the constant proxy flag. See ReadBarrierOption. 40 return GetDeclaringClass<kWithoutReadBarrier>()->IsProxyClass<kVerifyNone>(); 41 } 42 43 template<ReadBarrierOption kReadBarrierOption> 44 inline ObjPtr<mirror::Class> ArtField::GetDeclaringClass() { 45 GcRootSource gc_root_source(this); 46 ObjPtr<mirror::Class> result = declaring_class_.Read<kReadBarrierOption>(&gc_root_source); 47 DCHECK(result != nullptr); 48 DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << result->GetStatus(); 49 return result; 50 } 51 52 inline void ArtField::SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) { 53 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); 54 } 55 56 inline MemberOffset ArtField::GetOffsetDuringLinking() { 57 DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); 58 return MemberOffset(offset_); 59 } 60 61 inline uint32_t ArtField::Get32(ObjPtr<mirror::Object> object) { 62 DCHECK(object != nullptr) << PrettyField(); 63 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 64 if (UNLIKELY(IsVolatile())) { 65 return object->GetField32Volatile(GetOffset()); 66 } 67 return object->GetField32(GetOffset()); 68 } 69 70 template<bool kTransactionActive> 71 inline void ArtField::Set32(ObjPtr<mirror::Object> object, uint32_t new_value) { 72 DCHECK(object != nullptr) << PrettyField(); 73 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 74 if (UNLIKELY(IsVolatile())) { 75 object->SetField32Volatile<kTransactionActive>(GetOffset(), new_value); 76 } else { 77 object->SetField32<kTransactionActive>(GetOffset(), new_value); 78 } 79 } 80 81 inline uint64_t ArtField::Get64(ObjPtr<mirror::Object> object) { 82 DCHECK(object != nullptr) << PrettyField(); 83 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 84 if (UNLIKELY(IsVolatile())) { 85 return object->GetField64Volatile(GetOffset()); 86 } 87 return object->GetField64(GetOffset()); 88 } 89 90 template<bool kTransactionActive> 91 inline void ArtField::Set64(ObjPtr<mirror::Object> object, uint64_t new_value) { 92 DCHECK(object != nullptr) << PrettyField(); 93 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 94 if (UNLIKELY(IsVolatile())) { 95 object->SetField64Volatile<kTransactionActive>(GetOffset(), new_value); 96 } else { 97 object->SetField64<kTransactionActive>(GetOffset(), new_value); 98 } 99 } 100 101 template<class MirrorType> 102 inline ObjPtr<MirrorType> ArtField::GetObj(ObjPtr<mirror::Object> object) { 103 DCHECK(object != nullptr) << PrettyField(); 104 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 105 if (UNLIKELY(IsVolatile())) { 106 return object->GetFieldObjectVolatile<MirrorType>(GetOffset()); 107 } 108 return object->GetFieldObject<MirrorType>(GetOffset()); 109 } 110 111 template<bool kTransactionActive> 112 inline void ArtField::SetObj(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> new_value) { 113 DCHECK(object != nullptr) << PrettyField(); 114 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 115 if (UNLIKELY(IsVolatile())) { 116 object->SetFieldObjectVolatile<kTransactionActive>(GetOffset(), new_value); 117 } else { 118 object->SetFieldObject<kTransactionActive>(GetOffset(), new_value); 119 } 120 } 121 122 #define FIELD_GET(object, type) \ 123 DCHECK_EQ(Primitive::kPrim ## type, GetTypeAsPrimitiveType()) << PrettyField(); \ 124 DCHECK((object) != nullptr) << PrettyField(); \ 125 DCHECK(!IsStatic() || ((object) == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); \ 126 if (UNLIKELY(IsVolatile())) { \ 127 return (object)->GetField ## type ## Volatile(GetOffset()); \ 128 } \ 129 return (object)->GetField ## type(GetOffset()); 130 131 #define FIELD_SET(object, type, value) \ 132 DCHECK((object) != nullptr) << PrettyField(); \ 133 DCHECK(!IsStatic() || ((object) == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); \ 134 if (UNLIKELY(IsVolatile())) { \ 135 (object)->SetField ## type ## Volatile<kTransactionActive>(GetOffset(), value); \ 136 } else { \ 137 (object)->SetField ## type<kTransactionActive>(GetOffset(), value); \ 138 } 139 140 inline uint8_t ArtField::GetBoolean(ObjPtr<mirror::Object> object) { 141 FIELD_GET(object, Boolean); 142 } 143 144 template<bool kTransactionActive> 145 inline void ArtField::SetBoolean(ObjPtr<mirror::Object> object, uint8_t z) { 146 if (kIsDebugBuild) { 147 // For simplicity, this method is being called by the compiler entrypoint for 148 // both boolean and byte fields. 149 Primitive::Type type = GetTypeAsPrimitiveType(); 150 DCHECK(type == Primitive::kPrimBoolean || type == Primitive::kPrimByte) << PrettyField(); 151 } 152 FIELD_SET(object, Boolean, z); 153 } 154 155 inline int8_t ArtField::GetByte(ObjPtr<mirror::Object> object) { 156 FIELD_GET(object, Byte); 157 } 158 159 template<bool kTransactionActive> 160 inline void ArtField::SetByte(ObjPtr<mirror::Object> object, int8_t b) { 161 DCHECK_EQ(Primitive::kPrimByte, GetTypeAsPrimitiveType()) << PrettyField(); 162 FIELD_SET(object, Byte, b); 163 } 164 165 inline uint16_t ArtField::GetChar(ObjPtr<mirror::Object> object) { 166 FIELD_GET(object, Char); 167 } 168 169 template<bool kTransactionActive> 170 inline void ArtField::SetChar(ObjPtr<mirror::Object> object, uint16_t c) { 171 if (kIsDebugBuild) { 172 // For simplicity, this method is being called by the compiler entrypoint for 173 // both char and short fields. 174 Primitive::Type type = GetTypeAsPrimitiveType(); 175 DCHECK(type == Primitive::kPrimChar || type == Primitive::kPrimShort) << PrettyField(); 176 } 177 FIELD_SET(object, Char, c); 178 } 179 180 inline int16_t ArtField::GetShort(ObjPtr<mirror::Object> object) { 181 FIELD_GET(object, Short); 182 } 183 184 template<bool kTransactionActive> 185 inline void ArtField::SetShort(ObjPtr<mirror::Object> object, int16_t s) { 186 DCHECK_EQ(Primitive::kPrimShort, GetTypeAsPrimitiveType()) << PrettyField(); 187 FIELD_SET(object, Short, s); 188 } 189 190 #undef FIELD_GET 191 #undef FIELD_SET 192 193 inline int32_t ArtField::GetInt(ObjPtr<mirror::Object> object) { 194 if (kIsDebugBuild) { 195 // For simplicity, this method is being called by the compiler entrypoint for 196 // both int and float fields. 197 Primitive::Type type = GetTypeAsPrimitiveType(); 198 CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(); 199 } 200 return Get32(object); 201 } 202 203 template<bool kTransactionActive> 204 inline void ArtField::SetInt(ObjPtr<mirror::Object> object, int32_t i) { 205 if (kIsDebugBuild) { 206 // For simplicity, this method is being called by the compiler entrypoint for 207 // both int and float fields. 208 Primitive::Type type = GetTypeAsPrimitiveType(); 209 CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(); 210 } 211 Set32<kTransactionActive>(object, i); 212 } 213 214 inline int64_t ArtField::GetLong(ObjPtr<mirror::Object> object) { 215 if (kIsDebugBuild) { 216 // For simplicity, this method is being called by the compiler entrypoint for 217 // both long and double fields. 218 Primitive::Type type = GetTypeAsPrimitiveType(); 219 CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(); 220 } 221 return Get64(object); 222 } 223 224 template<bool kTransactionActive> 225 inline void ArtField::SetLong(ObjPtr<mirror::Object> object, int64_t j) { 226 if (kIsDebugBuild) { 227 // For simplicity, this method is being called by the compiler entrypoint for 228 // both long and double fields. 229 Primitive::Type type = GetTypeAsPrimitiveType(); 230 CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(); 231 } 232 Set64<kTransactionActive>(object, j); 233 } 234 235 inline float ArtField::GetFloat(ObjPtr<mirror::Object> object) { 236 DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(); 237 JValue bits; 238 bits.SetI(Get32(object)); 239 return bits.GetF(); 240 } 241 242 template<bool kTransactionActive> 243 inline void ArtField::SetFloat(ObjPtr<mirror::Object> object, float f) { 244 DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(); 245 JValue bits; 246 bits.SetF(f); 247 Set32<kTransactionActive>(object, bits.GetI()); 248 } 249 250 inline double ArtField::GetDouble(ObjPtr<mirror::Object> object) { 251 DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(); 252 JValue bits; 253 bits.SetJ(Get64(object)); 254 return bits.GetD(); 255 } 256 257 template<bool kTransactionActive> 258 inline void ArtField::SetDouble(ObjPtr<mirror::Object> object, double d) { 259 DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(); 260 JValue bits; 261 bits.SetD(d); 262 Set64<kTransactionActive>(object, bits.GetJ()); 263 } 264 265 inline ObjPtr<mirror::Object> ArtField::GetObject(ObjPtr<mirror::Object> object) { 266 DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(); 267 return GetObj(object); 268 } 269 270 template<bool kTransactionActive> 271 inline void ArtField::SetObject(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> l) { 272 DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(); 273 SetObj<kTransactionActive>(object, l); 274 } 275 276 inline const char* ArtField::GetName() REQUIRES_SHARED(Locks::mutator_lock_) { 277 uint32_t field_index = GetDexFieldIndex(); 278 if (UNLIKELY(IsProxyField())) { 279 DCHECK(IsStatic()); 280 DCHECK_LT(field_index, 2U); 281 return field_index == 0 ? "interfaces" : "throws"; 282 } 283 const DexFile* dex_file = GetDexFile(); 284 return dex_file->GetFieldName(dex_file->GetFieldId(field_index)); 285 } 286 287 inline const char* ArtField::GetTypeDescriptor() REQUIRES_SHARED(Locks::mutator_lock_) { 288 uint32_t field_index = GetDexFieldIndex(); 289 if (UNLIKELY(IsProxyField())) { 290 DCHECK(IsStatic()); 291 DCHECK_LT(field_index, 2U); 292 // 0 == Class[] interfaces; 1 == Class[][] throws; 293 return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;"; 294 } 295 const DexFile* dex_file = GetDexFile(); 296 const dex::FieldId& field_id = dex_file->GetFieldId(field_index); 297 return dex_file->GetFieldTypeDescriptor(field_id); 298 } 299 300 inline Primitive::Type ArtField::GetTypeAsPrimitiveType() 301 REQUIRES_SHARED(Locks::mutator_lock_) { 302 return Primitive::GetType(GetTypeDescriptor()[0]); 303 } 304 305 inline bool ArtField::IsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_) { 306 return GetTypeAsPrimitiveType() != Primitive::kPrimNot; 307 } 308 309 inline ObjPtr<mirror::Class> ArtField::LookupResolvedType() { 310 ScopedAssertNoThreadSuspension ants(__FUNCTION__); 311 if (UNLIKELY(IsProxyField())) { 312 return ProxyFindSystemClass(GetTypeDescriptor()); 313 } 314 ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->LookupResolvedType( 315 GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this); 316 DCHECK(!Thread::Current()->IsExceptionPending()); 317 return type; 318 } 319 320 inline ObjPtr<mirror::Class> ArtField::ResolveType() { 321 if (UNLIKELY(IsProxyField())) { 322 return ProxyFindSystemClass(GetTypeDescriptor()); 323 } 324 ObjPtr<mirror::Class> type = Runtime::Current()->GetClassLinker()->ResolveType( 325 GetDexFile()->GetFieldId(GetDexFieldIndex()).type_idx_, this); 326 DCHECK_EQ(type == nullptr, Thread::Current()->IsExceptionPending()); 327 return type; 328 } 329 330 inline size_t ArtField::FieldSize() REQUIRES_SHARED(Locks::mutator_lock_) { 331 return Primitive::ComponentSize(GetTypeAsPrimitiveType()); 332 } 333 334 template <ReadBarrierOption kReadBarrierOption> 335 inline ObjPtr<mirror::DexCache> ArtField::GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_) { 336 ObjPtr<mirror::Class> klass = GetDeclaringClass<kReadBarrierOption>(); 337 return klass->GetDexCache<kDefaultVerifyFlags, kReadBarrierOption>(); 338 } 339 340 inline const DexFile* ArtField::GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_) { 341 return GetDexCache<kWithoutReadBarrier>()->GetDexFile(); 342 } 343 344 inline ObjPtr<mirror::String> ArtField::ResolveNameString() { 345 uint32_t dex_field_index = GetDexFieldIndex(); 346 CHECK_NE(dex_field_index, dex::kDexNoIndex); 347 const dex::FieldId& field_id = GetDexFile()->GetFieldId(dex_field_index); 348 return Runtime::Current()->GetClassLinker()->ResolveString(field_id.name_idx_, this); 349 } 350 351 template <typename Visitor> 352 inline void ArtField::UpdateObjects(const Visitor& visitor) { 353 ObjPtr<mirror::Class> old_class = DeclaringClassRoot().Read<kWithoutReadBarrier>(); 354 ObjPtr<mirror::Class> new_class = visitor(old_class.Ptr()); 355 if (old_class != new_class) { 356 SetDeclaringClass(new_class); 357 } 358 } 359 360 // If kExactOffset is true then we only find the matching offset, not the field containing the 361 // offset. 362 template <bool kExactOffset> 363 static inline ArtField* FindFieldWithOffset( 364 const IterationRange<StrideIterator<ArtField>>& fields, 365 uint32_t field_offset) REQUIRES_SHARED(Locks::mutator_lock_) { 366 for (ArtField& field : fields) { 367 if (kExactOffset) { 368 if (field.GetOffset().Uint32Value() == field_offset) { 369 return &field; 370 } 371 } else { 372 const uint32_t offset = field.GetOffset().Uint32Value(); 373 Primitive::Type type = field.GetTypeAsPrimitiveType(); 374 const size_t field_size = Primitive::ComponentSize(type); 375 DCHECK_GT(field_size, 0u); 376 if (offset <= field_offset && field_offset < offset + field_size) { 377 return &field; 378 } 379 } 380 } 381 return nullptr; 382 } 383 384 template <bool kExactOffset> 385 inline ArtField* ArtField::FindInstanceFieldWithOffset(ObjPtr<mirror::Class> klass, 386 uint32_t field_offset) { 387 DCHECK(klass != nullptr); 388 ArtField* field = FindFieldWithOffset<kExactOffset>(klass->GetIFields(), field_offset); 389 if (field != nullptr) { 390 return field; 391 } 392 // We did not find field in the class: look into superclass. 393 return (klass->GetSuperClass() != nullptr) ? 394 FindInstanceFieldWithOffset<kExactOffset>(klass->GetSuperClass(), field_offset) : nullptr; 395 } 396 397 template <bool kExactOffset> 398 inline ArtField* ArtField::FindStaticFieldWithOffset(ObjPtr<mirror::Class> klass, 399 uint32_t field_offset) { 400 DCHECK(klass != nullptr); 401 return FindFieldWithOffset<kExactOffset>(klass->GetSFields(), field_offset); 402 } 403 404 inline ObjPtr<mirror::ClassLoader> ArtField::GetClassLoader() { 405 return GetDeclaringClass()->GetClassLoader(); 406 } 407 408 } // namespace art 409 410 #endif // ART_RUNTIME_ART_FIELD_INL_H_ 411