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