art_field-inl.h revision 1bc977cf2f8199311a97f2ba9431a184540e3e9c
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