| /* |
| * Copyright (C) 2011 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ART_RUNTIME_ART_FIELD_H_ |
| #define ART_RUNTIME_ART_FIELD_H_ |
| |
| #include <jni.h> |
| |
| #include "dex/dex_file_types.h" |
| #include "dex/modifiers.h" |
| #include "dex/primitive.h" |
| #include "gc_root.h" |
| #include "obj_ptr.h" |
| #include "offsets.h" |
| #include "read_barrier_option.h" |
| |
| namespace art { |
| |
| class DexFile; |
| class ScopedObjectAccessAlreadyRunnable; |
| |
| namespace mirror { |
| class Class; |
| class DexCache; |
| class Object; |
| class String; |
| } // namespace mirror |
| |
| class ArtField FINAL { |
| public: |
| template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier> |
| ObjPtr<mirror::Class> GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| void SetDeclaringClass(ObjPtr<mirror::Class> new_declaring_class) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| mirror::CompressedReference<mirror::Object>* GetDeclaringClassAddressWithoutBarrier() { |
| return declaring_class_.AddressWithoutBarrier(); |
| } |
| |
| uint32_t GetAccessFlags() REQUIRES_SHARED(Locks::mutator_lock_) { |
| if (kIsDebugBuild) { |
| GetAccessFlagsDCheck(); |
| } |
| return access_flags_; |
| } |
| |
| void SetAccessFlags(uint32_t new_access_flags) REQUIRES_SHARED(Locks::mutator_lock_) { |
| // Not called within a transaction. |
| access_flags_ = new_access_flags; |
| } |
| |
| bool IsPublic() REQUIRES_SHARED(Locks::mutator_lock_) { |
| return (GetAccessFlags() & kAccPublic) != 0; |
| } |
| |
| bool IsStatic() REQUIRES_SHARED(Locks::mutator_lock_) { |
| return (GetAccessFlags() & kAccStatic) != 0; |
| } |
| |
| bool IsFinal() REQUIRES_SHARED(Locks::mutator_lock_) { |
| return (GetAccessFlags() & kAccFinal) != 0; |
| } |
| |
| uint32_t GetDexFieldIndex() { |
| return field_dex_idx_; |
| } |
| |
| void SetDexFieldIndex(uint32_t new_idx) { |
| // Not called within a transaction. |
| field_dex_idx_ = new_idx; |
| } |
| |
| // Offset to field within an Object. |
| MemberOffset GetOffset() REQUIRES_SHARED(Locks::mutator_lock_) { |
| if (kIsDebugBuild) { |
| GetOffsetDCheck(); |
| } |
| return MemberOffset(offset_); |
| } |
| |
| static MemberOffset OffsetOffset() { |
| return MemberOffset(OFFSETOF_MEMBER(ArtField, offset_)); |
| } |
| |
| MemberOffset GetOffsetDuringLinking() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| void SetOffset(MemberOffset num_bytes) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // field access, null object for static fields |
| uint8_t GetBoolean(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetBoolean(ObjPtr<mirror::Object> object, uint8_t z) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| int8_t GetByte(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetByte(ObjPtr<mirror::Object> object, int8_t b) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| uint16_t GetChar(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetChar(ObjPtr<mirror::Object> object, uint16_t c) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| int16_t GetShort(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetShort(ObjPtr<mirror::Object> object, int16_t s) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| int32_t GetInt(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetInt(ObjPtr<mirror::Object> object, int32_t i) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| int64_t GetLong(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetLong(ObjPtr<mirror::Object> object, int64_t j) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| float GetFloat(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetFloat(ObjPtr<mirror::Object> object, float f) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| double GetDouble(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetDouble(ObjPtr<mirror::Object> object, double d) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| ObjPtr<mirror::Object> GetObject(ObjPtr<mirror::Object> object) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetObject(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> l) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // Raw field accesses. |
| uint32_t Get32(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void Set32(ObjPtr<mirror::Object> object, uint32_t new_value) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| uint64_t Get64(ObjPtr<mirror::Object> object) REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void Set64(ObjPtr<mirror::Object> object, uint64_t new_value) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<class MirrorType = mirror::Object> |
| ObjPtr<MirrorType> GetObj(ObjPtr<mirror::Object> object) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| template<bool kTransactionActive> |
| void SetObj(ObjPtr<mirror::Object> object, ObjPtr<mirror::Object> new_value) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // NO_THREAD_SAFETY_ANALYSIS since we don't know what the callback requires. |
| template<typename RootVisitorType> |
| ALWAYS_INLINE inline void VisitRoots(RootVisitorType& visitor) NO_THREAD_SAFETY_ANALYSIS { |
| visitor.VisitRoot(declaring_class_.AddressWithoutBarrier()); |
| } |
| |
| bool IsVolatile() REQUIRES_SHARED(Locks::mutator_lock_) { |
| return (GetAccessFlags() & kAccVolatile) != 0; |
| } |
| |
| // Returns an instance field with this offset in the given class or null if not found. |
| // If kExactOffset is true then we only find the matching offset, not the field containing the |
| // offset. |
| template <bool kExactOffset = true> |
| static ArtField* FindInstanceFieldWithOffset(ObjPtr<mirror::Class> klass, uint32_t field_offset) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // Returns a static field with this offset in the given class or null if not found. |
| // If kExactOffset is true then we only find the matching offset, not the field containing the |
| // offset. |
| template <bool kExactOffset = true> |
| static ArtField* FindStaticFieldWithOffset(ObjPtr<mirror::Class> klass, uint32_t field_offset) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| const char* GetName() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // Resolves / returns the name from the dex cache. |
| ObjPtr<mirror::String> GetStringName(Thread* self, bool resolve) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| const char* GetTypeDescriptor() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| Primitive::Type GetTypeAsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| bool IsPrimitiveType() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| ObjPtr<mirror::Class> LookupResolvedType() REQUIRES_SHARED(Locks::mutator_lock_); |
| ObjPtr<mirror::Class> ResolveType() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| size_t FieldSize() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| ObjPtr<mirror::DexCache> GetDexCache() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| const DexFile* GetDexFile() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| GcRoot<mirror::Class>& DeclaringClassRoot() { |
| return declaring_class_; |
| } |
| |
| // Returns a human-readable signature. Something like "a.b.C.f" or |
| // "int a.b.C.f" (depending on the value of 'with_type'). |
| static std::string PrettyField(ArtField* f, bool with_type = true) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| std::string PrettyField(bool with_type = true) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| // Update the declaring class with the passed in visitor. Does not use read barrier. |
| template <typename Visitor> |
| ALWAYS_INLINE void UpdateObjects(const Visitor& visitor) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| private: |
| ObjPtr<mirror::Class> ProxyFindSystemClass(const char* descriptor) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| ObjPtr<mirror::String> ResolveGetStringName(Thread* self, |
| dex::StringIndex string_idx, |
| ObjPtr<mirror::DexCache> dex_cache) |
| REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| void GetAccessFlagsDCheck() REQUIRES_SHARED(Locks::mutator_lock_); |
| void GetOffsetDCheck() REQUIRES_SHARED(Locks::mutator_lock_); |
| |
| GcRoot<mirror::Class> declaring_class_; |
| |
| uint32_t access_flags_ = 0; |
| |
| // Dex cache index of field id |
| uint32_t field_dex_idx_ = 0; |
| |
| // Offset of field within an instance or in the Class' static fields |
| uint32_t offset_ = 0; |
| }; |
| |
| } // namespace art |
| |
| #endif // ART_RUNTIME_ART_FIELD_H_ |