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.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 mirror::Class* result = declaring_class_.Read(); 38 DCHECK(result != nullptr); 39 DCHECK(result->IsLoaded() || result->IsErroneous()); 40 return result; 41 } 42 43 inline void ArtField::SetDeclaringClass(mirror::Class* new_declaring_class) { 44 declaring_class_ = GcRoot<mirror::Class>(new_declaring_class); 45 } 46 47 inline uint32_t ArtField::GetAccessFlags() { 48 DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); 49 return access_flags_; 50 } 51 52 inline MemberOffset ArtField::GetOffset() { 53 DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous()); 54 return MemberOffset(offset_); 55 } 56 57 inline MemberOffset ArtField::GetOffsetDuringLinking() { 58 DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous()); 59 return MemberOffset(offset_); 60 } 61 62 inline uint32_t ArtField::Get32(mirror::Object* object) { 63 DCHECK(object != nullptr) << PrettyField(this); 64 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 65 if (UNLIKELY(IsVolatile())) { 66 return object->GetField32Volatile(GetOffset()); 67 } 68 return object->GetField32(GetOffset()); 69 } 70 71 template<bool kTransactionActive> 72 inline void ArtField::Set32(mirror::Object* object, uint32_t new_value) { 73 DCHECK(object != nullptr) << PrettyField(this); 74 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 75 if (UNLIKELY(IsVolatile())) { 76 object->SetField32Volatile<kTransactionActive>(GetOffset(), new_value); 77 } else { 78 object->SetField32<kTransactionActive>(GetOffset(), new_value); 79 } 80 } 81 82 inline uint64_t ArtField::Get64(mirror::Object* object) { 83 DCHECK(object != nullptr) << PrettyField(this); 84 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 85 if (UNLIKELY(IsVolatile())) { 86 return object->GetField64Volatile(GetOffset()); 87 } 88 return object->GetField64(GetOffset()); 89 } 90 91 template<bool kTransactionActive> 92 inline void ArtField::Set64(mirror::Object* object, uint64_t new_value) { 93 DCHECK(object != nullptr) << PrettyField(this); 94 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 95 if (UNLIKELY(IsVolatile())) { 96 object->SetField64Volatile<kTransactionActive>(GetOffset(), new_value); 97 } else { 98 object->SetField64<kTransactionActive>(GetOffset(), new_value); 99 } 100 } 101 102 inline mirror::Object* ArtField::GetObj(mirror::Object* object) { 103 DCHECK(object != nullptr) << PrettyField(this); 104 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); 105 if (UNLIKELY(IsVolatile())) { 106 return object->GetFieldObjectVolatile<mirror::Object>(GetOffset()); 107 } 108 return object->GetFieldObject<mirror::Object>(GetOffset()); 109 } 110 111 template<bool kTransactionActive> 112 inline void ArtField::SetObj(mirror::Object* object, mirror::Object* new_value) { 113 DCHECK(object != nullptr) << PrettyField(this); 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(this); \ 124 DCHECK(object != nullptr) << PrettyField(this); \ 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_EQ(Primitive::kPrim ## type, GetTypeAsPrimitiveType()) << PrettyField(this); \ 133 DCHECK(object != nullptr) << PrettyField(this); \ 134 DCHECK(!IsStatic() || (object == GetDeclaringClass()) || !Runtime::Current()->IsStarted()); \ 135 if (UNLIKELY(IsVolatile())) { \ 136 object->SetField ## type ## Volatile<kTransactionActive>(GetOffset(), value); \ 137 } else { \ 138 object->SetField ## type<kTransactionActive>(GetOffset(), value); \ 139 } 140 141 inline uint8_t ArtField::GetBoolean(mirror::Object* object) { 142 FIELD_GET(object, Boolean); 143 } 144 145 template<bool kTransactionActive> 146 inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) { 147 FIELD_SET(object, Boolean, z); 148 } 149 150 inline int8_t ArtField::GetByte(mirror::Object* object) { 151 FIELD_GET(object, Byte); 152 } 153 154 template<bool kTransactionActive> 155 inline void ArtField::SetByte(mirror::Object* object, int8_t b) { 156 FIELD_SET(object, Byte, b); 157 } 158 159 inline uint16_t ArtField::GetChar(mirror::Object* object) { 160 FIELD_GET(object, Char); 161 } 162 163 template<bool kTransactionActive> 164 inline void ArtField::SetChar(mirror::Object* object, uint16_t c) { 165 FIELD_SET(object, Char, c); 166 } 167 168 inline int16_t ArtField::GetShort(mirror::Object* object) { 169 FIELD_GET(object, Short); 170 } 171 172 template<bool kTransactionActive> 173 inline void ArtField::SetShort(mirror::Object* object, int16_t s) { 174 FIELD_SET(object, Short, s); 175 } 176 177 #undef FIELD_GET 178 #undef FIELD_SET 179 180 inline int32_t ArtField::GetInt(mirror::Object* object) { 181 if (kIsDebugBuild) { 182 Primitive::Type type = GetTypeAsPrimitiveType(); 183 CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); 184 } 185 return Get32(object); 186 } 187 188 template<bool kTransactionActive> 189 inline void ArtField::SetInt(mirror::Object* object, int32_t i) { 190 if (kIsDebugBuild) { 191 Primitive::Type type = GetTypeAsPrimitiveType(); 192 CHECK(type == Primitive::kPrimInt || type == Primitive::kPrimFloat) << PrettyField(this); 193 } 194 Set32<kTransactionActive>(object, i); 195 } 196 197 inline int64_t ArtField::GetLong(mirror::Object* object) { 198 if (kIsDebugBuild) { 199 Primitive::Type type = GetTypeAsPrimitiveType(); 200 CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); 201 } 202 return Get64(object); 203 } 204 205 template<bool kTransactionActive> 206 inline void ArtField::SetLong(mirror::Object* object, int64_t j) { 207 if (kIsDebugBuild) { 208 Primitive::Type type = GetTypeAsPrimitiveType(); 209 CHECK(type == Primitive::kPrimLong || type == Primitive::kPrimDouble) << PrettyField(this); 210 } 211 Set64<kTransactionActive>(object, j); 212 } 213 214 inline float ArtField::GetFloat(mirror::Object* object) { 215 DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); 216 JValue bits; 217 bits.SetI(Get32(object)); 218 return bits.GetF(); 219 } 220 221 template<bool kTransactionActive> 222 inline void ArtField::SetFloat(mirror::Object* object, float f) { 223 DCHECK_EQ(Primitive::kPrimFloat, GetTypeAsPrimitiveType()) << PrettyField(this); 224 JValue bits; 225 bits.SetF(f); 226 Set32<kTransactionActive>(object, bits.GetI()); 227 } 228 229 inline double ArtField::GetDouble(mirror::Object* object) { 230 DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); 231 JValue bits; 232 bits.SetJ(Get64(object)); 233 return bits.GetD(); 234 } 235 236 template<bool kTransactionActive> 237 inline void ArtField::SetDouble(mirror::Object* object, double d) { 238 DCHECK_EQ(Primitive::kPrimDouble, GetTypeAsPrimitiveType()) << PrettyField(this); 239 JValue bits; 240 bits.SetD(d); 241 Set64<kTransactionActive>(object, bits.GetJ()); 242 } 243 244 inline mirror::Object* ArtField::GetObject(mirror::Object* object) { 245 DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); 246 return GetObj(object); 247 } 248 249 template<bool kTransactionActive> 250 inline void ArtField::SetObject(mirror::Object* object, mirror::Object* l) { 251 DCHECK_EQ(Primitive::kPrimNot, GetTypeAsPrimitiveType()) << PrettyField(this); 252 SetObj<kTransactionActive>(object, l); 253 } 254 255 inline const char* ArtField::GetName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 256 uint32_t field_index = GetDexFieldIndex(); 257 if (UNLIKELY(GetDeclaringClass()->IsProxyClass())) { 258 DCHECK(IsStatic()); 259 DCHECK_LT(field_index, 2U); 260 return field_index == 0 ? "interfaces" : "throws"; 261 } 262 const DexFile* dex_file = GetDexFile(); 263 return dex_file->GetFieldName(dex_file->GetFieldId(field_index)); 264 } 265 266 inline const char* ArtField::GetTypeDescriptor() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 267 uint32_t field_index = GetDexFieldIndex(); 268 if (UNLIKELY(GetDeclaringClass()->IsProxyClass())) { 269 DCHECK(IsStatic()); 270 DCHECK_LT(field_index, 2U); 271 // 0 == Class[] interfaces; 1 == Class[][] throws; 272 return field_index == 0 ? "[Ljava/lang/Class;" : "[[Ljava/lang/Class;"; 273 } 274 const DexFile* dex_file = GetDexFile(); 275 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index); 276 return dex_file->GetFieldTypeDescriptor(field_id); 277 } 278 279 inline Primitive::Type ArtField::GetTypeAsPrimitiveType() 280 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 281 return Primitive::GetType(GetTypeDescriptor()[0]); 282 } 283 284 inline bool ArtField::IsPrimitiveType() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 285 return GetTypeAsPrimitiveType() != Primitive::kPrimNot; 286 } 287 288 template <bool kResolve> 289 inline mirror::Class* ArtField::GetType() { 290 const uint32_t field_index = GetDexFieldIndex(); 291 auto* declaring_class = GetDeclaringClass(); 292 if (UNLIKELY(declaring_class->IsProxyClass())) { 293 return ProxyFindSystemClass(GetTypeDescriptor()); 294 } 295 auto* dex_cache = declaring_class->GetDexCache(); 296 const DexFile* const dex_file = dex_cache->GetDexFile(); 297 const DexFile::FieldId& field_id = dex_file->GetFieldId(field_index); 298 mirror::Class* type = dex_cache->GetResolvedType(field_id.type_idx_); 299 if (kResolve && UNLIKELY(type == nullptr)) { 300 type = ResolveGetType(field_id.type_idx_); 301 CHECK(type != nullptr || Thread::Current()->IsExceptionPending()); 302 } 303 return type; 304 } 305 306 inline size_t ArtField::FieldSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 307 return Primitive::ComponentSize(GetTypeAsPrimitiveType()); 308 } 309 310 inline mirror::DexCache* ArtField::GetDexCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 311 return GetDeclaringClass()->GetDexCache(); 312 } 313 314 inline const DexFile* ArtField::GetDexFile() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 315 return GetDexCache()->GetDexFile(); 316 } 317 318 inline mirror::String* ArtField::GetStringName(Thread* self, bool resolve) { 319 auto dex_field_index = GetDexFieldIndex(); 320 CHECK_NE(dex_field_index, DexFile::kDexNoIndex); 321 auto* dex_cache = GetDexCache(); 322 const auto* dex_file = dex_cache->GetDexFile(); 323 const auto& field_id = dex_file->GetFieldId(dex_field_index); 324 auto* name = dex_cache->GetResolvedString(field_id.name_idx_); 325 if (resolve && name == nullptr) { 326 name = ResolveGetStringName(self, *dex_file, field_id.name_idx_, dex_cache); 327 } 328 return name; 329 } 330 331 template<typename RootVisitorType> 332 inline void ArtField::VisitRoots(RootVisitorType& visitor) { 333 visitor.VisitRoot(declaring_class_.AddressWithoutBarrier()); 334 } 335 336 } // namespace art 337 338 #endif // ART_RUNTIME_ART_FIELD_INL_H_ 339