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