art_field-inl.h revision a7a4759946d9f11c88dc108b2b6a9518ce9c1e18
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 34namespace art { 35 36inline 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()); 41 return result; 42} 43 44inline void ArtField::SetDeclaringClass(mirror::Class* new_declaring_class) { 45 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); 46} 47 48inline uint32_t ArtField::GetAccessFlags() { 49 DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); 50 return access_flags_; 51} 52 53inline MemberOffset ArtField::GetOffset() { 54 DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); 55 return MemberOffset(offset_); 56} 57 58inline MemberOffset ArtField::GetOffsetDuringLinking() { 59 DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); 60 return MemberOffset(offset_); 61} 62 63inline 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 72template<bool kTransactionActive> 73inline 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 83inline 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 92template<bool kTransactionActive> 93inline 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 103inline 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 112template<bool kTransactionActive> 113inline 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 142inline uint8_t ArtField::GetBoolean(mirror::Object* object) { 143 FIELD_GET(object, Boolean); 144} 145 146template<bool kTransactionActive> 147inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) { 148 FIELD_SET(object, Boolean, z); 149} 150 151inline int8_t ArtField::GetByte(mirror::Object* object) { 152 FIELD_GET(object, Byte); 153} 154 155template<bool kTransactionActive> 156inline void ArtField::SetByte(mirror::Object* object, int8_t b) { 157 FIELD_SET(object, Byte, b); 158} 159 160inline uint16_t ArtField::GetChar(mirror::Object* object) { 161 FIELD_GET(object, Char); 162} 163 164template<bool kTransactionActive> 165inline void ArtField::SetChar(mirror::Object* object, uint16_t c) { 166 FIELD_SET(object, Char, c); 167} 168 169inline int16_t ArtField::GetShort(mirror::Object* object) { 170 FIELD_GET(object, Short); 171} 172 173template<bool kTransactionActive> 174inline 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 181inline 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 189template<bool kTransactionActive> 190inline 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 198inline 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 206template<bool kTransactionActive> 207inline 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 215inline 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 222template<bool kTransactionActive> 223inline 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 230inline 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 237template<bool kTransactionActive> 238inline 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 245inline mirror::Object* ArtField::GetObject(mirror::Object* object) { 246 DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); 247 return GetObj(object); 248} 249 250template<bool kTransactionActive> 251inline void ArtField::SetObject(mirror::Object* object, mirror::Object* l) { 252 DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); 253 SetObj<kTransactionActive>(object, l); 254} 255 256inline 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 267inline 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 280inline Primitive::Type ArtField::GetTypeAsPrimitiveType() 281 SHARED_REQUIRES(Locks::mutator_lock_) { 282 return Primitive::GetType(GetTypeDescriptor()[0]); 283} 284 285inline bool ArtField::IsPrimitiveType() SHARED_REQUIRES(Locks::mutator_lock_) { 286 return GetTypeAsPrimitiveType() != Primitive::kPrimNot; 287} 288 289template <bool kResolve> 290inline 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 307inline size_t ArtField::FieldSize() SHARED_REQUIRES(Locks::mutator_lock_) { 308 return Primitive::ComponentSize(GetTypeAsPrimitiveType()); 309} 310 311inline mirror::DexCache* ArtField::GetDexCache() SHARED_REQUIRES(Locks::mutator_lock_) { 312 return GetDeclaringClass()->GetDexCache(); 313} 314 315inline const DexFile* ArtField::GetDexFile() SHARED_REQUIRES(Locks::mutator_lock_) { 316 return GetDexCache()->GetDexFile(); 317} 318 319inline 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 332template<typename RootVisitorType> 333inline void ArtField::VisitRoots(RootVisitorType& visitor) { 334 visitor.VisitRoot(declaring_class_.AddressWithoutBarrier()); 335} 336 337} // namespace art 338 339#endif // ART_RUNTIME_ART_FIELD_INL_H_ 340