summaryrefslogtreecommitdiff
path: root/src/object.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/object.h')
-rw-r--r--src/object.h2748
1 files changed, 0 insertions, 2748 deletions
diff --git a/src/object.h b/src/object.h
deleted file mode 100644
index f02e312dd6..0000000000
--- a/src/object.h
+++ /dev/null
@@ -1,2748 +0,0 @@
-/*
- * 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_SRC_OBJECT_H_
-#define ART_SRC_OBJECT_H_
-
-#include <iosfwd>
-#include <vector>
-
-#include "atomic.h"
-#include "base/casts.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/stringpiece.h"
-#include "globals.h"
-#include "heap.h"
-#include "invoke_type.h"
-#include "modifiers.h"
-#include "offsets.h"
-#include "primitive.h"
-#include "runtime.h"
-#include "thread.h"
-#include "UniquePtr.h"
-#include "utf.h"
-
-namespace art {
-
-class Array;
-class Class;
-class ClassLoader;
-class CodeAndDirectMethods;
-class DexCache;
-class Field;
-class IfTable;
-class Monitor;
-class Member;
-class AbstractMethod;
-class Object;
-class StaticStorageBase;
-class String;
-template<class T> class ObjectArray;
-template<class T> class PrimitiveArray;
-typedef PrimitiveArray<uint8_t> BooleanArray;
-typedef PrimitiveArray<int8_t> ByteArray;
-typedef PrimitiveArray<uint16_t> CharArray;
-typedef PrimitiveArray<double> DoubleArray;
-typedef PrimitiveArray<float> FloatArray;
-typedef PrimitiveArray<int32_t> IntArray;
-typedef PrimitiveArray<int64_t> LongArray;
-typedef PrimitiveArray<int16_t> ShortArray;
-union JValue;
-
-#if defined(ART_USE_LLVM_COMPILER)
-namespace compiler_llvm {
- class InferredRegCategoryMap;
-} // namespace compiler_llvm
-#endif
-
-/*
- * Definitions for packing refOffsets in Class.
- */
-/*
- * A magic value for refOffsets. Ignore the bits and walk the super
- * chain when this is the value.
- * [This is an unlikely "natural" value, since it would be 30 non-ref instance
- * fields followed by 2 ref instance fields.]
- */
-#define CLASS_WALK_SUPER ((unsigned int)(3))
-#define CLASS_BITS_PER_WORD (sizeof(unsigned long int) * 8)
-#define CLASS_OFFSET_ALIGNMENT 4
-#define CLASS_HIGH_BIT ((unsigned int)1 << (CLASS_BITS_PER_WORD - 1))
-/*
- * Given an offset, return the bit number which would encode that offset.
- * Local use only.
- */
-#define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \
- ((unsigned int)(byteOffset) / \
- CLASS_OFFSET_ALIGNMENT)
-/*
- * Is the given offset too large to be encoded?
- */
-#define CLASS_CAN_ENCODE_OFFSET(byteOffset) \
- (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD)
-/*
- * Return a single bit, encoding the offset.
- * Undefined if the offset is too large, as defined above.
- */
-#define CLASS_BIT_FROM_OFFSET(byteOffset) \
- (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset))
-/*
- * Return an offset, given a bit number as returned from CLZ.
- */
-#define CLASS_OFFSET_FROM_CLZ(rshift) \
- MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT))
-
-#define OFFSET_OF_OBJECT_MEMBER(type, field) \
- MemberOffset(OFFSETOF_MEMBER(type, field))
-
-// Classes shared with the managed side of the world need to be packed
-// so that they don't have extra platform specific padding.
-#define MANAGED PACKED(4)
-
-// C++ mirror of java.lang.Object
-class MANAGED Object {
- public:
- static MemberOffset ClassOffset() {
- return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
- }
-
- Class* GetClass() const {
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
- }
-
- void SetClass(Class* new_klass);
-
- bool InstanceOf(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- size_t SizeOf() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- Object* Clone(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- int32_t IdentityHashCode() const {
- #ifdef MOVING_GARBAGE_COLLECTOR
- // TODO: we'll need to use the Object's internal concept of identity
- UNIMPLEMENTED(FATAL);
- #endif
- return reinterpret_cast<int32_t>(this);
- }
-
- static MemberOffset MonitorOffset() {
- return OFFSET_OF_OBJECT_MEMBER(Object, monitor_);
- }
-
- volatile int32_t* GetRawLockWordAddress() {
- byte* raw_addr = reinterpret_cast<byte*>(this) +
- OFFSET_OF_OBJECT_MEMBER(Object, monitor_).Int32Value();
- int32_t* word_addr = reinterpret_cast<int32_t*>(raw_addr);
- return const_cast<volatile int32_t*>(word_addr);
- }
-
- uint32_t GetThinLockId();
-
- void MonitorEnter(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- EXCLUSIVE_LOCK_FUNCTION(monitor_lock_);
-
- bool MonitorExit(Thread* thread) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
- UNLOCK_FUNCTION(monitor_lock_);
-
- void Notify() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void NotifyAll() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void Wait() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void Wait(int64_t timeout) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void Wait(int64_t timeout, int32_t nanos) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsClass() const;
-
- Class* AsClass() {
- DCHECK(IsClass());
- return down_cast<Class*>(this);
- }
-
- const Class* AsClass() const {
- DCHECK(IsClass());
- return down_cast<const Class*>(this);
- }
-
- bool IsObjectArray() const;
-
- template<class T>
- ObjectArray<T>* AsObjectArray();
-
- template<class T>
- const ObjectArray<T>* AsObjectArray() const;
-
- bool IsArrayInstance() const;
-
- Array* AsArray() {
- DCHECK(IsArrayInstance());
- return down_cast<Array*>(this);
- }
-
- const Array* AsArray() const {
- DCHECK(IsArrayInstance());
- return down_cast<const Array*>(this);
- }
-
- BooleanArray* AsBooleanArray();
- ByteArray* AsByteArray();
- CharArray* AsCharArray();
- ShortArray* AsShortArray();
- IntArray* AsIntArray();
- LongArray* AsLongArray();
-
- String* AsString();
-
- Throwable* AsThrowable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsMethod() const;
-
- AbstractMethod* AsMethod() {
- DCHECK(IsMethod());
- return down_cast<AbstractMethod*>(this);
- }
-
- const AbstractMethod* AsMethod() const {
- DCHECK(IsMethod());
- return down_cast<const AbstractMethod*>(this);
- }
-
- bool IsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- Field* AsField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsField());
- return down_cast<Field*>(this);
- }
-
- const Field* AsField() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsField());
- return down_cast<const Field*>(this);
- }
-
- bool IsReferenceInstance() const;
-
- bool IsWeakReferenceInstance() const;
-
- bool IsSoftReferenceInstance() const;
-
- bool IsFinalizerReferenceInstance() const;
-
- bool IsPhantomReferenceInstance() const;
-
- // Accessors for Java type fields
- template<class T>
- T GetFieldObject(MemberOffset field_offset, bool is_volatile) const {
- T result = reinterpret_cast<T>(GetField32(field_offset, is_volatile));
- Runtime::Current()->GetHeap()->VerifyObject(result);
- return result;
- }
-
- void SetFieldObject(MemberOffset field_offset, const Object* new_value, bool is_volatile,
- bool this_is_valid = true) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Runtime::Current()->GetHeap()->VerifyObject(new_value);
- SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
- if (new_value != NULL) {
- CheckFieldAssignment(field_offset, new_value);
- Runtime::Current()->GetHeap()->WriteBarrierField(this, field_offset, new_value);
- }
- }
-
- uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const {
- Runtime::Current()->GetHeap()->VerifyObject(this);
- const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
- const int32_t* word_addr = reinterpret_cast<const int32_t*>(raw_addr);
- if (UNLIKELY(is_volatile)) {
- return android_atomic_acquire_load(word_addr);
- } else {
- return *word_addr;
- }
- }
-
- void SetField32(MemberOffset field_offset, uint32_t new_value, bool is_volatile, bool this_is_valid = true) {
- if (this_is_valid) {
- Runtime::Current()->GetHeap()->VerifyObject(this);
- }
- byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
- uint32_t* word_addr = reinterpret_cast<uint32_t*>(raw_addr);
- if (UNLIKELY(is_volatile)) {
- /*
- * TODO: add an android_atomic_synchronization_store() function and
- * use it in the 32-bit volatile set handlers. On some platforms we
- * can use a fast atomic instruction and avoid the barriers.
- */
- ANDROID_MEMBAR_STORE();
- *word_addr = new_value;
- ANDROID_MEMBAR_FULL();
- } else {
- *word_addr = new_value;
- }
- }
-
- uint64_t GetField64(MemberOffset field_offset, bool is_volatile) const {
- Runtime::Current()->GetHeap()->VerifyObject(this);
- const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset.Int32Value();
- const int64_t* addr = reinterpret_cast<const int64_t*>(raw_addr);
- if (UNLIKELY(is_volatile)) {
- uint64_t result = QuasiAtomic::Read64(addr);
- ANDROID_MEMBAR_FULL();
- return result;
- } else {
- return *addr;
- }
- }
-
- void SetField64(MemberOffset field_offset, uint64_t new_value, bool is_volatile) {
- Runtime::Current()->GetHeap()->VerifyObject(this);
- byte* raw_addr = reinterpret_cast<byte*>(this) + field_offset.Int32Value();
- int64_t* addr = reinterpret_cast<int64_t*>(raw_addr);
- if (UNLIKELY(is_volatile)) {
- ANDROID_MEMBAR_STORE();
- QuasiAtomic::Write64(addr, new_value);
- // Post-store barrier not required due to use of atomic op or mutex.
- } else {
- *addr = new_value;
- }
- }
-
- protected:
- // Accessors for non-Java type fields
- template<class T>
- T GetFieldPtr(MemberOffset field_offset, bool is_volatile) const {
- return reinterpret_cast<T>(GetField32(field_offset, is_volatile));
- }
-
- template<typename T>
- void SetFieldPtr(MemberOffset field_offset, T new_value, bool is_volatile, bool this_is_valid = true) {
- SetField32(field_offset, reinterpret_cast<uint32_t>(new_value), is_volatile, this_is_valid);
- }
-
- private:
-#if VERIFY_OBJECT_ENABLED
- void CheckFieldAssignment(MemberOffset field_offset, const Object* new_value)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-#else
- void CheckFieldAssignment(MemberOffset, const Object*)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {}
-#endif
-
- Class* klass_;
-
- uint32_t monitor_;
-
- friend class ImageWriter; // for abusing monitor_ directly
- friend struct ObjectOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
-};
-
-// C++ mirror of java.lang.reflect.Field
-class MANAGED Field : public Object {
- public:
- Class* GetDeclaringClass() const;
-
- void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- uint32_t GetAccessFlags() const;
-
- void SetAccessFlags(uint32_t new_access_flags) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), new_access_flags, false);
- }
-
- bool IsPublic() const {
- return (GetAccessFlags() & kAccPublic) != 0;
- }
-
- bool IsStatic() const {
- return (GetAccessFlags() & kAccStatic) != 0;
- }
-
- bool IsFinal() const {
- return (GetAccessFlags() & kAccFinal) != 0;
- }
-
- uint32_t GetDexFieldIndex() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), false);
- }
-
- void SetDexFieldIndex(uint32_t new_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Field, field_dex_idx_), new_idx, false);
- }
-
- // Offset to field within an Object
- MemberOffset GetOffset() const;
-
- static MemberOffset OffsetOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Field, offset_));
- }
-
- MemberOffset GetOffsetDuringLinking() const;
-
- void SetOffset(MemberOffset num_bytes);
-
- // field access, null object for static fields
- bool GetBoolean(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetBoolean(Object* object, bool z) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int8_t GetByte(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetByte(Object* object, int8_t b) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint16_t GetChar(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetChar(Object* object, uint16_t c) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int16_t GetShort(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetShort(Object* object, int16_t s) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int32_t GetInt(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetInt(Object* object, int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- int64_t GetLong(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetLong(Object* object, int64_t j) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- float GetFloat(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetFloat(Object* object, float f) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- double GetDouble(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetDouble(Object* object, double d) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object* GetObject(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObject(Object* object, const Object* l) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // raw field accesses
- uint32_t Get32(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Set32(Object* object, uint32_t new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- uint64_t Get64(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Set64(Object* object, uint64_t new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Object* GetObj(const Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void SetObj(Object* object, const Object* new_value) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static Class* GetJavaLangReflectField() {
- DCHECK(java_lang_reflect_Field_ != NULL);
- return java_lang_reflect_Field_;
- }
-
- static void SetClass(Class* java_lang_reflect_Field);
- static void ResetClass();
-
- bool IsVolatile() const {
- return (GetAccessFlags() & kAccVolatile) != 0;
- }
-
- private:
- // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- // The class we are a part of
- Class* declaring_class_;
-
- uint32_t access_flags_;
-
- // Dex cache index of field id
- uint32_t field_dex_idx_;
-
- // Offset of field within an instance or in the Class' static fields
- uint32_t offset_;
-
- static Class* java_lang_reflect_Field_;
-
- friend struct FieldOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(Field);
-};
-
-// C++ mirror of java.lang.reflect.Method and java.lang.reflect.Constructor
-class MANAGED AbstractMethod : public Object {
- public:
- // A function that invokes a method with an array of its arguments.
- typedef void InvokeStub(const AbstractMethod* method,
- Object* obj,
- Thread* thread,
- JValue* args,
- JValue* result);
-
- Class* GetDeclaringClass() const;
-
- void SetDeclaringClass(Class *new_declaring_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static MemberOffset DeclaringClassOffset() {
- return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_));
- }
-
- uint32_t GetAccessFlags() const;
-
- void SetAccessFlags(uint32_t new_access_flags) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), new_access_flags, false);
- }
-
- // Approximate what kind of method call would be used for this method.
- InvokeType GetInvokeType() const;
-
- // Returns true if the method is declared public.
- bool IsPublic() const {
- return (GetAccessFlags() & kAccPublic) != 0;
- }
-
- // Returns true if the method is declared private.
- bool IsPrivate() const {
- return (GetAccessFlags() & kAccPrivate) != 0;
- }
-
- // Returns true if the method is declared static.
- bool IsStatic() const {
- return (GetAccessFlags() & kAccStatic) != 0;
- }
-
- // Returns true if the method is a constructor.
- bool IsConstructor() const {
- return (GetAccessFlags() & kAccConstructor) != 0;
- }
-
- // Returns true if the method is static, private, or a constructor.
- bool IsDirect() const {
- return IsDirect(GetAccessFlags());
- }
-
- static bool IsDirect(uint32_t access_flags) {
- return (access_flags & (kAccStatic | kAccPrivate | kAccConstructor)) != 0;
- }
-
- // Returns true if the method is declared synchronized.
- bool IsSynchronized() const {
- uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
- return (GetAccessFlags() & synchonized) != 0;
- }
-
- bool IsFinal() const {
- return (GetAccessFlags() & kAccFinal) != 0;
- }
-
- bool IsMiranda() const {
- return (GetAccessFlags() & kAccMiranda) != 0;
- }
-
- bool IsNative() const {
- return (GetAccessFlags() & kAccNative) != 0;
- }
-
- bool IsAbstract() const {
- return (GetAccessFlags() & kAccAbstract) != 0;
- }
-
- bool IsSynthetic() const {
- return (GetAccessFlags() & kAccSynthetic) != 0;
- }
-
- bool IsProxyMethod() const;
-
- bool CheckIncompatibleClassChange(InvokeType type);
-
- uint16_t GetMethodIndex() const;
-
- size_t GetVtableIndex() const {
- return GetMethodIndex();
- }
-
- void SetMethodIndex(uint16_t new_method_index) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), new_method_index, false);
- }
-
- static MemberOffset MethodIndexOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_);
- }
-
- uint32_t GetCodeItemOffset() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), false);
- }
-
- void SetCodeItemOffset(uint32_t new_code_off) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_item_offset_), new_code_off, false);
- }
-
- // Number of 32bit registers that would be required to hold all the arguments
- static size_t NumArgRegisters(const StringPiece& shorty);
-
- uint32_t GetDexMethodIndex() const;
-
- void SetDexMethodIndex(uint32_t new_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), new_idx, false);
- }
-
- ObjectArray<String>* GetDexCacheStrings() const;
- void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static MemberOffset DexCacheStringsOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_strings_);
- }
-
- static MemberOffset DexCacheResolvedMethodsOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_methods_);
- }
-
- static MemberOffset DexCacheResolvedTypesOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, dex_cache_resolved_types_);
- }
-
- static MemberOffset DexCacheInitializedStaticStorageOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod,
- dex_cache_initialized_static_storage_);
- }
-
- ObjectArray<AbstractMethod>* GetDexCacheResolvedMethods() const;
- void SetDexCacheResolvedMethods(ObjectArray<AbstractMethod>* new_dex_cache_methods)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- ObjectArray<Class>* GetDexCacheResolvedTypes() const;
- void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- ObjectArray<StaticStorageBase>* GetDexCacheInitializedStaticStorage() const;
- void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Find the method that this method overrides
- AbstractMethod* FindOverriddenMethod() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void Invoke(Thread* self, Object* receiver, JValue* args, JValue* result)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- const void* GetCode() const {
- return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), false);
- }
-
- void SetCode(const void* code) {
- SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_), code, false);
- }
-
- uint32_t GetCodeSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
- uintptr_t code = reinterpret_cast<uintptr_t>(GetCode());
- if (code == 0) {
- return 0;
- }
- // TODO: make this Thumb2 specific
- code &= ~0x1;
- return reinterpret_cast<uint32_t*>(code)[-1];
- }
-
- bool IsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uintptr_t code = reinterpret_cast<uintptr_t>(GetCode());
- if (code == 0) {
- return pc == 0;
- }
- /*
- * During a stack walk, a return PC may point to the end of the code + 1
- * (in the case that the last instruction is a call that isn't expected to
- * return. Thus, we check <= code + GetCodeSize().
- */
- return (code <= pc && pc <= code + GetCodeSize());
- }
-
- void AssertPcIsWithinCode(uintptr_t pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- uint32_t GetOatCodeOffset() const {
- DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetCode());
- }
-
- void SetOatCodeOffset(uint32_t code_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetCode(reinterpret_cast<void*>(code_offset));
- }
-
- static MemberOffset GetCodeOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, code_);
- }
-
- const uint32_t* GetMappingTable() const {
- const uint32_t* map = GetMappingTableRaw();
- if (map == NULL) {
- return map;
- }
- return map + 1;
- }
-
- uint32_t GetPcToDexMappingTableLength() const {
- const uint32_t* map = GetMappingTableRaw();
- if (map == NULL) {
- return 0;
- }
- return map[2];
- }
-
- const uint32_t* GetPcToDexMappingTable() const {
- const uint32_t* map = GetMappingTableRaw();
- if (map == NULL) {
- return map;
- }
- return map + 3;
- }
-
-
- uint32_t GetDexToPcMappingTableLength() const {
- const uint32_t* map = GetMappingTableRaw();
- if (map == NULL) {
- return 0;
- }
- return map[1] - map[2];
- }
-
- const uint32_t* GetDexToPcMappingTable() const {
- const uint32_t* map = GetMappingTableRaw();
- if (map == NULL) {
- return map;
- }
- return map + 3 + map[2];
- }
-
-
- const uint32_t* GetMappingTableRaw() const {
- return GetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_), false);
- }
-
- void SetMappingTable(const uint32_t* mapping_table) {
- SetFieldPtr<const uint32_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, mapping_table_),
- mapping_table, false);
- }
-
- uint32_t GetOatMappingTableOffset() const {
- DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetMappingTableRaw());
- }
-
- void SetOatMappingTableOffset(uint32_t mapping_table_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetMappingTable(reinterpret_cast<const uint32_t*>(mapping_table_offset));
- }
-
- // Callers should wrap the uint16_t* in a VmapTable instance for convenient access.
- const uint16_t* GetVmapTableRaw() const {
- return GetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), false);
- }
-
- void SetVmapTable(const uint16_t* vmap_table) {
- SetFieldPtr<const uint16_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, vmap_table_), vmap_table, false);
- }
-
- uint32_t GetOatVmapTableOffset() const {
- DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetVmapTableRaw());
- }
-
- void SetOatVmapTableOffset(uint32_t vmap_table_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetVmapTable(reinterpret_cast<uint16_t*>(vmap_table_offset));
- }
-
- const uint8_t* GetNativeGcMap() const {
- return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), false);
- }
- void SetNativeGcMap(const uint8_t* data) {
- SetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_gc_map_), data,
- false);
- }
-
- // When building the oat need a convenient place to stuff the offset of the native GC map.
- void SetOatNativeGcMapOffset(uint32_t gc_map_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
- }
-
- uint32_t GetOatNativeGcMapOffset() const {
- DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetNativeGcMap());
- }
-
- size_t GetFrameSizeInBytes() const {
- DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
- size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_), false);
- DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
- return result;
- }
-
- void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) {
- DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
- SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, frame_size_in_bytes_),
- new_frame_size_in_bytes, false);
- }
-
- size_t GetReturnPcOffsetInBytes() const {
- return GetFrameSizeInBytes() - kPointerSize;
- }
-
- bool IsRegistered() const;
-
- void RegisterNative(Thread* self, const void* native_method)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void UnregisterNative(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static MemberOffset NativeMethodOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, native_method_);
- }
-
- const void* GetNativeMethod() const {
- return reinterpret_cast<const void*>(GetField32(NativeMethodOffset(), false));
- }
-
- // Native to managed invocation stub entry point
- InvokeStub* GetInvokeStub() const {
- InvokeStub* result = GetFieldPtr<InvokeStub*>(
- OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_), false);
- // TODO: DCHECK(result != NULL); should be ahead of time compiled
- return result;
- }
-
- void SetInvokeStub(InvokeStub* invoke_stub) {
- SetFieldPtr<InvokeStub*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_),
- invoke_stub, false);
- }
-
- uint32_t GetInvokeStubSize() const {
- uintptr_t invoke_stub = reinterpret_cast<uintptr_t>(GetInvokeStub());
- if (invoke_stub == 0) {
- return 0;
- }
- // TODO: make this Thumb2 specific
- invoke_stub &= ~0x1;
- return reinterpret_cast<const uint32_t*>(invoke_stub)[-1];
- }
-
- uint32_t GetOatInvokeStubOffset() const {
- DCHECK(!Runtime::Current()->IsStarted());
- return reinterpret_cast<uint32_t>(GetInvokeStub());
- }
-
- void SetOatInvokeStubOffset(uint32_t invoke_stub_offset) {
- DCHECK(!Runtime::Current()->IsStarted());
- SetInvokeStub(reinterpret_cast<InvokeStub*>(invoke_stub_offset));
- }
-
- static MemberOffset GetInvokeStubOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, invoke_stub_);
- }
-
- static MemberOffset GetMethodIndexOffset() {
- return OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_);
- }
-
- uint32_t GetCoreSpillMask() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), false);
- }
-
- void SetCoreSpillMask(uint32_t core_spill_mask) {
- // Computed during compilation
- SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, core_spill_mask_), core_spill_mask, false);
- }
-
- uint32_t GetFpSpillMask() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), false);
- }
-
- void SetFpSpillMask(uint32_t fp_spill_mask) {
- // Computed during compilation
- SetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, fp_spill_mask_), fp_spill_mask, false);
- }
-
- // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal
- // conventions for a method of managed code. Returns false for Proxy methods.
- bool IsRuntimeMethod() const {
- return GetDexMethodIndex() == DexFile::kDexNoIndex16;
- }
-
- // Is this a hand crafted method used for something like describing callee saves?
- bool IsCalleeSaveMethod() const {
- if (!IsRuntimeMethod()) {
- return false;
- }
- Runtime* runtime = Runtime::Current();
- bool result = false;
- for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
- if (this == runtime->GetCalleeSaveMethod(Runtime::CalleeSaveType(i))) {
- result = true;
- break;
- }
- }
- return result;
- }
-
- bool IsResolutionMethod() const {
- bool result = this == Runtime::Current()->GetResolutionMethod();
- // Check that if we do think it is phony it looks like the resolution method
- DCHECK(!result || GetDexMethodIndex() == DexFile::kDexNoIndex16);
- return result;
- }
-
- uintptr_t NativePcOffset(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Converts a native PC to a dex PC.
- uint32_t ToDexPc(const uintptr_t pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Converts a dex PC to a native PC.
- uintptr_t ToNativePc(const uint32_t dex_pc) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Converts a dex PC to the first corresponding safepoint PC.
- uintptr_t ToFirstNativeSafepointPc(const uint32_t dex_pc)
- const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Find the catch block for the given exception type and dex_pc
- uint32_t FindCatchBlock(Class* exception_type, uint32_t dex_pc) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static void SetClasses(Class* java_lang_reflect_Constructor, Class* java_lang_reflect_Method);
-
- static Class* GetConstructorClass() {
- return java_lang_reflect_Constructor_;
- }
-
- static Class* GetMethodClass() {
- return java_lang_reflect_Method_;
- }
-
- static void ResetClasses();
-
- protected:
- // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- // The class we are a part of
- Class* declaring_class_;
-
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<StaticStorageBase>* dex_cache_initialized_static_storage_;
-
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<AbstractMethod>* dex_cache_resolved_methods_;
-
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<Class>* dex_cache_resolved_types_;
-
- // short cuts to declaring_class_->dex_cache_ member for fast compiled code access
- ObjectArray<String>* dex_cache_strings_;
-
- // Access flags; low 16 bits are defined by spec.
- uint32_t access_flags_;
-
- // Compiled code associated with this method for callers from managed code.
- // May be compiled managed code or a bridge for invoking a native method.
- const void* code_;
-
- // Offset to the CodeItem.
- uint32_t code_item_offset_;
-
- // Architecture-dependent register spill mask
- uint32_t core_spill_mask_;
-
- // Architecture-dependent register spill mask
- uint32_t fp_spill_mask_;
-
- // Total size in bytes of the frame
- size_t frame_size_in_bytes_;
-
- // Garbage collection map of native PC offsets to reference bitmaps.
- const uint8_t* native_gc_map_;
-
- // Native invocation stub entry point for calling from native to managed code.
- InvokeStub* invoke_stub_;
-
- // Mapping from native pc to dex pc
- const uint32_t* mapping_table_;
-
- // Index into method_ids of the dex file associated with this method
- uint32_t method_dex_index_;
-
- // For concrete virtual methods, this is the offset of the method in Class::vtable_.
- //
- // For abstract methods in an interface class, this is the offset of the method in
- // "iftable_->Get(n)->GetMethodArray()".
- //
- // For static and direct methods this is the index in the direct methods table.
- uint32_t method_index_;
-
- // The target native method registered with this method
- const void* native_method_;
-
- // When a register is promoted into a register, the spill mask holds which registers hold dex
- // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
- // is vmap_table_[N]. vmap_table_[0] holds the length of the table.
- const uint16_t* vmap_table_;
-
- static Class* java_lang_reflect_Constructor_;
- static Class* java_lang_reflect_Method_;
-
- friend class ImageWriter; // for relocating code_ and invoke_stub_
- friend struct AbstractMethodOffsets; // for verifying offset information
- friend struct ConstructorMethodOffsets; // for verifying offset information
- friend struct MethodOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod);
-};
-
-class MANAGED Method : public AbstractMethod {
-
-};
-
-class MANAGED Constructor : public AbstractMethod {
-
-};
-
-class MANAGED Array : public Object {
- public:
- // A convenience for code that doesn't know the component size,
- // and doesn't want to have to work it out itself.
- static Array* Alloc(Thread* self, Class* array_class, int32_t component_count)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static Array* Alloc(Thread* self, Class* array_class, int32_t component_count,
- size_t component_size)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static Array* CreateMultiArray(Thread* self, Class* element_class, IntArray* dimensions)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- size_t SizeOf() const;
-
- int32_t GetLength() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
- }
-
- void SetLength(int32_t length) {
- CHECK_GE(length, 0);
- SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false);
- }
-
- static MemberOffset LengthOffset() {
- return OFFSET_OF_OBJECT_MEMBER(Array, length_);
- }
-
- static MemberOffset DataOffset(size_t component_size) {
- if (component_size != sizeof(int64_t)) {
- return OFFSET_OF_OBJECT_MEMBER(Array, first_element_);
- } else {
- // Align longs and doubles.
- return MemberOffset(OFFSETOF_MEMBER(Array, first_element_) + 4);
- }
- }
-
- void* GetRawData(size_t component_size) {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value();
- return reinterpret_cast<void*>(data);
- }
-
- const void* GetRawData(size_t component_size) const {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(component_size).Int32Value();
- return reinterpret_cast<const void*>(data);
- }
-
- protected:
- bool IsValidIndex(int32_t index) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (UNLIKELY(index < 0 || index >= GetLength())) {
- return ThrowArrayIndexOutOfBoundsException(index);
- }
- return true;
- }
-
- protected:
- bool ThrowArrayIndexOutOfBoundsException(int32_t index) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool ThrowArrayStoreException(Object* object) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- private:
- // The number of array elements.
- int32_t length_;
- // Marker for the data (used by generated code)
- uint32_t first_element_[0];
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(Array);
-};
-
-template<class T>
-class MANAGED ObjectArray : public Array {
- public:
- static ObjectArray<T>* Alloc(Thread* self, Class* object_array_class, int32_t length)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- T* Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void Set(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Set element without bound and element type checks, to be used in limited
- // circumstances, such as during boot image writing
- void SetWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Set element without bound and element type checks, to be used in limited circumstances, such
- // as during boot image writing. Does not do write barrier.
- void SetPtrWithoutChecks(int32_t i, T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- T* GetWithoutChecks(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static void Copy(const ObjectArray<T>* src, int src_pos,
- ObjectArray<T>* dst, int dst_pos,
- size_t length)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- ObjectArray<T>* CopyOf(Thread* self, int32_t new_length)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray);
-};
-
-template<class T>
-ObjectArray<T>* ObjectArray<T>::Alloc(Thread* self, Class* object_array_class, int32_t length) {
- Array* array = Array::Alloc(self, object_array_class, length, sizeof(Object*));
- if (UNLIKELY(array == NULL)) {
- return NULL;
- } else {
- return array->AsObjectArray<T>();
- }
-}
-
-template<class T>
-inline T* ObjectArray<T>::Get(int32_t i) const {
- if (UNLIKELY(!IsValidIndex(i))) {
- return NULL;
- }
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- return GetFieldObject<T*>(data_offset, false);
-}
-
-template<class T>
-ObjectArray<T>* ObjectArray<T>::CopyOf(Thread* self, int32_t new_length) {
- ObjectArray<T>* new_array = Alloc(self, GetClass(), new_length);
- Copy(this, 0, new_array, 0, std::min(GetLength(), new_length));
- return new_array;
-}
-
-class MANAGED IfTable : public ObjectArray<Object> {
- public:
- Class* GetInterface(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Class* interface = Get((i * kMax) + kInterface)->AsClass();
- DCHECK(interface != NULL);
- return interface;
- }
-
- void SetInterface(int32_t i, Class* interface) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- ObjectArray<AbstractMethod>* GetMethodArray(int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<AbstractMethod>* method_array =
- down_cast<ObjectArray<AbstractMethod>*>(Get((i * kMax) + kMethodArray));
- DCHECK(method_array != NULL);
- return method_array;
- }
-
- size_t GetMethodArrayCount(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<AbstractMethod>* method_array =
- down_cast<ObjectArray<AbstractMethod>*>(Get((i * kMax) + kMethodArray));
- if (method_array == NULL) {
- return 0;
- }
- return method_array->GetLength();
- }
-
- void SetMethodArray(int32_t i, ObjectArray<AbstractMethod>* new_ma)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_ma != NULL);
- DCHECK(Get((i * kMax) + kMethodArray) == NULL);
- Set((i * kMax) + kMethodArray, new_ma);
- }
-
- size_t Count() const {
- return GetLength() / kMax;
- }
-
- enum {
- // Points to the interface class.
- kInterface = 0,
- // Method pointers into the vtable, allow fast map from interface method index to concrete
- // instance method.
- kMethodArray = 1,
- kMax = 2,
- };
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(IfTable);
-};
-
-// Type for the InitializedStaticStorage table. Currently the Class
-// provides the static storage. However, this might change to an Array
-// to improve image sharing, so we use this type to avoid assumptions
-// on the current storage.
-class MANAGED StaticStorageBase : public Object {
-};
-
-// C++ mirror of java.lang.Class
-class MANAGED Class : public StaticStorageBase {
- public:
- // Class Status
- //
- // kStatusNotReady: If a Class cannot be found in the class table by
- // FindClass, it allocates an new one with AllocClass in the
- // kStatusNotReady and calls LoadClass. Note if it does find a
- // class, it may not be kStatusResolved and it will try to push it
- // forward toward kStatusResolved.
- //
- // kStatusIdx: LoadClass populates with Class with information from
- // the DexFile, moving the status to kStatusIdx, indicating that the
- // Class value in super_class_ has not been populated. The new Class
- // can then be inserted into the classes table.
- //
- // kStatusLoaded: After taking a lock on Class, the ClassLinker will
- // attempt to move a kStatusIdx class forward to kStatusLoaded by
- // using ResolveClass to initialize the super_class_ and ensuring the
- // interfaces are resolved.
- //
- // kStatusResolved: Still holding the lock on Class, the ClassLinker
- // shows linking is complete and fields of the Class populated by making
- // it kStatusResolved. Java allows circularities of the form where a super
- // class has a field that is of the type of the sub class. We need to be able
- // to fully resolve super classes while resolving types for fields.
- //
- // kStatusRetryVerificationAtRuntime: The verifier sets a class to
- // this state if it encounters a soft failure at compile time. This
- // often happens when there are unresolved classes in other dex
- // files, and this status marks a class as needing to be verified
- // again at runtime.
- //
- // TODO: Explain the other states
- enum Status {
- kStatusError = -1,
- kStatusNotReady = 0,
- kStatusIdx = 1, // Loaded, DEX idx in super_class_type_idx_ and interfaces_type_idx_.
- kStatusLoaded = 2, // DEX idx values resolved.
- kStatusResolved = 3, // Part of linking.
- kStatusVerifying = 4, // In the process of being verified.
- kStatusRetryVerificationAtRuntime = 5, // Compile time verification failed, retry at runtime.
- kStatusVerifyingAtRuntime = 6, // Retrying verification at runtime.
- kStatusVerified = 7, // Logically part of linking; done pre-init.
- kStatusInitializing = 8, // Class init in progress.
- kStatusInitialized = 9, // Ready to go.
- };
-
- Status GetStatus() const {
- DCHECK_EQ(sizeof(Status), sizeof(uint32_t));
- return static_cast<Status>(GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), false));
- }
-
- void SetStatus(Status new_status) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Returns true if the class has failed to link.
- bool IsErroneous() const {
- return GetStatus() == kStatusError;
- }
-
- // Returns true if the class has been loaded.
- bool IsIdxLoaded() const {
- return GetStatus() >= kStatusIdx;
- }
-
- // Returns true if the class has been loaded.
- bool IsLoaded() const {
- return GetStatus() >= kStatusLoaded;
- }
-
- // Returns true if the class has been linked.
- bool IsResolved() const {
- return GetStatus() >= kStatusResolved;
- }
-
- // Returns true if the class was compile-time verified.
- bool IsCompileTimeVerified() const {
- return GetStatus() >= kStatusRetryVerificationAtRuntime;
- }
-
- // Returns true if the class has been verified.
- bool IsVerified() const {
- return GetStatus() >= kStatusVerified;
- }
-
- // Returns true if the class is initializing.
- bool IsInitializing() const {
- return GetStatus() >= kStatusInitializing;
- }
-
- // Returns true if the class is initialized.
- bool IsInitialized() const {
- return GetStatus() == kStatusInitialized;
- }
-
- uint32_t GetAccessFlags() const;
-
- void SetAccessFlags(uint32_t new_access_flags) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags, false);
- }
-
- // Returns true if the class is an interface.
- bool IsInterface() const {
- return (GetAccessFlags() & kAccInterface) != 0;
- }
-
- // Returns true if the class is declared public.
- bool IsPublic() const {
- return (GetAccessFlags() & kAccPublic) != 0;
- }
-
- // Returns true if the class is declared final.
- bool IsFinal() const {
- return (GetAccessFlags() & kAccFinal) != 0;
- }
-
- bool IsFinalizable() const {
- return (GetAccessFlags() & kAccClassIsFinalizable) != 0;
- }
-
- void SetFinalizable() {
- uint32_t flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
- SetAccessFlags(flags | kAccClassIsFinalizable);
- }
-
- // Returns true if the class is abstract.
- bool IsAbstract() const {
- return (GetAccessFlags() & kAccAbstract) != 0;
- }
-
- // Returns true if the class is an annotation.
- bool IsAnnotation() const {
- return (GetAccessFlags() & kAccAnnotation) != 0;
- }
-
- // Returns true if the class is synthetic.
- bool IsSynthetic() const {
- return (GetAccessFlags() & kAccSynthetic) != 0;
- }
-
- bool IsReferenceClass() const {
- return (GetAccessFlags() & kAccClassIsReference) != 0;
- }
-
- bool IsWeakReferenceClass() const {
- return (GetAccessFlags() & kAccClassIsWeakReference) != 0;
- }
-
- bool IsSoftReferenceClass() const {
- return (GetAccessFlags() & kAccReferenceFlagsMask) == kAccClassIsReference;
- }
-
- bool IsFinalizerReferenceClass() const {
- return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0;
- }
-
- bool IsPhantomReferenceClass() const {
- return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
- }
-
-
- String* GetName() const; // Returns the cached name.
- void SetName(String* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Sets the cached name.
- // Computes the name, then sets the cached value.
- String* ComputeName() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsProxyClass() const {
- // Read access flags without using getter as whether something is a proxy can be check in
- // any loaded state
- // TODO: switch to a check if the super class is java.lang.reflect.Proxy?
- uint32_t access_flags = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
- return (access_flags & kAccClassIsProxy) != 0;
- }
-
- Primitive::Type GetPrimitiveType() const {
- DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
- return static_cast<Primitive::Type>(
- GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
- }
-
- void SetPrimitiveType(Primitive::Type new_type) {
- DCHECK_EQ(sizeof(Primitive::Type), sizeof(int32_t));
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type, false);
- }
-
- // Returns true if the class is a primitive type.
- bool IsPrimitive() const {
- return GetPrimitiveType() != Primitive::kPrimNot;
- }
-
- bool IsPrimitiveBoolean() const {
- return GetPrimitiveType() == Primitive::kPrimBoolean;
- }
-
- bool IsPrimitiveByte() const {
- return GetPrimitiveType() == Primitive::kPrimByte;
- }
-
- bool IsPrimitiveChar() const {
- return GetPrimitiveType() == Primitive::kPrimChar;
- }
-
- bool IsPrimitiveShort() const {
- return GetPrimitiveType() == Primitive::kPrimShort;
- }
-
- bool IsPrimitiveInt() const {
- return GetPrimitiveType() == Primitive::kPrimInt;
- }
-
- bool IsPrimitiveLong() const {
- return GetPrimitiveType() == Primitive::kPrimLong;
- }
-
- bool IsPrimitiveFloat() const {
- return GetPrimitiveType() == Primitive::kPrimFloat;
- }
-
- bool IsPrimitiveDouble() const {
- return GetPrimitiveType() == Primitive::kPrimDouble;
- }
-
- bool IsPrimitiveVoid() const {
- return GetPrimitiveType() == Primitive::kPrimVoid;
- }
-
- bool IsPrimitiveArray() const {
- return IsArrayClass() && GetComponentType()->IsPrimitive();
- }
-
- // Depth of class from java.lang.Object
- size_t Depth() {
- size_t depth = 0;
- for (Class* klass = this; klass->GetSuperClass() != NULL; klass = klass->GetSuperClass()) {
- depth++;
- }
- return depth;
- }
-
- bool IsArrayClass() const {
- return GetComponentType() != NULL;
- }
-
- bool IsClassClass() const;
-
- bool IsStringClass() const;
-
- bool IsThrowableClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsFieldClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsMethodClass() const;
-
- Class* GetComponentType() const {
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), false);
- }
-
- void SetComponentType(Class* new_component_type) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(GetComponentType() == NULL);
- DCHECK(new_component_type != NULL);
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, component_type_), new_component_type, false);
- }
-
- size_t GetComponentSize() const {
- return Primitive::ComponentSize(GetComponentType()->GetPrimitiveType());
- }
-
- bool IsObjectClass() const {
- return !IsPrimitive() && GetSuperClass() == NULL;
- }
- bool IsInstantiable() const {
- return !IsPrimitive() && !IsInterface() && !IsAbstract();
- }
-
- bool IsObjectArrayClass() const {
- return GetComponentType() != NULL && !GetComponentType()->IsPrimitive();
- }
-
- // Creates a raw object instance but does not invoke the default constructor.
- Object* AllocObject(Thread* self) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool IsVariableSize() const {
- // Classes and arrays vary in size, and so the object_size_ field cannot
- // be used to get their instance size
- return IsClassClass() || IsArrayClass();
- }
-
- size_t SizeOf() const {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
- }
-
- size_t GetClassSize() const {
- DCHECK_EQ(sizeof(size_t), sizeof(uint32_t));
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
- }
-
- void SetClassSize(size_t new_class_size)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- size_t GetObjectSize() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(!IsVariableSize()) << " class=" << PrettyTypeOf(this);
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), false);
- CHECK_GE(result, sizeof(Object)) << " class=" << PrettyTypeOf(this);
- return result;
- }
-
- void SetObjectSize(size_t new_object_size) {
- DCHECK(!IsVariableSize());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size, false);
- }
-
- // Returns true if this class is in the same packages as that class.
- bool IsInSamePackage(const Class* that) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static bool IsInSamePackage(const StringPiece& descriptor1, const StringPiece& descriptor2);
-
- // Returns true if this class can access that class.
- bool CanAccess(Class* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return that->IsPublic() || this->IsInSamePackage(that);
- }
-
- // Can this class access a member in the provided class with the provided member access flags?
- // Note that access to the class isn't checked in case the declaring class is protected and the
- // method has been exposed by a public sub-class
- bool CanAccessMember(Class* access_to, uint32_t member_flags) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // Classes can access all of their own members
- if (this == access_to) {
- return true;
- }
- // Public members are trivially accessible
- if (member_flags & kAccPublic) {
- return true;
- }
- // Private members are trivially not accessible
- if (member_flags & kAccPrivate) {
- return false;
- }
- // Check for protected access from a sub-class, which may or may not be in the same package.
- if (member_flags & kAccProtected) {
- if (this->IsSubClass(access_to)) {
- return true;
- }
- }
- // Allow protected access from other classes in the same package.
- return this->IsInSamePackage(access_to);
- }
-
- bool IsSubClass(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Can src be assigned to this class? For example, String can be assigned to Object (by an
- // upcast), however, an Object cannot be assigned to a String as a potentially exception throwing
- // downcast would be necessary. Similarly for interfaces, a class that implements (or an interface
- // that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign
- // to themselves. Classes for primitive types may not assign to each other.
- bool IsAssignableFrom(const Class* src) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(src != NULL);
- if (this == src) {
- // Can always assign to things of the same type.
- return true;
- } else if (IsObjectClass()) {
- // Can assign any reference to java.lang.Object.
- return !src->IsPrimitive();
- } else if (IsInterface()) {
- return src->Implements(this);
- } else if (src->IsArrayClass()) {
- return IsAssignableFromArray(src);
- } else {
- return !src->IsInterface() && src->IsSubClass(this);
- }
- }
-
- Class* GetSuperClass() const {
- // Can only get super class for loaded classes (hack for when runtime is
- // initializing)
- DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded();
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
- }
-
- void SetSuperClass(Class *new_super_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // super class is assigned once, except during class linker initialization
- Class* old_super_class = GetFieldObject<Class*>(
- OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
- DCHECK(old_super_class == NULL || old_super_class == new_super_class);
- DCHECK(new_super_class != NULL);
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), new_super_class, false);
- }
-
- bool HasSuperClass() const {
- return GetSuperClass() != NULL;
- }
-
- static MemberOffset SuperClassOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Class, super_class_));
- }
-
- ClassLoader* GetClassLoader() const;
-
- void SetClassLoader(ClassLoader* new_cl) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static MemberOffset DexCacheOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Class, dex_cache_));
- }
-
- enum {
- kDumpClassFullDetail = 1,
- kDumpClassClassLoader = (1 << 1),
- kDumpClassInitialized = (1 << 2),
- };
-
- void DumpClass(std::ostream& os, int flags) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- DexCache* GetDexCache() const;
-
- void SetDexCache(DexCache* new_dex_cache) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- ObjectArray<AbstractMethod>* GetDirectMethods() const {
- DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<AbstractMethod>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
- }
-
- void SetDirectMethods(ObjectArray<AbstractMethod>* new_direct_methods)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<AbstractMethod>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false));
- DCHECK_NE(0, new_direct_methods->GetLength());
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_),
- new_direct_methods, false);
- }
-
- AbstractMethod* GetDirectMethod(int32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetDirectMethods()->Get(i);
- }
-
- void SetDirectMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
- ObjectArray<AbstractMethod>* direct_methods =
- GetFieldObject<ObjectArray<AbstractMethod>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
- direct_methods->Set(i, f);
- }
-
- // Returns the number of static, private, and constructor methods.
- size_t NumDirectMethods() const {
- return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
- }
-
- ObjectArray<AbstractMethod>* GetVirtualMethods() const {
- DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<AbstractMethod>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
- }
-
- void SetVirtualMethods(ObjectArray<AbstractMethod>* new_virtual_methods)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- // TODO: we reassign virtual methods to grow the table for miranda
- // methods.. they should really just be assigned once
- DCHECK_NE(0, new_virtual_methods->GetLength());
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_),
- new_virtual_methods, false);
- }
-
- // Returns the number of non-inherited virtual methods.
- size_t NumVirtualMethods() const {
- return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
- }
-
- AbstractMethod* GetVirtualMethod(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsResolved() || IsErroneous());
- return GetVirtualMethods()->Get(i);
- }
-
- AbstractMethod* GetVirtualMethodDuringLinking(uint32_t i) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(IsLoaded() || IsErroneous());
- return GetVirtualMethods()->Get(i);
- }
-
- void SetVirtualMethod(uint32_t i, AbstractMethod* f) // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<AbstractMethod>* virtual_methods =
- GetFieldObject<ObjectArray<AbstractMethod>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
- virtual_methods->Set(i, f);
- }
-
- ObjectArray<AbstractMethod>* GetVTable() const {
- DCHECK(IsResolved() || IsErroneous());
- return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
- }
-
- ObjectArray<AbstractMethod>* GetVTableDuringLinking() const {
- DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<AbstractMethod>*>(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
- }
-
- void SetVTable(ObjectArray<AbstractMethod>* new_vtable)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, vtable_), new_vtable, false);
- }
-
- static MemberOffset VTableOffset() {
- return OFFSET_OF_OBJECT_MEMBER(Class, vtable_);
- }
-
- // Given a method implemented by this class but potentially from a
- // super class, return the specific implementation
- // method for this class.
- AbstractMethod* FindVirtualMethodForVirtual(AbstractMethod* method)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(!method->GetDeclaringClass()->IsInterface());
- // The argument method may from a super class.
- // Use the index to a potentially overridden one for this instance's class.
- return GetVTable()->Get(method->GetMethodIndex());
- }
-
- // Given a method implemented by this class' super class, return the specific implementation
- // method for this class.
- AbstractMethod* FindVirtualMethodForSuper(AbstractMethod* method)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(!method->GetDeclaringClass()->IsInterface());
- return GetSuperClass()->GetVTable()->Get(method->GetMethodIndex());
- }
-
- // Given a method implemented by this class, but potentially from a
- // super class or interface, return the specific implementation
- // method for this class.
- AbstractMethod* FindVirtualMethodForInterface(AbstractMethod* method)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindInterfaceMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindVirtualMethodForVirtualOrInterface(AbstractMethod* method)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (method->IsDirect()) {
- return method;
- }
- if (method->GetDeclaringClass()->IsInterface()) {
- return FindVirtualMethodForInterface(method);
- }
- return FindVirtualMethodForVirtual(method);
- }
-
- AbstractMethod* FindDeclaredVirtualMethod(const StringPiece& name, const StringPiece& signature) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindDeclaredVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindVirtualMethod(const StringPiece& name, const StringPiece& descriptor) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindVirtualMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindDeclaredDirectMethod(const StringPiece& name, const StringPiece& signature) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindDeclaredDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindDirectMethod(const StringPiece& name, const StringPiece& signature) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- AbstractMethod* FindDirectMethod(const DexCache* dex_cache, uint32_t dex_method_idx) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- int32_t GetIfTableCount() const {
- IfTable* iftable = GetIfTable();
- if (iftable == NULL) {
- return 0;
- }
- return iftable->Count();
- }
-
- IfTable* GetIfTable() const {
- return GetFieldObject<IfTable*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
- }
-
- void SetIfTable(IfTable* new_iftable)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, iftable_), new_iftable, false);
- }
-
- // Get instance fields of the class (See also GetSFields).
- ObjectArray<Field>* GetIFields() const {
- DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
- }
-
- void SetIFields(ObjectArray<Field>* new_ifields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false));
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, ifields_), new_ifields, false);
- }
-
- size_t NumInstanceFields() const {
- return (GetIFields() != NULL) ? GetIFields()->GetLength() : 0;
- }
-
- Field* GetInstanceField(uint32_t i) const // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
- DCHECK_NE(NumInstanceFields(), 0U);
- return GetIFields()->Get(i);
- }
-
- void SetInstanceField(uint32_t i, Field* f) // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_){
- ObjectArray<Field>* ifields= GetFieldObject<ObjectArray<Field>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
- ifields->Set(i, f);
- }
-
- // Returns the number of instance fields containing reference types.
- size_t NumReferenceInstanceFields() const {
- DCHECK(IsResolved() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
- }
-
- size_t NumReferenceInstanceFieldsDuringLinking() const {
- DCHECK(IsLoaded() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
- }
-
- void SetNumReferenceInstanceFields(size_t new_num) {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), new_num, false);
- }
-
- uint32_t GetReferenceInstanceOffsets() const {
- DCHECK(IsResolved() || IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
- }
-
- void SetReferenceInstanceOffsets(uint32_t new_reference_offsets);
-
- // Beginning of static field data
- static MemberOffset FieldsOffset() {
- return OFFSET_OF_OBJECT_MEMBER(Class, fields_);
- }
-
- // Returns the number of static fields containing reference types.
- size_t NumReferenceStaticFields() const {
- DCHECK(IsResolved() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
- }
-
- size_t NumReferenceStaticFieldsDuringLinking() const {
- DCHECK(IsLoaded() || IsErroneous());
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
- }
-
- void SetNumReferenceStaticFields(size_t new_num) {
- DCHECK_EQ(sizeof(size_t), sizeof(int32_t));
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), new_num, false);
- }
-
- // Gets the static fields of the class.
- ObjectArray<Field>* GetSFields() const {
- DCHECK(IsLoaded() || IsErroneous());
- return GetFieldObject<ObjectArray<Field>*>(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
- }
-
- void SetSFields(ObjectArray<Field>* new_sfields) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(NULL == GetFieldObject<ObjectArray<Field>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false));
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, sfields_), new_sfields, false);
- }
-
- size_t NumStaticFields() const {
- return (GetSFields() != NULL) ? GetSFields()->GetLength() : 0;
- }
-
- Field* GetStaticField(uint32_t i) const // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return GetSFields()->Get(i);
- }
-
- void SetStaticField(uint32_t i, Field* f) // TODO: uint16_t
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- ObjectArray<Field>* sfields= GetFieldObject<ObjectArray<Field>*>(
- OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
- sfields->Set(i, f);
- }
-
- uint32_t GetReferenceStaticOffsets() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_), false);
- }
-
- void SetReferenceStaticOffsets(uint32_t new_reference_offsets);
-
- // Find a static or instance field using the JLS resolution order
- Field* FindField(const StringPiece& name, const StringPiece& type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Finds the given instance field in this class or a superclass.
- Field* FindInstanceField(const StringPiece& name, const StringPiece& type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Finds the given instance field in this class or a superclass, only searches classes that
- // have the same dex cache.
- Field* FindInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- Field* FindDeclaredInstanceField(const StringPiece& name, const StringPiece& type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- Field* FindDeclaredInstanceField(const DexCache* dex_cache, uint32_t dex_field_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Finds the given static field in this class or a superclass.
- Field* FindStaticField(const StringPiece& name, const StringPiece& type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Finds the given static field in this class or superclass, only searches classes that
- // have the same dex cache.
- Field* FindStaticField(const DexCache* dex_cache, uint32_t dex_field_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- Field* FindDeclaredStaticField(const StringPiece& name, const StringPiece& type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- Field* FindDeclaredStaticField(const DexCache* dex_cache, uint32_t dex_field_idx)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- pid_t GetClinitThreadId() const {
- DCHECK(IsIdxLoaded() || IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), false);
- }
-
- void SetClinitThreadId(pid_t new_clinit_thread_id) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), new_clinit_thread_id, false);
- }
-
- Class* GetVerifyErrorClass() const {
- // DCHECK(IsErroneous());
- return GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), false);
- }
-
- uint16_t GetDexTypeIndex() const {
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), false);
- }
-
- void SetDexTypeIndex(uint16_t type_idx) {
- SetField32(OFFSET_OF_OBJECT_MEMBER(Class, dex_type_idx_), type_idx, false);
- }
-
- static Class* GetJavaLangClass() {
- DCHECK(java_lang_Class_ != NULL);
- return java_lang_Class_;
- }
-
- // Can't call this SetClass or else gets called instead of Object::SetClass in places.
- static void SetClassClass(Class* java_lang_Class);
- static void ResetClass();
-
- private:
- void SetVerifyErrorClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(klass != NULL) << PrettyClass(this);
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_), klass, false);
- }
-
- bool Implements(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsArrayAssignableFromArray(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsAssignableFromArray(const Class* klass) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // defining class loader, or NULL for the "bootstrap" system loader
- ClassLoader* class_loader_;
-
- // For array classes, the component class object for instanceof/checkcast
- // (for String[][][], this will be String[][]). NULL for non-array classes.
- Class* component_type_;
-
- // DexCache of resolved constant pool entries (will be NULL for classes generated by the
- // runtime such as arrays and primitive classes).
- DexCache* dex_cache_;
-
- // static, private, and <init> methods
- ObjectArray<AbstractMethod>* direct_methods_;
-
- // instance fields
- //
- // These describe the layout of the contents of an Object.
- // Note that only the fields directly declared by this class are
- // listed in ifields; fields declared by a superclass are listed in
- // the superclass's Class.ifields.
- //
- // All instance fields that refer to objects are guaranteed to be at
- // the beginning of the field list. num_reference_instance_fields_
- // specifies the number of reference fields.
- ObjectArray<Field>* ifields_;
-
- // The interface table (iftable_) contains pairs of a interface class and an array of the
- // interface methods. There is one pair per interface supported by this class. That means one
- // pair for each interface we support directly, indirectly via superclass, or indirectly via a
- // superinterface. This will be null if neither we nor our superclass implement any interfaces.
- //
- // Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()".
- // Invoke faceObj.blah(), where "blah" is part of the Face interface. We can't easily use a
- // single vtable.
- //
- // For every interface a concrete class implements, we create an array of the concrete vtable_
- // methods for the methods in the interface.
- IfTable* iftable_;
-
- // descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
- String* name_;
-
- // Static fields
- ObjectArray<Field>* sfields_;
-
- // The superclass, or NULL if this is java.lang.Object, an interface or primitive type.
- Class* super_class_;
-
- // If class verify fails, we must return same error on subsequent tries.
- Class* verify_error_class_;
-
- // virtual methods defined in this class; invoked through vtable
- ObjectArray<AbstractMethod>* virtual_methods_;
-
- // Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is
- // copied in, and virtual methods from our class either replace those from the super or are
- // appended. For abstract classes, methods may be created in the vtable that aren't in
- // virtual_ methods_ for miranda methods.
- ObjectArray<AbstractMethod>* vtable_;
-
- // access flags; low 16 bits are defined by VM spec
- uint32_t access_flags_;
-
- // Total size of the Class instance; used when allocating storage on gc heap.
- // See also object_size_.
- size_t class_size_;
-
- // tid used to check for recursive <clinit> invocation
- pid_t clinit_thread_id_;
-
- // type index from dex file
- // TODO: really 16bits
- uint32_t dex_type_idx_;
-
- // number of instance fields that are object refs
- size_t num_reference_instance_fields_;
-
- // number of static fields that are object refs
- size_t num_reference_static_fields_;
-
- // Total object size; used when allocating storage on gc heap.
- // (For interfaces and abstract classes this will be zero.)
- // See also class_size_.
- size_t object_size_;
-
- // primitive type value, or Primitive::kPrimNot (0); set for generated prim classes
- Primitive::Type primitive_type_;
-
- // Bitmap of offsets of ifields.
- uint32_t reference_instance_offsets_;
-
- // Bitmap of offsets of sfields.
- uint32_t reference_static_offsets_;
-
- // state of class initialization
- Status status_;
-
- // TODO: ?
- // initiating class loader list
- // NOTE: for classes with low serialNumber, these are unused, and the
- // values are kept in a table in gDvm.
- // InitiatingLoaderList initiating_loader_list_;
-
- // Location of first static field.
- uint32_t fields_[0];
-
- // java.lang.Class
- static Class* java_lang_Class_;
-
- friend struct ClassOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(Class);
-};
-
-std::ostream& operator<<(std::ostream& os, const Class::Status& rhs);
-
-inline void Object::SetClass(Class* new_klass) {
- // new_klass may be NULL prior to class linker initialization
- // We don't mark the card since the class is guaranteed to be referenced from another location.
- // Proxy classes are held live by the class loader, and other classes are roots of the class
- // linker.
- SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false, false);
-}
-
-inline bool Object::InstanceOf(const Class* klass) const {
- DCHECK(klass != NULL);
- DCHECK(GetClass() != NULL);
- return klass->IsAssignableFrom(GetClass());
-}
-
-inline bool Object::IsClass() const {
- Class* java_lang_Class = GetClass()->GetClass();
- return GetClass() == java_lang_Class;
-}
-
-inline bool Object::IsObjectArray() const {
- return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
-}
-
-template<class T>
-inline ObjectArray<T>* Object::AsObjectArray() {
- DCHECK(IsObjectArray());
- return down_cast<ObjectArray<T>*>(this);
-}
-
-template<class T>
-inline const ObjectArray<T>* Object::AsObjectArray() const {
- DCHECK(IsObjectArray());
- return down_cast<const ObjectArray<T>*>(this);
-}
-
-inline bool Object::IsArrayInstance() const {
- return GetClass()->IsArrayClass();
-}
-
-inline bool Object::IsField() const {
- return GetClass()->IsFieldClass();
-}
-
-inline bool Object::IsMethod() const {
- return GetClass()->IsMethodClass();
-}
-
-inline bool Object::IsReferenceInstance() const {
- return GetClass()->IsReferenceClass();
-}
-
-inline bool Object::IsWeakReferenceInstance() const {
- return GetClass()->IsWeakReferenceClass();
-}
-
-inline bool Object::IsSoftReferenceInstance() const {
- return GetClass()->IsSoftReferenceClass();
-}
-
-inline bool Object::IsFinalizerReferenceInstance() const {
- return GetClass()->IsFinalizerReferenceClass();
-}
-
-inline bool Object::IsPhantomReferenceInstance() const {
- return GetClass()->IsPhantomReferenceClass();
-}
-
-inline size_t Object::SizeOf() const {
- size_t result;
- if (IsArrayInstance()) {
- result = AsArray()->SizeOf();
- } else if (IsClass()) {
- result = AsClass()->SizeOf();
- } else {
- result = GetClass()->GetObjectSize();
- }
- DCHECK(!IsField() || result == sizeof(Field));
- DCHECK(!IsMethod() || result == sizeof(AbstractMethod));
- return result;
-}
-
-inline Class* Field::GetDeclaringClass() const {
- Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), false);
- DCHECK(result != NULL);
- DCHECK(result->IsLoaded() || result->IsErroneous());
- return result;
-}
-
-inline void Field::SetDeclaringClass(Class *new_declaring_class) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), new_declaring_class, false);
-}
-
-inline Class* AbstractMethod::GetDeclaringClass() const {
- Class* result = GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), false);
- DCHECK(result != NULL) << this;
- DCHECK(result->IsIdxLoaded() || result->IsErroneous()) << this;
- return result;
-}
-
-inline void AbstractMethod::SetDeclaringClass(Class *new_declaring_class) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, declaring_class_), new_declaring_class, false);
-}
-
-inline size_t Array::SizeOf() const {
- // This is safe from overflow because the array was already allocated, so we know it's sane.
- size_t component_size = GetClass()->GetComponentSize();
- int32_t component_count = GetLength();
- size_t header_size = sizeof(Object) + (component_size == sizeof(int64_t) ? 8 : 4);
- size_t data_size = component_count * component_size;
- return header_size + data_size;
-}
-
-template<class T>
-void ObjectArray<T>::Set(int32_t i, T* object) {
- if (LIKELY(IsValidIndex(i))) {
- if (object != NULL) {
- Class* element_class = GetClass()->GetComponentType();
- if (UNLIKELY(!object->InstanceOf(element_class))) {
- ThrowArrayStoreException(object);
- return;
- }
- }
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- SetFieldObject(data_offset, object, false);
- }
-}
-
-template<class T>
-void ObjectArray<T>::SetWithoutChecks(int32_t i, T* object) {
- DCHECK(IsValidIndex(i));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- SetFieldObject(data_offset, object, false);
-}
-
-template<class T>
-void ObjectArray<T>::SetPtrWithoutChecks(int32_t i, T* object) {
- DCHECK(IsValidIndex(i));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- SetFieldPtr(data_offset, object, false);
-}
-
-template<class T>
-T* ObjectArray<T>::GetWithoutChecks(int32_t i) const {
- DCHECK(IsValidIndex(i));
- MemberOffset data_offset(DataOffset(sizeof(Object*)).Int32Value() + i * sizeof(Object*));
- return GetFieldObject<T*>(data_offset, false);
-}
-
-template<class T>
-void ObjectArray<T>::Copy(const ObjectArray<T>* src, int src_pos,
- ObjectArray<T>* dst, int dst_pos,
- size_t length) {
- if (src->IsValidIndex(src_pos) &&
- src->IsValidIndex(src_pos+length-1) &&
- dst->IsValidIndex(dst_pos) &&
- dst->IsValidIndex(dst_pos+length-1)) {
- MemberOffset src_offset(DataOffset(sizeof(Object*)).Int32Value() + src_pos * sizeof(Object*));
- MemberOffset dst_offset(DataOffset(sizeof(Object*)).Int32Value() + dst_pos * sizeof(Object*));
- Class* array_class = dst->GetClass();
- Heap* heap = Runtime::Current()->GetHeap();
- if (array_class == src->GetClass()) {
- // No need for array store checks if arrays are of the same type
- for (size_t i = 0; i < length; i++) {
- Object* object = src->GetFieldObject<Object*>(src_offset, false);
- heap->VerifyObject(object);
- // directly set field, we do a bulk write barrier at the end
- dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true);
- src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
- dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
- }
- } else {
- Class* element_class = array_class->GetComponentType();
- CHECK(!element_class->IsPrimitive());
- for (size_t i = 0; i < length; i++) {
- Object* object = src->GetFieldObject<Object*>(src_offset, false);
- if (object != NULL && !object->InstanceOf(element_class)) {
- dst->ThrowArrayStoreException(object);
- return;
- }
- heap->VerifyObject(object);
- // directly set field, we do a bulk write barrier at the end
- dst->SetField32(dst_offset, reinterpret_cast<uint32_t>(object), false, true);
- src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
- dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
- }
- }
- heap->WriteBarrierArray(dst, dst_pos, length);
- }
-}
-
-inline void IfTable::SetInterface(int32_t i, Class* interface) {
- DCHECK(interface != NULL);
- DCHECK(interface->IsInterface());
- DCHECK(Get((i * kMax) + kInterface) == NULL);
- Set((i * kMax) + kInterface, interface);
-}
-
-class MANAGED ClassClass : public Class {
- private:
- int32_t padding_;
- int64_t serialVersionUID_;
- friend struct ClassClassOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(ClassClass);
-};
-
-class MANAGED StringClass : public Class {
- private:
- CharArray* ASCII_;
- Object* CASE_INSENSITIVE_ORDER_;
- uint32_t REPLACEMENT_CHAR_;
- int64_t serialVersionUID_;
- friend struct StringClassOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(StringClass);
-};
-
-class MANAGED FieldClass : public Class {
- private:
- Object* ORDER_BY_NAME_AND_DECLARING_CLASS_;
- friend struct FieldClassOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(FieldClass);
-};
-
-class MANAGED MethodClass : public Class {
- private:
- Object* ORDER_BY_SIGNATURE_;
- friend struct MethodClassOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(MethodClass);
-};
-
-template<class T>
-class MANAGED PrimitiveArray : public Array {
- public:
- typedef T ElementType;
-
- static PrimitiveArray<T>* Alloc(Thread* self, size_t length)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- const T* GetData() const {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value();
- return reinterpret_cast<T*>(data);
- }
-
- T* GetData() {
- intptr_t data = reinterpret_cast<intptr_t>(this) + DataOffset(sizeof(T)).Int32Value();
- return reinterpret_cast<T*>(data);
- }
-
- T Get(int32_t i) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (!IsValidIndex(i)) {
- return T(0);
- }
- return GetData()[i];
- }
-
- void Set(int32_t i, T value) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- if (IsValidIndex(i)) {
- GetData()[i] = value;
- }
- }
-
- static void SetArrayClass(Class* array_class) {
- CHECK(array_class_ == NULL);
- CHECK(array_class != NULL);
- array_class_ = array_class;
- }
-
- static void ResetArrayClass() {
- CHECK(array_class_ != NULL);
- array_class_ = NULL;
- }
-
- private:
- static Class* array_class_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
-};
-
-// C++ mirror of java.lang.String
-class MANAGED String : public Object {
- public:
- static MemberOffset CountOffset() {
- return OFFSET_OF_OBJECT_MEMBER(String, count_);
- }
-
- static MemberOffset ValueOffset() {
- return OFFSET_OF_OBJECT_MEMBER(String, array_);
- }
-
- static MemberOffset OffsetOffset() {
- return OFFSET_OF_OBJECT_MEMBER(String, offset_);
- }
-
- const CharArray* GetCharArray() const {
- return GetFieldObject<const CharArray*>(ValueOffset(), false);
- }
-
- int32_t GetOffset() const {
- int32_t result = GetField32(OffsetOffset(), false);
- DCHECK_LE(0, result);
- return result;
- }
-
- int32_t GetLength() const;
-
- int32_t GetHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- void ComputeHashCode() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SetHashCode(ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()));
- }
-
- int32_t GetUtfLength() const {
- return CountUtf8Bytes(GetCharArray()->GetData() + GetOffset(), GetLength());
- }
-
- uint16_t CharAt(int32_t index) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- String* Intern() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static String* AllocFromUtf16(Thread* self,
- int32_t utf16_length,
- const uint16_t* utf16_data_in,
- int32_t hash_code = 0)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static String* AllocFromModifiedUtf8(Thread* self, const char* utf)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static String* AllocFromModifiedUtf8(Thread* self, int32_t utf16_length,
- const char* utf8_data_in)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static String* Alloc(Thread* self, Class* java_lang_String, int32_t utf16_length)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static String* Alloc(Thread* self, Class* java_lang_String, CharArray* array)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool Equals(const char* modified_utf8) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // TODO: do we need this overload? give it a more intention-revealing name.
- bool Equals(const StringPiece& modified_utf8) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- bool Equals(const String* that) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Compare UTF-16 code point values not in a locale-sensitive manner
- int Compare(int32_t utf16_length, const char* utf8_data_in);
-
- // TODO: do we need this overload? give it a more intention-revealing name.
- bool Equals(const uint16_t* that_chars, int32_t that_offset,
- int32_t that_length) const
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Create a modified UTF-8 encoded std::string from a java/lang/String object.
- std::string ToModifiedUtf8() const;
-
- int32_t FastIndexOf(int32_t ch, int32_t start) {
- int32_t count = GetLength();
- if (start < 0) {
- start = 0;
- } else if (start > count) {
- start = count;
- }
- const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
- const uint16_t* p = chars + start;
- const uint16_t* end = chars + count;
- while (p < end) {
- if (*p++ == ch) {
- return (p - 1) - chars;
- }
- }
- return -1;
- }
-
- int32_t CompareTo(String* other) const;
-
- static Class* GetJavaLangString() {
- DCHECK(java_lang_String_ != NULL);
- return java_lang_String_;
- }
-
- static void SetClass(Class* java_lang_String);
- static void ResetClass();
-
- private:
- void SetHashCode(int32_t new_hash_code) {
- DCHECK_EQ(0u,
- GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false));
- SetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_),
- new_hash_code, false);
- }
-
- void SetCount(int32_t new_count) {
- DCHECK_LE(0, new_count);
- SetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count, false);
- }
-
- void SetOffset(int32_t new_offset) {
- DCHECK_LE(0, new_offset);
- DCHECK_GE(GetLength(), new_offset);
- SetField32(OFFSET_OF_OBJECT_MEMBER(String, offset_), new_offset, false);
- }
-
- void SetArray(CharArray* new_array) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- DCHECK(new_array != NULL);
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(String, array_), new_array, false);
- }
-
- // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- CharArray* array_;
-
- int32_t count_;
-
- uint32_t hash_code_;
-
- int32_t offset_;
-
- static Class* java_lang_String_;
-
- friend struct StringOffsets; // for verifying offset information
- FRIEND_TEST(ObjectTest, StringLength); // for SetOffset and SetCount
- DISALLOW_IMPLICIT_CONSTRUCTORS(String);
-};
-
-// TODO: remove? only used in a unit test of itself.
-struct StringHashCode {
- int32_t operator()(String* string) const {
- return string->GetHashCode();
- }
-};
-
-inline uint32_t Field::GetAccessFlags() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), false);
-}
-
-inline MemberOffset Field::GetOffset() const {
- DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
- return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
-}
-
-inline MemberOffset Field::GetOffsetDuringLinking() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return MemberOffset(GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
-}
-
-inline uint32_t Class::GetAccessFlags() const {
- // Check class is loaded or this is java.lang.String that has a
- // circularity issue during loading the names of its members
- DCHECK(IsLoaded() || IsErroneous() ||
- this == String::GetJavaLangString() ||
- this == Field::GetJavaLangReflectField() ||
- this == AbstractMethod::GetConstructorClass() ||
- this == AbstractMethod::GetMethodClass());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
-}
-
-inline uint32_t AbstractMethod::GetAccessFlags() const {
- DCHECK(GetDeclaringClass()->IsIdxLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, access_flags_), false);
-}
-
-inline uint16_t AbstractMethod::GetMethodIndex() const {
- DCHECK(GetDeclaringClass()->IsResolved() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_index_), false);
-}
-
-inline uint32_t AbstractMethod::GetDexMethodIndex() const {
- DCHECK(GetDeclaringClass()->IsLoaded() || GetDeclaringClass()->IsErroneous());
- return GetField32(OFFSET_OF_OBJECT_MEMBER(AbstractMethod, method_dex_index_), false);
-}
-
-inline bool AbstractMethod::CheckIncompatibleClassChange(InvokeType type) {
- switch (type) {
- case kStatic:
- return !IsStatic();
- case kDirect:
- return !IsDirect() || IsStatic();
- case kVirtual: {
- Class* methods_class = GetDeclaringClass();
- return IsDirect() || (methods_class->IsInterface() && !IsMiranda());
- }
- case kSuper:
- return false; // TODO: appropriate checks for call to super class.
- case kInterface: {
- Class* methods_class = GetDeclaringClass();
- return IsDirect() || !(methods_class->IsInterface() || methods_class->IsObjectClass());
- }
- default:
- LOG(FATAL) << "Unreachable - invocation type: " << type;
- return true;
- }
-}
-
-inline void AbstractMethod::AssertPcIsWithinCode(uintptr_t pc) const {
- if (!kIsDebugBuild) {
- return;
- }
- if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) {
- return;
- }
- Runtime* runtime = Runtime::Current();
- if (GetCode() == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
- return;
- }
- DCHECK(IsWithinCode(pc))
- << PrettyMethod(this)
- << " pc=" << std::hex << pc
- << " code=" << GetCode()
- << " size=" << GetCodeSize();
-}
-
-inline String* Class::GetName() const {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Class, name_), false);
-}
-inline void Class::SetName(String* name) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, name_), name, false);
-}
-
-// C++ mirror of java.lang.Throwable
-class MANAGED Throwable : public Object {
- public:
- void SetDetailMessage(String* new_detail_message) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), new_detail_message, false);
- }
- String* GetDetailMessage() const {
- return GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Throwable, detail_message_), false);
- }
- std::string Dump() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // This is a runtime version of initCause, you shouldn't use it if initCause may have been
- // overridden. Also it asserts rather than throwing exceptions. Currently this is only used
- // in cases like the verifier where the checks cannot fail and initCause isn't overridden.
- void SetCause(Throwable* cause) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool IsCheckedException() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static Class* GetJavaLangThrowable() {
- DCHECK(java_lang_Throwable_ != NULL);
- return java_lang_Throwable_;
- }
-
- static void SetClass(Class* java_lang_Throwable);
- static void ResetClass();
-
- private:
- Object* GetStackState() const {
- return GetFieldObject<Object*>(OFFSET_OF_OBJECT_MEMBER(Throwable, stack_state_), true);
- }
-
- // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- Throwable* cause_;
- String* detail_message_;
- Object* stack_state_; // Note this is Java volatile:
- Object* stack_trace_;
- Object* suppressed_exceptions_;
-
- static Class* java_lang_Throwable_;
-
- friend struct ThrowableOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable);
-};
-
-// C++ mirror of java.lang.StackTraceElement
-class MANAGED StackTraceElement : public Object {
- public:
- const String* GetDeclaringClass() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), false);
- }
-
- const String* GetMethodName() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), false);
- }
-
- const String* GetFileName() const {
- return GetFieldObject<const String*>(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), false);
- }
-
- int32_t GetLineNumber() const {
- return GetField32(
- OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false);
- }
-
- static StackTraceElement* Alloc(Thread* self,
- String* declaring_class,
- String* method_name,
- String* file_name,
- int32_t line_number)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static void SetClass(Class* java_lang_StackTraceElement);
-
- static void ResetClass();
-
- private:
- // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- String* declaring_class_;
- String* file_name_;
- String* method_name_;
- int32_t line_number_;
-
- static Class* GetStackTraceElement() {
- DCHECK(java_lang_StackTraceElement_ != NULL);
- return java_lang_StackTraceElement_;
- }
-
- static Class* java_lang_StackTraceElement_;
-
- friend struct StackTraceElementOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement);
-};
-
-class MANAGED SynthesizedProxyClass : public Class {
- public:
- ObjectArray<Class>* GetInterfaces() {
- return interfaces_;
- }
-
- ObjectArray<ObjectArray<Class> >* GetThrows() {
- return throws_;
- }
-
- private:
- ObjectArray<Class>* interfaces_;
- ObjectArray<ObjectArray<Class> >* throws_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(SynthesizedProxyClass);
-};
-
-class MANAGED Proxy : public Object {
- private:
- Object* h_;
-
- friend struct ProxyOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(Proxy);
-};
-
-} // namespace art
-
-#endif // ART_SRC_OBJECT_H_