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 
GetDeclaringClass()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 
SetDeclaringClass(mirror::Class * new_declaring_class)44 inline void ArtField::SetDeclaringClass(mirror::Class* new_declaring_class) {
45   declaring_class_ = GcRoot<mirror::Class>(new_declaring_class);
46 }
47 
GetAccessFlags()48 inline uint32_t ArtField::GetAccessFlags() {
49   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
50   return access_flags_;
51 }
52 
GetOffset()53 inline MemberOffset ArtField::GetOffset() {
54   DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
55   return MemberOffset(offset_);
56 }
57 
GetOffsetDuringLinking()58 inline MemberOffset ArtField::GetOffsetDuringLinking() {
59   DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
60   return MemberOffset(offset_);
61 }
62 
Get32(mirror::Object * object)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>
Set32(mirror::Object * object,uint32_t new_value)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 
Get64(mirror::Object * object)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>
Set64(mirror::Object * object,uint64_t new_value)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 
GetObj(mirror::Object * object)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>
SetObj(mirror::Object * object,mirror::Object * new_value)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 
GetBoolean(mirror::Object * object)142 inline uint8_t ArtField::GetBoolean(mirror::Object* object) {
143   FIELD_GET(object, Boolean);
144 }
145 
146 template<bool kTransactionActive>
SetBoolean(mirror::Object * object,uint8_t z)147 inline void ArtField::SetBoolean(mirror::Object* object, uint8_t z) {
148   FIELD_SET(object, Boolean, z);
149 }
150 
GetByte(mirror::Object * object)151 inline int8_t ArtField::GetByte(mirror::Object* object) {
152   FIELD_GET(object, Byte);
153 }
154 
155 template<bool kTransactionActive>
SetByte(mirror::Object * object,int8_t b)156 inline void ArtField::SetByte(mirror::Object* object, int8_t b) {
157   FIELD_SET(object, Byte, b);
158 }
159 
GetChar(mirror::Object * object)160 inline uint16_t ArtField::GetChar(mirror::Object* object) {
161   FIELD_GET(object, Char);
162 }
163 
164 template<bool kTransactionActive>
SetChar(mirror::Object * object,uint16_t c)165 inline void ArtField::SetChar(mirror::Object* object, uint16_t c) {
166   FIELD_SET(object, Char, c);
167 }
168 
GetShort(mirror::Object * object)169 inline int16_t ArtField::GetShort(mirror::Object* object) {
170   FIELD_GET(object, Short);
171 }
172 
173 template<bool kTransactionActive>
SetShort(mirror::Object * object,int16_t s)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 
GetInt(mirror::Object * object)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>
SetInt(mirror::Object * object,int32_t i)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 
GetLong(mirror::Object * object)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>
SetLong(mirror::Object * object,int64_t j)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 
GetFloat(mirror::Object * object)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>
SetFloat(mirror::Object * object,float f)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 
GetDouble(mirror::Object * object)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>
SetDouble(mirror::Object * object,double d)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 
GetObject(mirror::Object * object)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>
SetObject(mirror::Object * object,mirror::Object * l)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 
GetName()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 
GetTypeDescriptor()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 
GetTypeAsPrimitiveType()280 inline Primitive::Type ArtField::GetTypeAsPrimitiveType()
281     SHARED_REQUIRES(Locks::mutator_lock_) {
282   return Primitive::GetType(GetTypeDescriptor()[0]);
283 }
284 
IsPrimitiveType()285 inline bool ArtField::IsPrimitiveType() SHARED_REQUIRES(Locks::mutator_lock_) {
286   return GetTypeAsPrimitiveType() != Primitive::kPrimNot;
287 }
288 
289 template <bool kResolve>
GetType()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 
FieldSize()307 inline size_t ArtField::FieldSize() SHARED_REQUIRES(Locks::mutator_lock_) {
308   return Primitive::ComponentSize(GetTypeAsPrimitiveType());
309 }
310 
GetDexCache()311 inline mirror::DexCache* ArtField::GetDexCache() SHARED_REQUIRES(Locks::mutator_lock_) {
312   return GetDeclaringClass()->GetDexCache();
313 }
314 
GetDexFile()315 inline const DexFile* ArtField::GetDexFile() SHARED_REQUIRES(Locks::mutator_lock_) {
316   return GetDexCache()->GetDexFile();
317 }
318 
GetStringName(Thread * self,bool resolve)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>
VisitRoots(RootVisitorType & visitor)333 inline void ArtField::VisitRoots(RootVisitorType& visitor) {
334   visitor.VisitRoot(declaring_class_.AddressWithoutBarrier());
335 }
336 
337 template <typename Visitor>
UpdateObjects(const Visitor & 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>
FindFieldWithOffset(const IterationRange<StrideIterator<ArtField>> & fields,uint32_t field_offset)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>
FindInstanceFieldWithOffset(mirror::Class * klass,uint32_t field_offset)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>
FindStaticFieldWithOffset(mirror::Class * klass,uint32_t field_offset)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