summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/assembler_arm.cc2
-rw-r--r--src/check_jni.cc50
-rw-r--r--src/class_linker.cc1053
-rw-r--r--src/class_linker.h38
-rw-r--r--src/class_linker_test.cc119
-rw-r--r--src/class_loader.h5
-rw-r--r--src/common_test.h4
-rw-r--r--src/compiler/Dataflow.cc6
-rw-r--r--src/compiler/Frontend.cc4
-rw-r--r--src/compiler/Ralloc.cc6
-rw-r--r--src/compiler/SSATransformation.cc4
-rw-r--r--src/compiler/codegen/arm/ArchUtility.cc2
-rw-r--r--src/compiler/codegen/arm/ArmRallocUtil.cc8
-rw-r--r--src/compiler/codegen/arm/MethodCodegenDriver.cc40
-rw-r--r--src/compiler/codegen/arm/Thumb2/Gen.cc34
-rw-r--r--src/dex_cache.h8
-rw-r--r--src/dex_file.cc6
-rw-r--r--src/dex_verifier.cc14
-rw-r--r--src/exception_test.cc21
-rw-r--r--src/heap.cc84
-rw-r--r--src/heap.h61
-rw-r--r--src/heap_test.cc4
-rw-r--r--src/image_test.cc4
-rw-r--r--src/image_writer.cc25
-rw-r--r--src/image_writer.h6
-rw-r--r--src/java_lang_System.cc4
-rw-r--r--src/jni_compiler.cc1
-rw-r--r--src/jni_compiler_test.cc9
-rw-r--r--src/jni_internal.cc24
-rw-r--r--src/jni_internal_arm.cc6
-rw-r--r--src/jni_internal_test.cc5
-rw-r--r--src/jni_internal_x86.cc4
-rw-r--r--src/mark_sweep.cc71
-rw-r--r--src/mark_sweep.h1
-rw-r--r--src/object.cc866
-rw-r--r--src/object.h1979
-rw-r--r--src/object_test.cc38
-rw-r--r--src/runtime.h2
-rw-r--r--src/thread.cc30
-rw-r--r--src/thread.h74
-rw-r--r--src/utf.cc11
-rw-r--r--src/utf.h4
42 files changed, 3119 insertions, 1618 deletions
diff --git a/src/assembler_arm.cc b/src/assembler_arm.cc
index 60b8f38ae9..e613307cf9 100644
--- a/src/assembler_arm.cc
+++ b/src/assembler_arm.cc
@@ -1419,7 +1419,7 @@ void Assembler::BuildFrame(size_t frame_size, ManagedRegister method_reg,
CHECK_EQ(R0, method_reg.AsCoreRegister());
AddConstant(SP, -frame_size);
RegList spill_list = 1 << R0 | 1 << LR;
- for(size_t i = 0; i < spill_regs.size(); i++) {
+ for (size_t i = 0; i < spill_regs.size(); i++) {
Register reg = spill_regs.at(i).AsCoreRegister();
// check assumption LR is the last register that gets spilled
CHECK_LT(reg, LR);
diff --git a/src/check_jni.cc b/src/check_jni.cc
index 3037eea50f..8a30279683 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -360,34 +360,39 @@ public:
ScopedJniThreadState ts(mEnv);
Field* f = DecodeField(ts, fid);
- if ((f->GetType() == 'L' || f->GetType() == '[') && java_object != NULL) {
- Object* obj = Decode<Object*>(ts, java_object);
- /*
- * If java_object is a weak global ref whose referent has been cleared,
- * obj will be NULL. Otherwise, obj should always be non-NULL
- * and valid.
- */
- if (obj != NULL && !Heap::IsHeapAddress(obj)) {
- LOG(ERROR) << "JNI ERROR: field operation on invalid " << GetIndirectRefKind(java_object) << ": " << java_object;
- JniAbort();
- return;
- } else {
-#if 0
- Class* field_class = dvmFindLoadedClass(f->signature);
- if (!obj->GetClass()->InstanceOf(field_class)) {
- LOG(ERROR) << "JNI ERROR: attempt to set field " << PrettyField(f) << " with value of wrong type: " << PrettyType(java_object);
+ Class* field_type = f->GetType();
+ if (!field_type->IsPrimitive()) {
+ if (java_object != NULL) {
+ Object* obj = Decode<Object*>(ts, java_object);
+ /*
+ * If java_object is a weak global ref whose referent has been cleared,
+ * obj will be NULL. Otherwise, obj should always be non-NULL
+ * and valid.
+ */
+ if (obj != NULL && !Heap::IsHeapAddress(obj)) {
+ LOG(ERROR) << "JNI ERROR: field operation on invalid " << GetIndirectRefKind(java_object) << ": " << java_object;
JniAbort();
return;
- }
+ } else {
+#if 0
+ Class* field_class = dvmFindLoadedClass(f->signature);
+ if (!obj->GetClass()->InstanceOf(field_class)) {
+ LOG(ERROR) << "JNI ERROR: attempt to set field " << PrettyField(f) << " with value of wrong type: " << PrettyType(java_object);
+ JniAbort();
+ return;
+ }
#else
- UNIMPLEMENTED(WARNING) << "need way to get Class* for a given Field*'s type";
+ UNIMPLEMENTED(WARNING) << "need way to get Class* for a given Field*'s type";
#endif
+ }
}
- } else if (f->GetType() != prim) {
+ } else if (field_type != Runtime::Current()->GetClassLinker()->FindPrimitiveClass(prim)) {
LOG(ERROR) << "JNI ERROR: attempt to set field " << PrettyField(f) << " with value of wrong type: " << prim;
JniAbort();
return;
- } else if (isStatic && !f->IsStatic()) {
+ }
+
+ if (isStatic && !f->IsStatic()) {
if (isStatic) {
LOG(ERROR) << "JNI ERROR: accessing non-static field " << PrettyField(f) << " as static";
} else {
@@ -414,8 +419,11 @@ public:
}
Field* f = DecodeField(ts, fid);
+ Class* f_type = f->GetType();
+ // check invariant that all jfieldIDs have resovled types
+ DCHECK(f_type != NULL);
Class* c = o->GetClass();
- if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f->GetDescriptor()) == NULL) {
+ if (c->FindInstanceField(f->GetName()->ToModifiedUtf8(), f_type) == NULL) {
LOG(ERROR) << "JNI ERROR: jfieldID " << PrettyField(f) << " not valid for an object of class " << PrettyType(o);
JniAbort();
}
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 36bf6a7300..9a6470b5d2 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2,6 +2,7 @@
#include "class_linker.h"
+#include <string>
#include <utility>
#include <vector>
@@ -69,6 +70,8 @@ ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_p
ClassLinker::ClassLinker(InternTable* intern_table)
: classes_lock_(Mutex::Create("ClassLinker::Lock")),
class_roots_(NULL),
+ array_interfaces_(NULL),
+ array_iftable_(NULL),
init_done_(false),
intern_table_(intern_table) {
}
@@ -77,72 +80,84 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) {
CHECK(!init_done_);
// java_lang_Class comes first, its needed for AllocClass
- Class* java_lang_Class = down_cast<Class*>(Heap::AllocObject(NULL, sizeof(ClassClass)));
+ Class* java_lang_Class = down_cast<Class*>(
+ Heap::AllocObject(NULL, sizeof(ClassClass)));
CHECK(java_lang_Class != NULL);
- java_lang_Class->class_size_ = sizeof(ClassClass);
- java_lang_Class->klass_ = java_lang_Class;
+ java_lang_Class->SetClass(java_lang_Class);
+ java_lang_Class->SetClassSize(sizeof(ClassClass));
// AllocClass(Class*) can now be used
// java_lang_Object comes next so that object_array_class can be created
Class* java_lang_Object = AllocClass(java_lang_Class, sizeof(Class));
CHECK(java_lang_Object != NULL);
// backfill Object as the super class of Class
- java_lang_Class->super_class_ = java_lang_Object;
- // mark as non-primitive for object_array_class
- java_lang_Object->primitive_type_ = Class::kPrimNot;
+ java_lang_Class->SetSuperClass(java_lang_Object);
+ java_lang_Object->SetStatus(Class::kStatusLoaded);
- // Object[] is for DexCache and int[] is for various Class members.
+ // Object[] next to hold class roots
Class* object_array_class = AllocClass(java_lang_Class, sizeof(Class));
- CHECK(object_array_class != NULL);
- object_array_class->array_rank_ = 1;
- object_array_class->component_type_ = java_lang_Object;
- Class* int_array_class = AllocClass(java_lang_Class, sizeof(Class));
- CHECK(int_array_class != NULL);
- int_array_class->array_rank_ = 1;
- IntArray::SetArrayClass(int_array_class);
+ object_array_class->SetArrayRank(1);
+ object_array_class->SetComponentType(java_lang_Object);
- // String and char[] are necessary so that FindClass can assign names to members
- Class* java_lang_String = AllocClass(java_lang_Class, sizeof(StringClass));
- CHECK(java_lang_String != NULL);
- CHECK_LT(java_lang_String->object_size_, sizeof(String));
- java_lang_String->object_size_ = sizeof(String);
- String::SetClass(java_lang_String);
+
+ // Setup the char[] class to be used for String
Class* char_array_class = AllocClass(java_lang_Class, sizeof(Class));
- CHECK(char_array_class != NULL);
- char_array_class->array_rank_ = 1;
+ char_array_class->SetArrayRank(1);
CharArray::SetArrayClass(char_array_class);
- // Now String::Alloc* can be used
-
- // backfill Class descriptors missing until this point
- java_lang_Class->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/Class;");
- java_lang_Object->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/Object;");
- object_array_class->descriptor_ = String::AllocFromModifiedUtf8("[Ljava/lang/Object;");
- java_lang_String->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/String;");
- char_array_class->descriptor_ = String::AllocFromModifiedUtf8("[C");
- int_array_class->descriptor_ = String::AllocFromModifiedUtf8("[I");
- // Field and Method are necessary so that FindClass can link members
- Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
- CHECK(java_lang_reflect_Field != NULL);
- java_lang_reflect_Field->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/reflect/Field;");
- CHECK_LT(java_lang_reflect_Field->object_size_, sizeof(Field));
- java_lang_reflect_Field->object_size_ = sizeof(Field);
- Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
- java_lang_reflect_Method->descriptor_ = String::AllocFromModifiedUtf8("Ljava/lang/reflect/Method;");
- CHECK(java_lang_reflect_Method != NULL);
- CHECK_LT(java_lang_reflect_Method->object_size_, sizeof(Method));
- java_lang_reflect_Method->object_size_ = sizeof(Method);
-
- // create storage for root classes, save away our work so far
+ // Setup String
+ Class* java_lang_String = AllocClass(java_lang_Class, sizeof(StringClass));
+ String::SetClass(java_lang_String);
+ java_lang_String->SetObjectSize(sizeof(String));
+ java_lang_String->SetStatus(Class::kStatusResolved);
+
+ // Backfill Class descriptors missing until this point
+ // TODO: intern these strings
+ java_lang_Class->SetDescriptor(
+ String::AllocFromModifiedUtf8("Ljava/lang/Class;"));
+ java_lang_Object->SetDescriptor(
+ String::AllocFromModifiedUtf8("Ljava/lang/Object;"));
+ object_array_class->SetDescriptor(
+ String::AllocFromModifiedUtf8("[Ljava/lang/Object;"));
+ java_lang_String->SetDescriptor(
+ String::AllocFromModifiedUtf8("Ljava/lang/String;"));
+ char_array_class->SetDescriptor(String::AllocFromModifiedUtf8("[C"));
+
+ // Create storage for root classes, save away our work so far (requires
+ // descriptors)
class_roots_ = ObjectArray<Class>::Alloc(object_array_class, kClassRootsMax);
SetClassRoot(kJavaLangClass, java_lang_Class);
SetClassRoot(kJavaLangObject, java_lang_Object);
SetClassRoot(kObjectArrayClass, object_array_class);
- SetClassRoot(kJavaLangString, java_lang_String);
SetClassRoot(kCharArrayClass, char_array_class);
+ SetClassRoot(kJavaLangString, java_lang_String);
+
+ // Setup the primitive type classes.
+ SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Class::kPrimBoolean));
+ SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Class::kPrimByte));
+ SetClassRoot(kPrimitiveChar, CreatePrimitiveClass("C", Class::kPrimChar));
+ SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Class::kPrimShort));
+ SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Class::kPrimInt));
+ SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Class::kPrimLong));
+ SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Class::kPrimFloat));
+ SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Class::kPrimDouble));
+ SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Class::kPrimVoid));
+
+ // Backfill component type of char[]
+ char_array_class->SetComponentType(GetClassRoot(kPrimitiveChar));
+
+ // Create array interface entries to populate once we can load system classes
+ array_interfaces_ = AllocObjectArray<Class>(2);
+ array_iftable_ = new InterfaceEntry[2];
+
+ // Create int array type for AllocDexCache (done in AppendToBootClassPath)
+ Class* int_array_class = AllocClass(java_lang_Class, sizeof(Class));
+ int_array_class->SetArrayRank(1);
+ int_array_class->SetDescriptor(String::AllocFromModifiedUtf8("[I"));
+ int_array_class->SetComponentType(GetClassRoot(kPrimitiveInt));
+ IntArray::SetArrayClass(int_array_class);
SetClassRoot(kIntArrayClass, int_array_class);
- SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
- SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
+
// now that these are registered, we can use AllocClass() and AllocObjectArray
// setup boot_class_path_ now that we can use AllocObjectArray to
@@ -152,137 +167,174 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path) {
CHECK(dex_file != NULL);
AppendToBootClassPath(*dex_file);
}
- // now we can use FindSystemClass, at least for non-arrays classes.
- // run Class, Field, and Method through FindSystemClass.
- // this initializes their dex_cache_ fields and register them in classes_.
- // we also override their object_size_ values to accommodate the extra C++ fields.
- Class* Class_class = FindSystemClass("Ljava/lang/Class;");
- CHECK_EQ(java_lang_Class, Class_class);
- CHECK_LT(java_lang_Class->object_size_, sizeof(Class));
- java_lang_Class->object_size_ = sizeof(Class);
- Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
- CHECK_EQ(java_lang_reflect_Field, Field_class);
- CHECK_LT(java_lang_reflect_Field->object_size_, sizeof(Field));
- java_lang_reflect_Field->object_size_ = sizeof(Field);
- Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
- CHECK_EQ(java_lang_reflect_Method, Method_class);
- CHECK_LT(java_lang_reflect_Method->object_size_, sizeof(Method));
- java_lang_reflect_Method->object_size_ = sizeof(Method);
+ // Field and Method are necessary so that FindClass can link members
+ Class* java_lang_reflect_Field = AllocClass(java_lang_Class, sizeof(FieldClass));
+ CHECK(java_lang_reflect_Field != NULL);
+ java_lang_reflect_Field->SetDescriptor(String::AllocFromModifiedUtf8("Ljava/lang/reflect/Field;"));
+ java_lang_reflect_Field->SetObjectSize(sizeof(Field));
+ SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
+ java_lang_reflect_Field->SetStatus(Class::kStatusResolved);
+ Field::SetClass(java_lang_reflect_Field);
+
+ Class* java_lang_reflect_Method = AllocClass(java_lang_Class, sizeof(MethodClass));
+ java_lang_reflect_Method->SetDescriptor(String::AllocFromModifiedUtf8("Ljava/lang/reflect/Method;"));
+ CHECK(java_lang_reflect_Method != NULL);
+ java_lang_reflect_Method->SetObjectSize(sizeof(Method));
+ SetClassRoot(kJavaLangReflectMethod, java_lang_reflect_Method);
+ java_lang_reflect_Method->SetStatus(Class::kStatusResolved);
+ Method::SetClass(java_lang_reflect_Method);
+
+ // now we can use FindSystemClass
- // Object and String just need more minimal setup, since they do not have extra C++ fields.
+ // Object and String just need more minimal setup, since they do not have
+ // extra C++ fields.
+ java_lang_Object->SetStatus(Class::kStatusNotReady);
Class* Object_class = FindSystemClass("Ljava/lang/Object;");
CHECK_EQ(java_lang_Object, Object_class);
- CHECK_EQ(java_lang_Object->object_size_, sizeof(Object));
+ CHECK_EQ(java_lang_Object->GetObjectSize(), sizeof(Object));
+ java_lang_String->SetStatus(Class::kStatusNotReady);
Class* String_class = FindSystemClass("Ljava/lang/String;");
CHECK_EQ(java_lang_String, String_class);
- CHECK_EQ(java_lang_String->object_size_, sizeof(String));
+ CHECK_EQ(java_lang_String->GetObjectSize(), sizeof(String));
- // Setup the ClassLoaders, adjusting the object_size_ as necessary
- Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;");
- CHECK(java_lang_ClassLoader != NULL);
- CHECK_LT(java_lang_ClassLoader->object_size_, sizeof(ClassLoader));
- java_lang_ClassLoader->object_size_ = sizeof(ClassLoader);
- SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader);
- Class* dalvik_system_BaseDexClassLoader = FindSystemClass("Ldalvik/system/BaseDexClassLoader;");
- CHECK(dalvik_system_BaseDexClassLoader != NULL);
- CHECK_EQ(dalvik_system_BaseDexClassLoader->object_size_, sizeof(BaseDexClassLoader));
- SetClassRoot(kDalvikSystemBaseDexClassLoader, dalvik_system_BaseDexClassLoader);
- Class* dalvik_system_PathClassLoader = FindSystemClass("Ldalvik/system/PathClassLoader;");
- CHECK(dalvik_system_PathClassLoader != NULL);
- CHECK_EQ(dalvik_system_PathClassLoader->object_size_, sizeof(PathClassLoader));
- SetClassRoot(kDalvikSystemPathClassLoader, dalvik_system_PathClassLoader);
- PathClassLoader::SetClass(dalvik_system_PathClassLoader);
+ // Setup the primitive array type classes - can't be done until Object has
+ // a vtable
+ SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z"));
+ BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
+
+ SetClassRoot(kByteArrayClass, FindSystemClass("[B"));
+ ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
+
+ Class* found_char_array_class = FindSystemClass("[C");
+ CHECK_EQ(char_array_class, found_char_array_class);
+
+ SetClassRoot(kShortArrayClass, FindSystemClass("[S"));
+ ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
+
+ Class* found_int_array_class = FindSystemClass("[I");
+ CHECK_EQ(int_array_class, found_int_array_class);
+
+ SetClassRoot(kLongArrayClass, FindSystemClass("[J"));
+ LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
+
+ SetClassRoot(kFloatArrayClass, FindSystemClass("[F"));
+ FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
+
+ SetClassRoot(kDoubleArrayClass, FindSystemClass("[D"));
+ DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
- // Setup a single, global copy of "interfaces" and "iftable" for
- // reuse across array classes
+ Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
+ CHECK_EQ(object_array_class, found_object_array_class);
+
+ // Setup the single, global copies of "interfaces" and "iftable"
Class* java_lang_Cloneable = FindSystemClass("Ljava/lang/Cloneable;");
CHECK(java_lang_Cloneable != NULL);
Class* java_io_Serializable = FindSystemClass("Ljava/io/Serializable;");
CHECK(java_io_Serializable != NULL);
-
- array_interfaces_ = AllocObjectArray<Class>(2);
CHECK(array_interfaces_ != NULL);
array_interfaces_->Set(0, java_lang_Cloneable);
array_interfaces_->Set(1, java_io_Serializable);
-
// We assume that Cloneable/Serializable don't have superinterfaces --
// normally we'd have to crawl up and explicitly list all of the
// supers as well. These interfaces don't have any methods, so we
// don't have to worry about the ifviPool either.
- array_iftable_ = new InterfaceEntry[2];
array_iftable_[0].SetInterface(array_interfaces_->Get(0));
array_iftable_[1].SetInterface(array_interfaces_->Get(1));
- // now FindClass can be used for non-primitive array classes
- // run Object[] through FindClass to complete initialization
- Class* found_object_array_class = FindSystemClass("[Ljava/lang/Object;");
- CHECK_EQ(object_array_class, found_object_array_class);
+ // Sanity check Object[]'s interfaces
CHECK_EQ(java_lang_Cloneable, object_array_class->GetInterface(0));
CHECK_EQ(java_io_Serializable, object_array_class->GetInterface(1));
- // Setup the primitive type classes.
- SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z"));
- SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B"));
- SetClassRoot(kPrimitiveChar, CreatePrimitiveClass("C"));
- SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D"));
- SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F"));
- SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I"));
- SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J"));
- SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S"));
- SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V"));
- // now we can use FindSystemClass for anything, including for "[C"
-
- // run char[] and int[] through FindClass to complete initialization
- Class* found_char_array_class = FindSystemClass("[C");
- CHECK_EQ(char_array_class, found_char_array_class);
- Class* found_int_array_class = FindSystemClass("[I");
- CHECK_EQ(int_array_class, found_int_array_class);
+ // run Class, Field, and Method through FindSystemClass.
+ // this initializes their dex_cache_ fields and register them in classes_.
+ // we also override their object_size_ values to accommodate the extra C++ fields.
+ Class* Class_class = FindSystemClass("Ljava/lang/Class;");
+ CHECK_EQ(java_lang_Class, Class_class);
+ // No sanity check on size as Class is variably sized
- // Initialize all the other primitive array types for PrimitiveArray::Alloc.
- // These are easy because everything we need has already been set up.
- SetClassRoot(kBooleanArrayClass, FindSystemClass("[Z"));
- SetClassRoot(kByteArrayClass, FindSystemClass("[B"));
- SetClassRoot(kDoubleArrayClass, FindSystemClass("[D"));
- SetClassRoot(kFloatArrayClass, FindSystemClass("[F"));
- SetClassRoot(kLongArrayClass, FindSystemClass("[J"));
- SetClassRoot(kShortArrayClass, FindSystemClass("[S"));
- BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
- ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
- DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
- FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
- LongArray::SetArrayClass(GetClassRoot(kLongArrayClass));
- ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
+ java_lang_reflect_Field->SetStatus(Class::kStatusNotReady);
+ Class* Field_class = FindSystemClass("Ljava/lang/reflect/Field;");
+ CHECK_EQ(java_lang_reflect_Field, Field_class);
+ CHECK_LT(java_lang_reflect_Field->GetObjectSize(), sizeof(Field));
+ java_lang_reflect_Field->SetObjectSize(sizeof(Field));
+
+ java_lang_reflect_Method->SetStatus(Class::kStatusNotReady);
+ Class* Method_class = FindSystemClass("Ljava/lang/reflect/Method;");
+ CHECK_EQ(java_lang_reflect_Method, Method_class);
+ CHECK_LT(java_lang_reflect_Method->GetObjectSize(), sizeof(Method));
+ java_lang_reflect_Method->SetObjectSize(sizeof(Method));
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
Class* java_lang_ref_FinalizerReference = FindSystemClass("Ljava/lang/ref/FinalizerReference;");
+ java_lang_ref_FinalizerReference->SetAccessFlags(
+ java_lang_ref_FinalizerReference->GetAccessFlags() |
+ kAccClassIsReference | kAccClassIsFinalizerReference);
Class* java_lang_ref_PhantomReference = FindSystemClass("Ljava/lang/ref/PhantomReference;");
+ java_lang_ref_PhantomReference->SetAccessFlags(
+ java_lang_ref_PhantomReference->GetAccessFlags() |
+ kAccClassIsReference | kAccClassIsPhantomReference);
Class* java_lang_ref_SoftReference = FindSystemClass("Ljava/lang/ref/SoftReference;");
+ java_lang_ref_SoftReference->SetAccessFlags(
+ java_lang_ref_SoftReference->GetAccessFlags() | kAccClassIsReference);
Class* java_lang_ref_WeakReference = FindSystemClass("Ljava/lang/ref/WeakReference;");
- java_lang_ref_FinalizerReference->access_flags_ |= kAccClassIsReference | kAccClassIsFinalizerReference;
- java_lang_ref_PhantomReference->access_flags_ |= kAccClassIsReference | kAccClassIsPhantomReference;
- java_lang_ref_SoftReference->access_flags_ |= kAccClassIsReference;
- java_lang_ref_WeakReference->access_flags_ |= kAccClassIsReference | kAccClassIsWeakReference;
+ java_lang_ref_WeakReference->SetAccessFlags(
+ java_lang_ref_WeakReference->GetAccessFlags() |
+ kAccClassIsReference | kAccClassIsWeakReference);
// Let the heap know some key offsets into java.lang.ref instances
+ // NB we hard code the field indexes here rather than using FindInstanceField
+ // as the types of the field can't be resolved prior to the runtime being
+ // fully initialized
Class* java_lang_ref_Reference = FindSystemClass("Ljava/lang/ref/Reference;");
- Field* referent = java_lang_ref_Reference->FindDeclaredInstanceField(
- "referent", "Ljava/lang/Object;");
- Field* queue = java_lang_ref_Reference->FindDeclaredInstanceField(
- "queue", "Ljava/lang/ref/ReferenceQueue;");
- Field* queueNext = java_lang_ref_Reference->FindDeclaredInstanceField(
- "queueNext", "Ljava/lang/ref/Reference;");
- Field* pendingNext = java_lang_ref_Reference->FindDeclaredInstanceField(
- "pendingNext", "Ljava/lang/ref/Reference;");
- Field* zombie = java_lang_ref_FinalizerReference->FindDeclaredInstanceField(
- "zombie", "Ljava/lang/Object;");
+
+ Field* pendingNext = java_lang_ref_Reference->GetInstanceField(0);
+ CHECK(pendingNext->GetName()->Equals("pendingNext"));
+ CHECK(ResolveType(pendingNext->GetTypeIdx(), pendingNext) ==
+ java_lang_ref_Reference);
+
+ Field* queue = java_lang_ref_Reference->GetInstanceField(1);
+ CHECK(queue->GetName()->Equals("queue"));
+ CHECK(ResolveType(queue->GetTypeIdx(), queue) ==
+ FindSystemClass("Ljava/lang/ref/ReferenceQueue;"));
+
+ Field* queueNext = java_lang_ref_Reference->GetInstanceField(2);
+ CHECK(queueNext->GetName()->Equals("queueNext"));
+ CHECK(ResolveType(queueNext->GetTypeIdx(), queueNext) ==
+ java_lang_ref_Reference);
+
+ Field* referent = java_lang_ref_Reference->GetInstanceField(3);
+ CHECK(referent->GetName()->Equals("referent"));
+ CHECK(ResolveType(referent->GetTypeIdx(), referent) ==
+ java_lang_Object);
+
+ Field* zombie = java_lang_ref_FinalizerReference->GetInstanceField(2);
+ CHECK(zombie->GetName()->Equals("zombie"));
+ CHECK(ResolveType(zombie->GetTypeIdx(), zombie) ==
+ java_lang_Object);
+
Heap::SetReferenceOffsets(referent->GetOffset(),
queue->GetOffset(),
queueNext->GetOffset(),
pendingNext->GetOffset(),
zombie->GetOffset());
- // Optimization for quick stack trace allocation
+ // Setup the ClassLoaders, adjusting the object_size_ as necessary
+ Class* java_lang_ClassLoader = FindSystemClass("Ljava/lang/ClassLoader;");
+ CHECK_LT(java_lang_ClassLoader->GetObjectSize(), sizeof(ClassLoader));
+ java_lang_ClassLoader->SetObjectSize(sizeof(ClassLoader));
+ SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader);
+
+ Class* dalvik_system_BaseDexClassLoader = FindSystemClass("Ldalvik/system/BaseDexClassLoader;");
+ CHECK_EQ(dalvik_system_BaseDexClassLoader->GetObjectSize(), sizeof(BaseDexClassLoader));
+ SetClassRoot(kDalvikSystemBaseDexClassLoader, dalvik_system_BaseDexClassLoader);
+
+ Class* dalvik_system_PathClassLoader = FindSystemClass("Ldalvik/system/PathClassLoader;");
+ CHECK_EQ(dalvik_system_PathClassLoader->GetObjectSize(), sizeof(PathClassLoader));
+ SetClassRoot(kDalvikSystemPathClassLoader, dalvik_system_PathClassLoader);
+ PathClassLoader::SetClass(dalvik_system_PathClassLoader);
+
+ // Set up java.lang.StackTraceElement as a convenience
SetClassRoot(kJavaLangStackTraceElement, FindSystemClass("Ljava/lang/StackTraceElement;"));
SetClassRoot(kJavaLangStackTraceElementArrayClass, FindSystemClass("[Ljava/lang/StackTraceElement;"));
StackTraceElement::SetClass(GetClassRoot(kJavaLangStackTraceElement));
@@ -296,7 +348,7 @@ void ClassLinker::FinishInit() {
ClassRoot class_root = static_cast<ClassRoot>(i);
Class* klass = GetClassRoot(class_root);
CHECK(klass != NULL);
- DCHECK(klass->IsArrayClass() || klass->IsPrimitive() || klass->dex_cache_ != NULL);
+ DCHECK(klass->IsArrayClass() || klass->IsPrimitive() || klass->GetDexCache() != NULL);
// note SetClassRoot does additional validation.
// if possible add new checks there to catch errors early
}
@@ -316,7 +368,7 @@ struct ClassLinker::InitCallbackState {
struct DexCacheHash {
size_t operator()(art::DexCache* const& obj) const {
- return reinterpret_cast<size_t>(&obj);
+ return reinterpret_cast<size_t>(&obj);
}
};
typedef std::tr1::unordered_set<DexCache*, DexCacheHash> Set;
@@ -355,12 +407,12 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path, Space
}
// reinit array_interfaces_ from any array class instance, they should all be ==
- array_interfaces_ = GetClassRoot(kObjectArrayClass)->interfaces_;
- DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->interfaces_);
+ array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces();
+ DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces());
// build a map from location to DexCache to match up with DexFile::GetLocation
std::tr1::unordered_map<std::string, DexCache*> location_to_dex_cache;
- typedef InitCallbackState::Set::const_iterator It; // TODO: C++0x auto
+ typedef InitCallbackState::Set::const_iterator It; // TODO: C++0x auto
for (It it = state.dex_caches.begin(), end = state.dex_caches.end(); it != end; ++it) {
DexCache* dex_cache = *it;
std::string location = dex_cache->GetLocation()->ToModifiedUtf8();
@@ -374,8 +426,9 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path, Space
DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()];
AppendToBootClassPath(*dex_file, dex_cache);
}
-
String::SetClass(GetClassRoot(kJavaLangString));
+ Field::SetClass(GetClassRoot(kJavaLangReflectField));
+ Method::SetClass(GetClassRoot(kJavaLangReflectMethod));
BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
CharArray::SetArrayClass(GetClassRoot(kCharArrayClass));
@@ -399,7 +452,7 @@ void ClassLinker::InitCallback(Object* obj, void *arg) {
return;
}
Class* klass = obj->AsClass();
- CHECK(klass->class_loader_ == NULL);
+ CHECK(klass->GetClassLoader() == NULL);
std::string descriptor = klass->GetDescriptor()->ToModifiedUtf8();
@@ -415,7 +468,7 @@ void ClassLinker::InitCallback(Object* obj, void *arg) {
}
// check if this is a root, if so, register it
- typedef InitCallbackState::Table::const_iterator It; // TODO: C++0x auto
+ typedef InitCallbackState::Table::const_iterator It; // TODO: C++0x auto
It it = state->descriptor_to_class_root.find(descriptor);
if (it != state->descriptor_to_class_root.end()) {
ClassRoot class_root = it->second;
@@ -435,7 +488,7 @@ void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
{
MutexLock mu(classes_lock_);
- typedef Table::const_iterator It; // TODO: C++0x auto
+ typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = classes_.begin(), end = classes_.end(); it != end; ++it) {
visitor(it->second, arg);
}
@@ -447,6 +500,8 @@ void ClassLinker::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
ClassLinker::~ClassLinker() {
delete classes_lock_;
String::ResetClass();
+ Field::ResetClass();
+ Method::ResetClass();
BooleanArray::ResetArrayClass();
ByteArray::ResetArrayClass();
CharArray::ResetArrayClass();
@@ -478,7 +533,8 @@ CodeAndDirectMethods* ClassLinker::AllocCodeAndDirectMethods(size_t length) {
Class* ClassLinker::AllocClass(Class* java_lang_Class, size_t class_size) {
DCHECK_GE(class_size, sizeof(Class));
Class* klass = Heap::AllocObject(java_lang_Class, class_size)->AsClass();
- klass->class_size_ = class_size;
+ klass->SetPrimitiveType(Class::kPrimNot); // default to not being primitive
+ klass->SetClassSize(class_size);
return klass;
}
@@ -553,27 +609,29 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor,
} else {
klass = AllocClass(SizeOfClass(dex_file, dex_class_def));
}
- klass->dex_cache_ = dex_cache;
- LoadClass(dex_file, dex_class_def, klass, class_loader);
- // Check for a pending exception during load
- if (self->IsExceptionPending()) {
- // TODO: free native allocations in klass
- return NULL;
- }
- {
+ if (!klass->IsLinked()) {
+ klass->SetDexCache(dex_cache);
+ LoadClass(dex_file, dex_class_def, klass, class_loader);
+ // Check for a pending exception during load
+ if (self->IsExceptionPending()) {
+ // TODO: free native allocations in klass
+ return NULL;
+ }
ObjectLock lock(klass);
- klass->clinit_thread_id_ = self->GetId();
+ klass->SetClinitThreadId(self->GetId());
// Add the newly loaded class to the loaded classes table.
bool success = InsertClass(descriptor, klass); // TODO: just return collision
if (!success) {
// We may fail to insert if we raced with another thread.
- klass->clinit_thread_id_ = 0;
+ klass->SetClinitThreadId(0);
// TODO: free native allocations in klass
klass = LookupClass(descriptor, class_loader);
CHECK(klass != NULL);
+ return klass;
} else {
// Finish loading (if necessary) by finding parents
- if (!klass->IsLoaded() && !LoadSuperAndInterfaces(klass, dex_file)) {
+ CHECK(!klass->IsLoaded());
+ if (!LoadSuperAndInterfaces(klass, dex_file)) {
// Loading failed.
// TODO: CHECK(self->IsExceptionPending());
lock.NotifyAll();
@@ -581,7 +639,8 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor,
}
CHECK(klass->IsLoaded());
// Link the class (if necessary)
- if (!klass->IsLinked() && !LinkClass(klass, dex_file)) {
+ CHECK(!klass->IsLinked());
+ if (!LinkClass(klass)) {
// Linking failed.
// TODO: CHECK(self->IsExceptionPending());
lock.NotifyAll();
@@ -595,7 +654,7 @@ Class* ClassLinker::FindClass(const StringPiece& descriptor,
if (!klass->IsLinked() && !klass->IsErroneous()) {
ObjectLock lock(klass);
// Check for circular dependencies between classes.
- if (!klass->IsLinked() && klass->clinit_thread_id_ == self->GetId()) {
+ if (!klass->IsLinked() && klass->GetClinitThreadId() == self->GetId()) {
self->ThrowNewException("Ljava/lang/ClassCircularityError;", NULL); // TODO: detail
return NULL;
}
@@ -666,43 +725,46 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
Class* klass,
const ClassLoader* class_loader) {
CHECK(klass != NULL);
- CHECK(klass->dex_cache_ != NULL);
- CHECK_EQ(Class::kStatusNotReady, klass->status_);
+ CHECK(klass->GetDexCache() != NULL);
+ CHECK_EQ(Class::kStatusNotReady, klass->GetStatus());
const byte* class_data = dex_file.GetClassData(dex_class_def);
DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
const char* descriptor = dex_file.GetClassDescriptor(dex_class_def);
CHECK(descriptor != NULL);
- klass->klass_ = GetClassRoot(kJavaLangClass);
- klass->descriptor_ = String::AllocFromModifiedUtf8(descriptor);
- klass->access_flags_ = dex_class_def.access_flags_;
- klass->class_loader_ = class_loader;
- klass->primitive_type_ = Class::kPrimNot;
- klass->status_ = Class::kStatusIdx;
-
- // Make sure the aren't any "bonus" flags set, since we use them for runtime state.
- CHECK_EQ(klass->access_flags_ & ~kAccClassFlagsMask, 0U);
+ klass->SetClass(GetClassRoot(kJavaLangClass));
+ if (klass->GetDescriptor() != NULL) {
+ DCHECK(klass->GetDescriptor()->Equals(descriptor));
+ } else {
+ klass->SetDescriptor(String::AllocFromModifiedUtf8(descriptor));
+ }
+ uint32_t access_flags = dex_class_def.access_flags_;
+ // Make sure there aren't any "bonus" flags set, since we use them for runtime
+ // state.
+ CHECK_EQ(access_flags & ~kAccClassFlagsMask, 0U);
+ klass->SetAccessFlags(access_flags);
+ klass->SetClassLoader(class_loader);
+ DCHECK(klass->GetPrimitiveType() == Class::kPrimNot);
+ klass->SetStatus(Class::kStatusIdx);
- klass->super_class_ = NULL;
- klass->super_class_type_idx_ = dex_class_def.superclass_idx_;
+ klass->SetSuperClassTypeIdx(dex_class_def.superclass_idx_);
size_t num_static_fields = header.static_fields_size_;
size_t num_instance_fields = header.instance_fields_size_;
size_t num_direct_methods = header.direct_methods_size_;
size_t num_virtual_methods = header.virtual_methods_size_;
- klass->source_file_ = dex_file.dexGetSourceFile(dex_class_def);
+ klass->SetSourceFile(dex_file.dexGetSourceFile(dex_class_def));
// Load class interfaces.
LoadInterfaces(dex_file, dex_class_def, klass);
// Load static fields.
- DCHECK(klass->sfields_ == NULL);
if (num_static_fields != 0) {
- klass->sfields_ = AllocObjectArray<Field>(num_static_fields);
+ klass->SetSFields(AllocObjectArray<Field>(num_static_fields));
uint32_t last_idx = 0;
- for (size_t i = 0; i < klass->NumStaticFields(); ++i) {
+ for (size_t i = 0; i < num_static_fields; ++i) {
DexFile::Field dex_field;
dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
Field* sfield = AllocField();
@@ -712,11 +774,10 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
}
// Load instance fields.
- DCHECK(klass->ifields_ == NULL);
if (num_instance_fields != 0) {
- klass->ifields_ = AllocObjectArray<Field>(num_instance_fields);
+ klass->SetIFields(AllocObjectArray<Field>(num_instance_fields));
uint32_t last_idx = 0;
- for (size_t i = 0; i < klass->NumInstanceFields(); ++i) {
+ for (size_t i = 0; i < num_instance_fields; ++i) {
DexFile::Field dex_field;
dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
Field* ifield = AllocField();
@@ -726,12 +787,11 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
}
// Load direct methods.
- DCHECK(klass->direct_methods_ == NULL);
if (num_direct_methods != 0) {
// TODO: append direct methods to class object
- klass->direct_methods_ = AllocObjectArray<Method>(num_direct_methods);
+ klass->SetDirectMethods(AllocObjectArray<Method>(num_direct_methods));
uint32_t last_idx = 0;
- for (size_t i = 0; i < klass->NumDirectMethods(); ++i) {
+ for (size_t i = 0; i < num_direct_methods; ++i) {
DexFile::Method dex_method;
dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
Method* meth = AllocMethod();
@@ -742,12 +802,11 @@ void ClassLinker::LoadClass(const DexFile& dex_file,
}
// Load virtual methods.
- DCHECK(klass->virtual_methods_ == NULL);
if (num_virtual_methods != 0) {
// TODO: append virtual methods to class object
- klass->virtual_methods_ = AllocObjectArray<Method>(num_virtual_methods);
+ klass->SetVirtualMethods(AllocObjectArray<Method>(num_virtual_methods));
uint32_t last_idx = 0;
- for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+ for (size_t i = 0; i < num_virtual_methods; ++i) {
DexFile::Method dex_method;
dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
Method* meth = AllocMethod();
@@ -763,13 +822,12 @@ void ClassLinker::LoadInterfaces(const DexFile& dex_file,
Class* klass) {
const DexFile::TypeList* list = dex_file.GetInterfacesList(dex_class_def);
if (list != NULL) {
- DCHECK(klass->interfaces_ == NULL);
- klass->interfaces_ = AllocObjectArray<Class>(list->Size());
- DCHECK(klass->interfaces_type_idx_ == NULL);
- klass->interfaces_type_idx_ = IntArray::Alloc(list->Size());
+ klass->SetInterfaces(AllocObjectArray<Class>(list->Size()));
+ IntArray* interfaces_idx = IntArray::Alloc(list->Size());
+ klass->SetInterfacesTypeIdx(interfaces_idx);
for (size_t i = 0; i < list->Size(); ++i) {
const DexFile::TypeItem& type_item = list->GetTypeItem(i);
- klass->interfaces_type_idx_->Set(i, type_item.type_idx_);
+ interfaces_idx->Set(i, type_item.type_idx_);
}
}
}
@@ -779,11 +837,19 @@ void ClassLinker::LoadField(const DexFile& dex_file,
Class* klass,
Field* dst) {
const DexFile::FieldId& field_id = dex_file.GetFieldId(src.field_idx_);
- dst->declaring_class_ = klass;
- dst->name_ = ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache());
- dst->descriptor_.set(dex_file.dexStringByTypeIdx(field_id.type_idx_));
- // TODO: Assign dst->type_.
- dst->access_flags_ = src.access_flags_;
+ dst->SetDeclaringClass(klass);
+ dst->SetName(ResolveString(dex_file, field_id.name_idx_, klass->GetDexCache()));
+ dst->SetTypeIdx(field_id.type_idx_);
+ dst->SetAccessFlags(src.access_flags_);
+
+ // In order to access primitive types using GetTypeDuringLinking we need to
+ // ensure they are resolved into the dex cache
+ const char* descriptor = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+ if (descriptor[1] == '\0') {
+ // only the descriptors of primitive types should be 1 character long
+ Class* resolved = ResolveType(dex_file, field_id.type_idx_, klass);
+ DCHECK(resolved->IsPrimitive());
+ }
}
void ClassLinker::LoadMethod(const DexFile& dex_file,
@@ -791,38 +857,40 @@ void ClassLinker::LoadMethod(const DexFile& dex_file,
Class* klass,
Method* dst) {
const DexFile::MethodId& method_id = dex_file.GetMethodId(src.method_idx_);
- dst->declaring_class_ = klass;
- dst->name_ = ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache());
+ dst->SetDeclaringClass(klass);
+ dst->SetName(ResolveString(dex_file, method_id.name_idx_, klass->GetDexCache()));
{
int32_t utf16_length;
std::string utf8(dex_file.CreateMethodDescriptor(method_id.proto_idx_, &utf16_length));
- dst->signature_ = String::AllocFromModifiedUtf8(utf16_length, utf8.c_str());
- }
- dst->proto_idx_ = method_id.proto_idx_;
- dst->code_off_ = src.code_off_;
- dst->shorty_ = dex_file.GetShorty(method_id.proto_idx_);
- dst->access_flags_ = src.access_flags_;
-
- dst->dex_cache_strings_ = klass->dex_cache_->GetStrings();
- dst->dex_cache_resolved_types_ = klass->dex_cache_->GetResolvedTypes();
- dst->dex_cache_resolved_methods_ = klass->dex_cache_->GetResolvedMethods();
- dst->dex_cache_resolved_fields_ = klass->dex_cache_->GetResolvedFields();
- dst->dex_cache_code_and_direct_methods_ = klass->dex_cache_->GetCodeAndDirectMethods();
- dst->dex_cache_initialized_static_storage_ = klass->dex_cache_->GetInitializedStaticStorage();
+ dst->SetSignature(String::AllocFromModifiedUtf8(utf16_length, utf8.c_str()));
+ }
+ dst->SetProtoIdx(method_id.proto_idx_);
+ dst->SetCodeItemOffset(src.code_off_);
+ const char* shorty = dex_file.GetShorty(method_id.proto_idx_);
+ dst->SetShorty(shorty);
+ dst->SetAccessFlags(src.access_flags_);
+ dst->SetReturnTypeIdx(dex_file.GetProtoId(method_id.proto_idx_).return_type_idx_);
+
+ dst->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
+ dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
+ dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods());
+ dst->SetDexCacheResolvedFields(klass->GetDexCache()->GetResolvedFields());
+ dst->SetDexCacheCodeAndDirectMethods(klass->GetDexCache()->GetCodeAndDirectMethods());
+ dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());
// TODO: check for finalize method
const DexFile::CodeItem* code_item = dex_file.GetCodeItem(src);
if (code_item != NULL) {
- dst->num_registers_ = code_item->registers_size_;
- dst->num_ins_ = code_item->ins_size_;
- dst->num_outs_ = code_item->outs_size_;
+ dst->SetNumRegisters(code_item->registers_size_);
+ dst->SetNumIns(code_item->ins_size_);
+ dst->SetNumOuts(code_item->outs_size_);
} else {
- uint16_t num_args = dst->NumArgRegisters();
- if (!dst->IsStatic()) {
+ uint16_t num_args = Method::NumArgRegisters(shorty);
+ if ((src.access_flags_ & kAccStatic) != 0) {
++num_args;
}
- dst->num_registers_ = dst->num_ins_ + num_args;
+ dst->SetNumRegisters(num_args);
// TODO: native methods
}
}
@@ -867,13 +935,15 @@ DexCache* ClassLinker::FindDexCache(const DexFile& dex_file) const {
return NULL;
}
-Class* ClassLinker::CreatePrimitiveClass(const char* descriptor) {
+Class* ClassLinker::CreatePrimitiveClass(const char* descriptor,
+ Class::PrimitiveType type) {
+ // TODO: deduce one argument from the other
Class* klass = AllocClass(sizeof(Class));
CHECK(klass != NULL);
- klass->super_class_ = NULL;
- klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract;
- klass->descriptor_ = String::AllocFromModifiedUtf8(descriptor);
- klass->status_ = Class::kStatusInitialized;
+ klass->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
+ klass->SetDescriptor(String::AllocFromModifiedUtf8(descriptor));
+ klass->SetPrimitiveType(type);
+ klass->SetStatus(Class::kStatusInitialized);
bool success = InsertClass(descriptor, klass);
CHECK(success) << "CreatePrimitiveClass(" << descriptor << ") failed";
return klass;
@@ -893,36 +963,35 @@ Class* ClassLinker::CreatePrimitiveClass(const char* descriptor) {
//
// Returns NULL with an exception raised on failure.
Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
- const ClassLoader* class_loader)
-{
- CHECK(descriptor[0] == '[');
+ const ClassLoader* class_loader) {
+ CHECK_EQ('[', descriptor[0]);
// Identify the underlying element class and the array dimension depth.
- Class* component_type_ = NULL;
+ Class* component_type = NULL;
int array_rank;
if (descriptor[1] == '[') {
// array of arrays; keep descriptor and grab stuff from parent
Class* outer = FindClass(descriptor.substr(1), class_loader);
if (outer != NULL) {
- // want the base class, not "outer", in our component_type_
- component_type_ = outer->component_type_;
- array_rank = outer->array_rank_ + 1;
+ // want the base class, not "outer", in our component_type
+ component_type = outer->GetComponentType();
+ array_rank = outer->GetArrayRank() + 1;
} else {
- DCHECK(component_type_ == NULL); // make sure we fail
+ DCHECK(component_type == NULL); // make sure we fail
}
} else {
array_rank = 1;
if (descriptor[1] == 'L') {
// array of objects; strip off "[" and look up descriptor.
const StringPiece subDescriptor = descriptor.substr(1);
- component_type_ = FindClass(subDescriptor, class_loader);
+ component_type = FindClass(subDescriptor, class_loader);
} else {
// array of a primitive type
- component_type_ = FindPrimitiveClass(descriptor[1]);
+ component_type = FindPrimitiveClass(descriptor[1]);
}
}
- if (component_type_ == NULL) {
+ if (component_type == NULL) {
// failed
// DCHECK(Thread::Current()->IsExceptionPending()); // TODO
return NULL;
@@ -939,14 +1008,14 @@ Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
// If we find it, the caller adds "loader" to the class' initiating
// loader list, which should prevent us from going through this again.
//
- // This call is unnecessary if "loader" and "component_type_->class_loader_"
+ // This call is unnecessary if "loader" and "component_type->GetClassLoader()"
// are the same, because our caller (FindClass) just did the
// lookup. (Even if we get this wrong we still have correct behavior,
// because we effectively do this lookup again when we add the new
// class to the hash table --- necessary because of possible races with
// other threads.)
- if (class_loader != component_type_->class_loader_) {
- Class* new_class = LookupClass(descriptor, component_type_->class_loader_);
+ if (class_loader != component_type->GetClassLoader()) {
+ Class* new_class = LookupClass(descriptor, component_type->GetClassLoader());
if (new_class != NULL) {
return new_class;
}
@@ -963,6 +1032,7 @@ Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
Class* new_class = NULL;
if (!init_done_) {
+ // Classes that were hand created, ie not by FindSystemClass
if (descriptor == "[Ljava/lang/Object;") {
new_class = GetClassRoot(kObjectArrayClass);
} else if (descriptor == "[C") {
@@ -976,17 +1046,19 @@ Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
if (new_class == NULL) {
return NULL;
}
+ new_class->SetArrayRank(array_rank);
+ new_class->SetComponentType(component_type);
}
- new_class->descriptor_ = String::AllocFromModifiedUtf8(descriptor.ToString().c_str());
+ DCHECK_LE(1, new_class->GetArrayRank());
+ DCHECK(new_class->GetComponentType() != NULL);
+ new_class->SetDescriptor(String::AllocFromModifiedUtf8(descriptor.ToString().c_str()));
Class* java_lang_Object = GetClassRoot(kJavaLangObject);
- new_class->super_class_ = java_lang_Object;
- new_class->vtable_ = java_lang_Object->vtable_;
- new_class->primitive_type_ = Class::kPrimNot;
- new_class->component_type_ = component_type_;
- new_class->class_loader_ = component_type_->class_loader_;
- new_class->array_rank_ = array_rank;
- new_class->status_ = Class::kStatusInitialized;
- // don't need to set new_class->object_size_
+ new_class->SetSuperClass(java_lang_Object);
+ new_class->SetVTable(java_lang_Object->GetVTable());
+ new_class->SetPrimitiveType(Class::kPrimNot);
+ new_class->SetClassLoader(component_type->GetClassLoader());
+ new_class->SetStatus(Class::kStatusInitialized);
+ // don't need to set new_class->SetObjectSize(..)
// because Object::SizeOf delegates to Array::SizeOf
@@ -1002,21 +1074,19 @@ Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
// Use the single, global copies of "interfaces" and "iftable"
// (remember not to free them for arrays).
- DCHECK(array_interfaces_ != NULL);
- new_class->interfaces_ = array_interfaces_;
- new_class->iftable_count_ = 2;
- DCHECK(array_iftable_ != NULL);
- new_class->iftable_ = array_iftable_;
+ new_class->SetInterfaces(array_interfaces_);
+ new_class->SetIFTableCount(2);
+ new_class->SetIFTable(array_iftable_);
// Inherit access flags from the component type. Arrays can't be
// used as a superclass or interface, so we want to add "final"
// and remove "interface".
//
// Don't inherit any non-standard flags (e.g., kAccFinal)
- // from component_type_. We assume that the array class does not
+ // from component_type. We assume that the array class does not
// override finalize().
- new_class->access_flags_ = ((new_class->component_type_->access_flags_ &
- ~kAccInterface) | kAccFinal) & kAccJavaFlagsMask;
+ new_class->SetAccessFlags(((new_class->GetComponentType()->GetAccessFlags() &
+ ~kAccInterface) | kAccFinal) & kAccJavaFlagsMask);
if (InsertClass(descriptor, new_class)) {
return new_class;
@@ -1028,7 +1098,7 @@ Class* ClassLinker::CreateArrayClass(const StringPiece& descriptor,
// (Yes, this happens.)
// Grab the winning class.
- Class* other_class = LookupClass(descriptor, component_type_->class_loader_);
+ Class* other_class = LookupClass(descriptor, component_type->GetClassLoader());
DCHECK(other_class != NULL);
return other_class;
}
@@ -1070,10 +1140,10 @@ bool ClassLinker::InsertClass(const StringPiece& descriptor, Class* klass) {
Class* ClassLinker::LookupClass(const StringPiece& descriptor, const ClassLoader* class_loader) {
size_t hash = StringPieceHash()(descriptor);
MutexLock mu(classes_lock_);
- typedef Table::const_iterator It; // TODO: C++0x auto
+ typedef Table::const_iterator It; // TODO: C++0x auto
for (It it = classes_.find(hash), end = classes_.end(); it != end; ++it) {
Class* klass = it->second;
- if (klass->descriptor_->Equals(descriptor) && klass->class_loader_ == class_loader) {
+ if (klass->GetDescriptor()->Equals(descriptor) && klass->GetClassLoader() == class_loader) {
return klass;
}
}
@@ -1097,7 +1167,7 @@ bool ClassLinker::InitializeClass(Class* klass) {
CHECK(klass->GetStatus() == Class::kStatusResolved);
- klass->status_ = Class::kStatusVerifying;
+ klass->SetStatus(Class::kStatusVerifying);
if (!DexVerify::VerifyClass(klass)) {
LG << "Verification failed"; // TODO: ThrowVerifyError
Object* exception = self->GetException();
@@ -1109,13 +1179,13 @@ bool ClassLinker::InitializeClass(Class* klass) {
klass->SetStatus(Class::kStatusVerified);
}
- if (klass->status_ == Class::kStatusInitialized) {
+ if (klass->GetStatus() == Class::kStatusInitialized) {
return true;
}
- while (klass->status_ == Class::kStatusInitializing) {
+ while (klass->GetStatus() == Class::kStatusInitializing) {
// we caught somebody else in the act; was it us?
- if (klass->clinit_thread_id_ == self->GetId()) {
+ if (klass->GetClinitThreadId() == self->GetId()) {
LG << "recursive <clinit>";
return true;
}
@@ -1161,10 +1231,10 @@ bool ClassLinker::InitializeClass(Class* klass) {
return false;
}
- DCHECK(klass->status_ < Class::kStatusInitializing);
+ DCHECK(klass->GetStatus() < Class::kStatusInitializing);
- klass->clinit_thread_id_ = self->GetId();
- klass->status_ = Class::kStatusInitializing;
+ klass->SetClinitThreadId(self->GetId());
+ klass->SetStatus(Class::kStatusInitializing);
}
if (!InitializeSuperClass(klass)) {
@@ -1211,12 +1281,12 @@ bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) {
}
}
}
- for (size_t i = 0; i < klass->iftable_count_; ++i) {
- const InterfaceEntry* iftable = &klass->iftable_[i];
+ for (size_t i = 0; i < klass->GetIFTableCount(); ++i) {
+ const InterfaceEntry* iftable = &klass->GetIFTable()[i];
Class* interface = iftable->GetInterface();
if (klass->GetClassLoader() != interface->GetClassLoader()) {
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
- uint32_t vtable_index = iftable->method_index_array_[j];
+ uint32_t vtable_index = iftable->GetMethodIndexArray()[j];
const Method* method = klass->GetVirtualMethod(vtable_index);
if (!HasSameMethodDescriptorClasses(method, interface,
method->GetClass())) {
@@ -1233,7 +1303,7 @@ bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
const Class* klass1,
const Class* klass2) {
const DexFile& dex_file = FindDexFile(method->GetClass()->GetDexCache());
- const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->proto_idx_);
+ const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
DexFile::ParameterIterator *it;
for (it = dex_file.GetParameterIterator(proto_id); it->HasNext(); it->Next()) {
const char* descriptor = it->GetDescriptor();
@@ -1391,8 +1461,8 @@ void ClassLinker::InitializeStaticFields(Class* klass) {
}
}
-bool ClassLinker::LinkClass(Class* klass, const DexFile& dex_file) {
- CHECK_EQ(Class::kStatusLoaded, klass->status_);
+bool ClassLinker::LinkClass(Class* klass) {
+ CHECK_EQ(Class::kStatusLoaded, klass->GetStatus());
if (!LinkSuperClass(klass)) {
return false;
}
@@ -1407,44 +1477,43 @@ bool ClassLinker::LinkClass(Class* klass, const DexFile& dex_file) {
}
CreateReferenceInstanceOffsets(klass);
CreateReferenceStaticOffsets(klass);
- CHECK_EQ(Class::kStatusLoaded, klass->status_);
- klass->status_ = Class::kStatusResolved;
+ CHECK_EQ(Class::kStatusLoaded, klass->GetStatus());
+ klass->SetStatus(Class::kStatusResolved);
return true;
}
bool ClassLinker::LoadSuperAndInterfaces(Class* klass, const DexFile& dex_file) {
- CHECK_EQ(Class::kStatusIdx, klass->status_);
- if (klass->super_class_type_idx_ != DexFile::kDexNoIndex) {
- Class* super_class = ResolveType(dex_file, klass->super_class_type_idx_, klass);
+ CHECK_EQ(Class::kStatusIdx, klass->GetStatus());
+ if (klass->GetSuperClassTypeIdx() != DexFile::kDexNoIndex) {
+ Class* super_class = ResolveType(dex_file, klass->GetSuperClassTypeIdx(), klass);
if (super_class == NULL) {
LG << "Failed to resolve superclass";
return false;
}
- klass->super_class_ = super_class; // TODO: write barrier
+ klass->SetSuperClass(super_class);
}
- if (klass->NumInterfaces() > 0) {
- for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
- uint32_t type_idx = klass->interfaces_type_idx_->Get(i);
- klass->SetInterface(i, ResolveType(dex_file, type_idx, klass));
- if (klass->GetInterface(i) == NULL) {
- LG << "Failed to resolve interface";
- return false;
- }
- // Verify
- if (!klass->CanAccess(klass->GetInterface(i))) {
- LG << "Inaccessible interface";
- return false;
- }
+ for (size_t i = 0; i < klass->NumInterfaces(); ++i) {
+ uint32_t idx = klass->GetInterfacesTypeIdx()->Get(i);
+ Class *interface = ResolveType(dex_file, idx, klass);
+ klass->SetInterface(i, interface);
+ if (interface == NULL) {
+ LG << "Failed to resolve interface";
+ return false;
+ }
+ // Verify
+ if (!klass->CanAccess(interface)) {
+ LG << "Inaccessible interface";
+ return false;
}
}
// Mark the class as loaded.
- klass->status_ = Class::kStatusLoaded;
+ klass->SetStatus(Class::kStatusLoaded);
return true;
}
bool ClassLinker::LinkSuperClass(Class* klass) {
CHECK(!klass->IsPrimitive());
- const Class* super = klass->GetSuperClass();
+ Class* super = klass->GetSuperClass();
if (klass->GetDescriptor()->Equals("Ljava/lang/Object;")) {
if (super != NULL) {
LG << "Superclass must not be defined"; // TODO: ClassFormatError
@@ -1459,21 +1528,28 @@ bool ClassLinker::LinkSuperClass(Class* klass) {
}
// Verify
if (super->IsFinal()) {
- LG << "Superclass " << super->descriptor_->ToModifiedUtf8() << " is declared final"; // TODO: IncompatibleClassChangeError
+ LG << "Superclass " << super->GetDescriptor()->ToModifiedUtf8() << " is declared final"; // TODO: IncompatibleClassChangeError
return false;
}
if (super->IsInterface()) {
- LG << "Superclass " << super->descriptor_->ToModifiedUtf8() << " is an interface"; // TODO: IncompatibleClassChangeError
+ LG << "Superclass " << super->GetDescriptor()->ToModifiedUtf8() << " is an interface"; // TODO: IncompatibleClassChangeError
return false;
}
if (!klass->CanAccess(super)) {
- LG << "Superclass " << super->descriptor_->ToModifiedUtf8() << " is inaccessible"; // TODO: IllegalAccessError
+ LG << "Superclass " << super->GetDescriptor()->ToModifiedUtf8() << " is inaccessible"; // TODO: IllegalAccessError
return false;
}
+#ifndef NDEBUG
+ // Ensure super classes are fully resolved prior to resolving fields..
+ while (super != NULL) {
+ CHECK(super->IsLinked());
+ super = super->GetSuperClass();
+ }
+#endif
return true;
}
-// Populate the class vtable and itable.
+// Populate the class vtable and itable. Compute return type indices.
bool ClassLinker::LinkMethods(Class* klass) {
if (klass->IsInterface()) {
// No vtable.
@@ -1483,7 +1559,7 @@ bool ClassLinker::LinkMethods(Class* klass) {
return false;
}
for (size_t i = 0; i < count; ++i) {
- klass->GetVirtualMethod(i)->method_index_ = i;
+ klass->GetVirtualMethodDuringLinking(i)->SetMethodIndex(i);
}
} else {
// Link virtual method tables
@@ -1500,32 +1576,32 @@ bool ClassLinker::LinkMethods(Class* klass) {
bool ClassLinker::LinkVirtualMethods(Class* klass) {
if (klass->HasSuperClass()) {
- uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->vtable_->GetLength();
- size_t actual_count = klass->GetSuperClass()->vtable_->GetLength();
+ uint32_t max_count = klass->NumVirtualMethods() + klass->GetSuperClass()->GetVTable()->GetLength();
+ size_t actual_count = klass->GetSuperClass()->GetVTable()->GetLength();
CHECK_LE(actual_count, max_count);
// TODO: do not assign to the vtable field until it is fully constructed.
- klass->vtable_ = klass->GetSuperClass()->vtable_->CopyOf(max_count);
+ ObjectArray<Method>* vtable = klass->GetSuperClass()->GetVTable()->CopyOf(max_count);
// See if any of our virtual methods override the superclass.
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
- Method* local_method = klass->GetVirtualMethod(i);
+ Method* local_method = klass->GetVirtualMethodDuringLinking(i);
size_t j = 0;
for (; j < actual_count; ++j) {
- Method* super_method = klass->vtable_->Get(j);
+ Method* super_method = vtable->Get(j);
if (local_method->HasSameNameAndDescriptor(super_method)) {
// Verify
if (super_method->IsFinal()) {
LG << "Method overrides final method"; // TODO: VirtualMachineError
return false;
}
- klass->vtable_->Set(j, local_method);
- local_method->method_index_ = j;
+ vtable->Set(j, local_method);
+ local_method->SetMethodIndex(j);
break;
}
}
if (j == actual_count) {
// Not overriding, append.
- klass->vtable_->Set(actual_count, local_method);
- local_method->method_index_ = actual_count;
+ vtable->Set(actual_count, local_method);
+ local_method->SetMethodIndex(actual_count);
actual_count += 1;
}
}
@@ -1533,11 +1609,12 @@ bool ClassLinker::LinkVirtualMethods(Class* klass) {
LG << "Too many methods defined on class"; // TODO: VirtualMachineError
return false;
}
+ // Shrink vtable if possible
CHECK_LE(actual_count, max_count);
if (actual_count < max_count) {
- // TODO: do not assign to the vtable field until it is fully constructed.
- klass->vtable_ = klass->vtable_->CopyOf(actual_count);
+ vtable = vtable->CopyOf(actual_count);
}
+ klass->SetVTable(vtable);
} else {
CHECK(klass->GetDescriptor()->Equals("Ljava/lang/Object;"));
uint32_t num_virtual_methods = klass->NumVirtualMethods();
@@ -1545,12 +1622,13 @@ bool ClassLinker::LinkVirtualMethods(Class* klass) {
LG << "Too many methods"; // TODO: VirtualMachineError
return false;
}
- // TODO: do not assign to the vtable field until it is fully constructed.
- klass->vtable_ = AllocObjectArray<Method>(num_virtual_methods);
+ ObjectArray<Method>* vtable = AllocObjectArray<Method>(num_virtual_methods);
for (size_t i = 0; i < num_virtual_methods; ++i) {
- klass->vtable_->Set(i, klass->GetVirtualMethod(i));
- klass->GetVirtualMethod(i)->method_index_ = i & 0xFFFF;
+ Method* virtual_method = klass->GetVirtualMethodDuringLinking(i);
+ vtable->Set(i, virtual_method);
+ virtual_method->SetMethodIndex(i & 0xFFFF);
}
+ klass->SetVTable(vtable);
}
return true;
}
@@ -1562,24 +1640,25 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
int miranda_alloc = 0;
size_t super_ifcount;
if (klass->HasSuperClass()) {
- super_ifcount = klass->GetSuperClass()->iftable_count_;
+ super_ifcount = klass->GetSuperClass()->GetIFTableCount();
} else {
super_ifcount = 0;
}
size_t ifcount = super_ifcount;
ifcount += klass->NumInterfaces();
for (size_t i = 0; i < klass->NumInterfaces(); i++) {
- ifcount += klass->GetInterface(i)->iftable_count_;
+ ifcount += klass->GetInterface(i)->GetIFTableCount();
}
if (ifcount == 0) {
- DCHECK(klass->iftable_count_ == 0);
- DCHECK(klass->iftable_ == NULL);
+ // TODO: enable these asserts with klass status validation
+ // DCHECK(klass->GetIFTableCount() == 0);
+ // DCHECK(klass->GetIFTable() == NULL);
return true;
}
- klass->iftable_ = new InterfaceEntry[ifcount * sizeof(InterfaceEntry)];
- memset(klass->iftable_, 0x00, sizeof(InterfaceEntry) * ifcount);
+ InterfaceEntry* iftable = new InterfaceEntry[ifcount];
+ memset(iftable, 0x00, sizeof(InterfaceEntry) * ifcount);
if (super_ifcount != 0) {
- memcpy(klass->iftable_, klass->GetSuperClass()->iftable_,
+ memcpy(iftable, klass->GetSuperClass()->GetIFTable(),
sizeof(InterfaceEntry) * super_ifcount);
}
// Flatten the interface inheritance hierarchy.
@@ -1591,40 +1670,43 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
LG << "Class implements non-interface class"; // TODO: IncompatibleClassChangeError
return false;
}
- klass->iftable_[idx++].SetInterface(interf);
- for (size_t j = 0; j < interf->iftable_count_; j++) {
- klass->iftable_[idx++].SetInterface(interf->iftable_[j].GetInterface());
+ iftable[idx++].SetInterface(interf);
+ for (size_t j = 0; j < interf->GetIFTableCount(); j++) {
+ iftable[idx++].SetInterface(interf->GetIFTable()[j].GetInterface());
}
}
+ klass->SetIFTable(iftable);
CHECK_EQ(idx, ifcount);
- klass->iftable_count_ = ifcount;
+ klass->SetIFTableCount(ifcount);
if (klass->IsInterface() || super_ifcount == ifcount) {
return true;
}
for (size_t i = super_ifcount; i < ifcount; i++) {
- pool_size += klass->iftable_[i].GetInterface()->NumVirtualMethods();
+ pool_size += iftable[i].GetInterface()->NumVirtualMethods();
}
if (pool_size == 0) {
return true;
}
- klass->ifvi_pool_count_ = pool_size;
- klass->ifvi_pool_ = new uint32_t[pool_size];
+ klass->SetIfviPoolCount(pool_size);
+ uint32_t* ifvi_pool = new uint32_t[pool_size];
+ klass->SetIfviPool(ifvi_pool);
std::vector<Method*> miranda_list;
for (size_t i = super_ifcount; i < ifcount; ++i) {
- klass->iftable_[i].method_index_array_ = klass->ifvi_pool_ + pool_offset;
- Class* interface = klass->iftable_[i].GetInterface();
+ iftable[i].SetMethodIndexArray(ifvi_pool + pool_offset);
+ Class* interface = iftable[i].GetInterface();
pool_offset += interface->NumVirtualMethods(); // end here
+ ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
for (size_t j = 0; j < interface->NumVirtualMethods(); ++j) {
Method* interface_method = interface->GetVirtualMethod(j);
int k; // must be signed
- for (k = klass->vtable_->GetLength() - 1; k >= 0; --k) {
- Method* vtable_method = klass->vtable_->Get(k);
+ for (k = vtable->GetLength() - 1; k >= 0; --k) {
+ Method* vtable_method = vtable->Get(k);
if (interface_method->HasSameNameAndDescriptor(vtable_method)) {
if (!vtable_method->IsPublic()) {
LG << "Implementation not public";
return false;
}
- klass->iftable_[i].method_index_array_[j] = k;
+ iftable[i].GetMethodIndexArray()[j] = k;
break;
}
}
@@ -1645,7 +1727,8 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
}
}
// point the interface table at a phantom slot index
- klass->iftable_[i].method_index_array_[j] = klass->vtable_->GetLength() + mir;
+ iftable[i].GetMethodIndexArray()[j] =
+ vtable->GetLength() + mir;
if (mir == miranda_count) {
miranda_list[miranda_count++] = interface_method;
}
@@ -1655,30 +1738,33 @@ bool ClassLinker::LinkInterfaceMethods(Class* klass) {
if (miranda_count != 0) {
int old_method_count = klass->NumVirtualMethods();
int new_method_count = old_method_count + miranda_count;
- klass->virtual_methods_ = klass->virtual_methods_->CopyOf(new_method_count);
+ klass->SetVirtualMethods(
+ klass->GetVirtualMethods()->CopyOf(new_method_count));
- CHECK(klass->vtable_ != NULL);
- int old_vtable_count = klass->vtable_->GetLength();
+ ObjectArray<Method>* vtable = klass->GetVTableDuringLinking();
+ CHECK(vtable != NULL);
+ int old_vtable_count = vtable->GetLength();
int new_vtable_count = old_vtable_count + miranda_count;
- // TODO: do not assign to the vtable field until it is fully constructed.
- klass->vtable_ = klass->vtable_->CopyOf(new_vtable_count);
-
+ vtable = vtable->CopyOf(new_vtable_count);
for (int i = 0; i < miranda_count; i++) {
Method* meth = AllocMethod();
+ // TODO: this shouldn't be a memcpy
memcpy(meth, miranda_list[i], sizeof(Method));
- meth->klass_ = klass;
- meth->access_flags_ |= kAccMiranda;
- meth->method_index_ = 0xFFFF & (old_vtable_count + i);
+ meth->SetDeclaringClass(klass);
+ meth->SetAccessFlags(meth->GetAccessFlags() | kAccMiranda);
+ meth->SetMethodIndex(0xFFFF & (old_vtable_count + i));
klass->SetVirtualMethod(old_method_count + i, meth);
- klass->vtable_->Set(old_vtable_count + i, meth);
+ vtable->Set(old_vtable_count + i, meth);
}
+ // TODO: do not assign to the vtable field until it is fully constructed.
+ klass->SetVTable(vtable);
}
return true;
}
void ClassLinker::LinkAbstractMethods(Class* klass) {
for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
- Method* method = klass->GetVirtualMethod(i);
+ Method* method = klass->GetVirtualMethodDuringLinking(i);
if (method->IsAbstract()) {
LG << "AbstractMethodError";
// TODO: throw AbstractMethodError
@@ -1688,53 +1774,64 @@ void ClassLinker::LinkAbstractMethods(Class* klass) {
bool ClassLinker::LinkInstanceFields(Class* klass) {
CHECK(klass != NULL);
- size_t field_offset;
- if (klass->GetSuperClass() != NULL) {
- field_offset = klass->GetSuperClass()->object_size_;
- } else {
- field_offset = OFFSETOF_MEMBER(DataObject, fields_);
- }
- return LinkFields(field_offset,
- klass->num_reference_instance_fields_,
- klass->NumInstanceFields(),
- klass->ifields_,
- klass->object_size_);
+ return LinkFields(klass, true);
}
bool ClassLinker::LinkStaticFields(Class* klass) {
CHECK(klass != NULL);
- size_t allocated_class_size = klass->class_size_;
- size_t field_offset = OFFSETOF_MEMBER(Class, fields_);
- bool success = LinkFields(field_offset,
- klass->num_reference_static_fields_,
- klass->NumStaticFields(),
- klass->sfields_,
- klass->class_size_);
- CHECK_EQ(allocated_class_size, klass->class_size_);
+ size_t allocated_class_size = klass->GetClassSize();
+ bool success = LinkFields(klass, false);
+ CHECK_EQ(allocated_class_size, klass->GetClassSize());
return success;
}
-bool ClassLinker::LinkFields(size_t field_offset,
- size_t& num_reference_fields,
- size_t num_fields,
- ObjectArray<Field>* fields,
- size_t& size) {
+bool ClassLinker::LinkFields(Class *klass, bool instance) {
+ size_t num_fields =
+ instance ? klass->NumInstanceFields() : klass->NumStaticFields();
+
+ ObjectArray<Field>* fields =
+ instance ? klass->GetIFields() : klass->GetSFields();
+ // Fields updated at end of LinkFields
+ size_t num_reference_fields;
+ size_t size;
+
+ // Initialize size and field_offset
+ MemberOffset field_offset = Class::FieldsOffset();
+ if (instance) {
+ Class* super_class = klass->GetSuperClass();
+ if (super_class != NULL) {
+ CHECK(super_class->IsLinked());
+ field_offset = MemberOffset(super_class->GetObjectSize());
+ if (field_offset.Uint32Value() == 0u) {
+ field_offset = OFFSET_OF_OBJECT_MEMBER(DataObject, fields_);
+ }
+ } else {
+ field_offset = OFFSET_OF_OBJECT_MEMBER(DataObject, fields_);
+ }
+ size = field_offset.Uint32Value();
+ } else {
+ size = klass->GetClassSize();
+ }
+ DCHECK_LE(CLASS_SMALLEST_OFFSET, size);
+
CHECK((num_fields == 0) == (fields == NULL));
+
// Move references to the front.
- num_reference_fields = 0;
size_t i = 0;
- for ( ; i < num_fields; i++) {
- Field* pField = fields->Get(i);
- char c = pField->GetType();
- if (c != '[' && c != 'L') {
+ num_reference_fields = 0;
+ for (; i < num_fields; i++) {
+ Field* field = fields->Get(i);
+ const Class* field_type = field->GetTypeDuringLinking();
+ // if a field's type at this point is NULL it isn't primitive
+ if (field_type != NULL && field_type->IsPrimitive()) {
for (size_t j = num_fields - 1; j > i; j--) {
- Field* refField = fields->Get(j);
- char rc = refField->GetType();
- if (rc == '[' || rc == 'L') {
- fields->Set(i, refField);
- fields->Set(j, pField);
- pField = refField;
- c = rc;
+ Field* ref_field = fields->Get(j);
+ const Class* ref_field_type = ref_field->GetTypeDuringLinking();
+ if (ref_field_type == NULL || !ref_field_type->IsPrimitive()) {
+ fields->Set(i, ref_field);
+ fields->Set(j, field);
+ field = ref_field;
+ field_type = ref_field_type;
num_reference_fields++;
break;
}
@@ -1742,65 +1839,70 @@ bool ClassLinker::LinkFields(size_t field_offset,
} else {
num_reference_fields++;
}
- if (c != '[' && c != 'L') {
+ if (field_type != NULL && field_type->IsPrimitive()) {
break;
}
- pField->SetOffset(field_offset);
- field_offset += sizeof(uint32_t);
+ field->SetOffset(field_offset);
+ field_offset = MemberOffset(field_offset.Uint32Value() + sizeof(uint32_t));
}
// Now we want to pack all of the double-wide fields together. If
// we're not aligned, though, we want to shuffle one 32-bit field
// into place. If we can't find one, we'll have to pad it.
- if (i != num_fields && (field_offset & 0x04) != 0) {
- Field* pField = fields->Get(i);
- char c = pField->GetType();
-
- if (c != 'J' && c != 'D') {
+ if (i != num_fields && !IsAligned(field_offset.Uint32Value(), 8)) {
+ Field* field = fields->Get(i);
+ const Class* c = field->GetTypeDuringLinking();
+ CHECK(c != NULL); // should only be working on primitive types
+ if (!c->IsPrimitiveLong() && !c->IsPrimitiveDouble()) {
// The field that comes next is 32-bit, so just advance past it.
- DCHECK(c != '[');
- DCHECK(c != 'L');
- pField->SetOffset(field_offset);
- field_offset += sizeof(uint32_t);
+ DCHECK(c->IsPrimitive());
+ field->SetOffset(field_offset);
+ field_offset = MemberOffset(field_offset.Uint32Value() +
+ sizeof(uint32_t));
i++;
} else {
// Next field is 64-bit, so search for a 32-bit field we can
// swap into it.
bool found = false;
for (size_t j = num_fields - 1; j > i; j--) {
- Field* singleField = fields->Get(j);
- char rc = singleField->GetType();
- if (rc != 'J' && rc != 'D') {
- fields->Set(i, singleField);
- fields->Set(j, pField);
- pField = singleField;
- pField->SetOffset(field_offset);
- field_offset += sizeof(uint32_t);
+ Field* single_field = fields->Get(j);
+ const Class* rc = single_field->GetTypeDuringLinking();
+ CHECK(rc != NULL); // should only be working on primitive types
+ if (!rc->IsPrimitiveLong() && !rc->IsPrimitiveDouble()) {
+ fields->Set(i, single_field);
+ fields->Set(j, field);
+ field = single_field;
+ field->SetOffset(field_offset);
+ field_offset = MemberOffset(field_offset.Uint32Value() +
+ sizeof(uint32_t));
found = true;
i++;
break;
}
}
if (!found) {
- field_offset += sizeof(uint32_t);
+ field_offset = MemberOffset(field_offset.Uint32Value() +
+ sizeof(uint32_t));
}
}
}
// Alignment is good, shuffle any double-wide fields forward, and
// finish assigning field offsets to all fields.
- DCHECK(i == num_fields || (field_offset & 0x04) == 0);
+ DCHECK(i == num_fields || IsAligned(field_offset.Uint32Value(), 4));
for ( ; i < num_fields; i++) {
- Field* pField = fields->Get(i);
- char c = pField->GetType();
- if (c != 'D' && c != 'J') {
+ Field* field = fields->Get(i);
+ const Class* c = field->GetTypeDuringLinking();
+ CHECK(c != NULL); // should only be working on primitive types
+ if (!c->IsPrimitiveDouble() && !c->IsPrimitiveLong()) {
for (size_t j = num_fields - 1; j > i; j--) {
- Field* doubleField = fields->Get(j);
- char rc = doubleField->GetType();
- if (rc == 'D' || rc == 'J') {
- fields->Set(i, doubleField);
- fields->Set(j, pField);
- pField = doubleField;
+ Field* double_field = fields->Get(j);
+ const Class* rc = double_field->GetTypeDuringLinking();
+ CHECK(rc != NULL); // should only be working on primitive types
+ if (rc->IsPrimitiveDouble() || rc->IsPrimitiveLong()) {
+ fields->Set(i, double_field);
+ fields->Set(j, field);
+ field = double_field;
c = rc;
break;
}
@@ -1809,10 +1911,13 @@ bool ClassLinker::LinkFields(size_t field_offset,
// This is a double-wide field, leave it be.
}
- pField->SetOffset(field_offset);
- field_offset += sizeof(uint32_t);
- if (c == 'J' || c == 'D') {
- field_offset += sizeof(uint32_t);
+ field->SetOffset(field_offset);
+ if (c->IsPrimitiveLong() || c->IsPrimitiveDouble()) {
+ field_offset = MemberOffset(field_offset.Uint32Value() +
+ sizeof(uint64_t));
+ } else {
+ field_offset = MemberOffset(field_offset.Uint32Value() +
+ sizeof(uint32_t));
}
}
@@ -1821,14 +1926,9 @@ bool ClassLinker::LinkFields(size_t field_offset,
// non-reference fields, and all double-wide fields are aligned.
bool seen_non_ref = false;
for (i = 0; i < num_fields; i++) {
- Field *pField = fields->Get(i);
- char c = pField->GetType();
-
- if (c == 'D' || c == 'J') {
- DCHECK_EQ(0U, pField->GetOffset() & 0x07);
- }
-
- if (c != '[' && c != 'L') {
+ Field* field = fields->Get(i);
+ const Class* c = field->GetTypeDuringLinking();
+ if (c != NULL && c->IsPrimitive()) {
if (!seen_non_ref) {
seen_non_ref = true;
DCHECK_EQ(num_reference_fields, i);
@@ -1841,47 +1941,59 @@ bool ClassLinker::LinkFields(size_t field_offset,
DCHECK_EQ(num_fields, num_reference_fields);
}
#endif
- size = field_offset;
+ size = field_offset.Uint32Value();
+ DCHECK_LE(CLASS_SMALLEST_OFFSET, size);
+ // Update klass
+ if(instance) {
+ klass->SetNumReferenceInstanceFields(num_reference_fields);
+ if(!klass->IsVariableSize()) {
+ klass->SetObjectSize(size);
+ }
+ } else {
+ klass->SetNumReferenceStaticFields(num_reference_fields);
+ klass->SetClassSize(size);
+ }
return true;
}
// Set the bitmap of reference offsets, refOffsets, from the ifields
// list.
void ClassLinker::CreateReferenceInstanceOffsets(Class* klass) {
- klass->reference_instance_offsets_ = 0;
- if (klass->HasSuperClass()) {
- klass->reference_instance_offsets_ = klass->GetSuperClass()->GetReferenceInstanceOffsets();
+ uint32_t reference_offsets = 0;
+ Class* super_class = klass->GetSuperClass();
+ if (super_class != NULL) {
+ reference_offsets = super_class->GetReferenceInstanceOffsets();
// If our superclass overflowed, we don't stand a chance.
- if (klass->reference_instance_offsets_ == CLASS_WALK_SUPER) {
+ if (reference_offsets == CLASS_WALK_SUPER) {
+ klass->SetReferenceInstanceOffsets(reference_offsets);
return;
}
}
- CreateReferenceOffsets(klass->reference_instance_offsets_,
- klass->NumReferenceInstanceFields(),
- klass->ifields_);
+ CreateReferenceOffsets(klass, true, reference_offsets);
}
void ClassLinker::CreateReferenceStaticOffsets(Class* klass) {
- klass->reference_static_offsets_ = 0;
- CreateReferenceOffsets(klass->reference_static_offsets_,
- klass->NumReferenceStaticFields(),
- klass->sfields_);
+ CreateReferenceOffsets(klass, false, 0);
}
-void ClassLinker::CreateReferenceOffsets(uint32_t& reference_offsets,
- size_t num_reference_fields,
- const ObjectArray<Field>* fields) {
+void ClassLinker::CreateReferenceOffsets(Class* klass, bool instance,
+ uint32_t reference_offsets) {
+ size_t num_reference_fields =
+ instance ? klass->NumReferenceInstanceFieldsDuringLinking()
+ : klass->NumReferenceStaticFieldsDuringLinking();
+ const ObjectArray<Field>* fields =
+ instance ? klass->GetIFields() : klass->GetSFields();
// All of the fields that contain object references are guaranteed
// to be at the beginning of the fields list.
for (size_t i = 0; i < num_reference_fields; ++i) {
// Note that byte_offset is the offset from the beginning of
// object, not the offset into instance data
const Field* field = fields->Get(i);
- size_t byte_offset = field->GetOffset();
- CHECK_GE(byte_offset, CLASS_SMALLEST_OFFSET);
- CHECK_EQ(byte_offset & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
- if (CLASS_CAN_ENCODE_OFFSET(byte_offset)) {
- uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset);
+ MemberOffset byte_offset = field->GetOffsetDuringLinking();
+ CHECK_GE(byte_offset.Uint32Value(), CLASS_SMALLEST_OFFSET);
+ CHECK_EQ(byte_offset.Uint32Value() & (CLASS_OFFSET_ALIGNMENT - 1), 0U);
+ if (CLASS_CAN_ENCODE_OFFSET(byte_offset.Uint32Value())) {
+ uint32_t new_bit = CLASS_BIT_FROM_OFFSET(byte_offset.Uint32Value());
CHECK_NE(new_bit, 0U);
reference_offsets |= new_bit;
} else {
@@ -1889,18 +2001,25 @@ void ClassLinker::CreateReferenceOffsets(uint32_t& reference_offsets,
break;
}
}
+ // Update fields in klass
+ if (instance) {
+ klass->SetReferenceInstanceOffsets(reference_offsets);
+ } else {
+ klass->SetReferenceStaticOffsets(reference_offsets);
+ }
}
-const String* ClassLinker::ResolveString(const DexFile& dex_file,
+String* ClassLinker::ResolveString(const DexFile& dex_file,
uint32_t string_idx, DexCache* dex_cache) {
- const String* resolved = dex_cache->GetResolvedString(string_idx);
+ String* resolved = dex_cache->GetResolvedString(string_idx);
if (resolved != NULL) {
return resolved;
}
const DexFile::StringId& string_id = dex_file.GetStringId(string_idx);
int32_t utf16_length = dex_file.GetStringLength(string_id);
const char* utf8_data = dex_file.GetStringData(string_id);
- const String* string = intern_table_->InternStrong(utf16_length, utf8_data);
+ // TODO: remote the const_cast below
+ String* string = const_cast<String*>(intern_table_->InternStrong(utf16_length, utf8_data));
dex_cache->SetResolvedString(string_idx, string);
return string;
}
@@ -1910,26 +2029,28 @@ Class* ClassLinker::ResolveType(const DexFile& dex_file,
DexCache* dex_cache,
const ClassLoader* class_loader) {
Class* resolved = dex_cache->GetResolvedType(type_idx);
- if (resolved != NULL) {
- return resolved;
- }
- const char* descriptor = dex_file.dexStringByTypeIdx(type_idx);
- if (descriptor[0] != '\0' && descriptor[1] == '\0') {
- resolved = FindPrimitiveClass(descriptor[0]);
- } else {
- resolved = FindClass(descriptor, class_loader);
- }
- if (resolved != NULL) {
- Class* check = resolved->IsArrayClass() ? resolved->component_type_ : resolved;
- if (dex_cache != check->GetDexCache()) {
- if (check->GetClassLoader() != NULL) {
- LG << "Class resolved by unexpected DEX"; // TODO: IllegalAccessError
- return NULL;
+ if (resolved == NULL) {
+ const char* descriptor = dex_file.dexStringByTypeIdx(type_idx);
+ if (descriptor[1] == '\0') {
+ // only the descriptors of primitive types should be 1 character long
+ resolved = FindPrimitiveClass(descriptor[0]);
+ } else {
+ resolved = FindClass(descriptor, class_loader);
+ }
+ if (resolved != NULL) {
+ Class* check = resolved->IsArrayClass() ? resolved->GetComponentType() : resolved;
+ if (dex_cache != check->GetDexCache()) {
+ if (check->GetClassLoader() != NULL) {
+ LG << "Class resolved by unexpected DEX"; // TODO: IllegalAccessError
+ resolved = NULL;
+ }
}
}
- dex_cache->SetResolvedType(type_idx, resolved);
- } else {
- DCHECK(Thread::Current()->IsExceptionPending());
+ if (resolved != NULL) {
+ dex_cache->SetResolvedType(type_idx, resolved);
+ } else {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ }
}
return resolved;
}
@@ -1980,16 +2101,18 @@ Field* ClassLinker::ResolveField(const DexFile& dex_file,
}
const char* name = dex_file.dexStringById(field_id.name_idx_);
- const char* type = dex_file.dexStringByTypeIdx(field_id.type_idx_);
+ Class* field_type = ResolveType(dex_file, field_id.type_idx_, dex_cache, class_loader);
+ // TODO: LinkageError?
+ CHECK(field_type != NULL);
if (is_static) {
- resolved = klass->FindStaticField(name, type);
+ resolved = klass->FindStaticField(name, field_type);
} else {
- resolved = klass->FindInstanceField(name, type);
+ resolved = klass->FindInstanceField(name, field_type);
}
if (resolved != NULL) {
dex_cache->SetResolvedfield(field_idx, resolved);
} else {
- // DCHECK(Thread::Current()->IsExceptionPending());
+ // TODO: DCHECK(Thread::Current()->IsExceptionPending());
}
return resolved;
}
diff --git a/src/class_linker.h b/src/class_linker.h
index 3f95b8d7bd..f63ab3c90b 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -45,7 +45,7 @@ class ClassLinker {
// Resolve a String with the given index from the DexFile, storing the
// result in the DexCache.
- const String* ResolveString(const DexFile& dex_file, uint32_t string_idx, DexCache* dex_cache);
+ String* ResolveString(const DexFile& dex_file, uint32_t string_idx, DexCache* dex_cache);
// Resolve a Type with the given index from the DexFile, storing the
// result in the DexCache. The referrer is used to identity the
@@ -60,11 +60,21 @@ class ClassLinker {
}
// Resolve a Type with the given index from the DexFile, storing the
- // result in the DexCache. The referrer is used to identity the
+ // result in the DexCache. The referrer is used to identify the
// target DexCache and ClassLoader to use for resolution.
Class* ResolveType(uint32_t type_idx, const Method* referrer) {
Class* declaring_class = referrer->GetDeclaringClass();
DexCache* dex_cache = declaring_class->GetDexCache();
+ // TODO: we could check for a dex cache hit here
+ const ClassLoader* class_loader = declaring_class->GetClassLoader();
+ const DexFile& dex_file = FindDexFile(dex_cache);
+ return ResolveType(dex_file, type_idx, dex_cache, class_loader);
+ }
+
+ Class* ResolveType(uint32_t type_idx, const Field* referrer) {
+ Class* declaring_class = referrer->GetDeclaringClass();
+ DexCache* dex_cache = declaring_class->GetDexCache();
+ // TODO: we could check for a dex cache hit here
const ClassLoader* class_loader = declaring_class->GetClassLoader();
const DexFile& dex_file = FindDexFile(dex_cache);
return ResolveType(dex_file, type_idx, dex_cache, class_loader);
@@ -96,6 +106,7 @@ class ClassLinker {
Field* ResolveField(uint32_t field_idx, const Method* referrer) {
Class* declaring_class = referrer->GetDeclaringClass();
DexCache* dex_cache = declaring_class->GetDexCache();
+ // TODO: we could check for a dex cache hit here
const ClassLoader* class_loader = declaring_class->GetClassLoader();
const DexFile& dex_file = FindDexFile(dex_cache);
return ResolveField(dex_file, field_idx, dex_cache, class_loader, true);
@@ -161,7 +172,8 @@ class ClassLinker {
Method* AllocMethod();
CodeAndDirectMethods* AllocCodeAndDirectMethods(size_t length);
- Class* CreatePrimitiveClass(const char* descriptor);
+ Class* CreatePrimitiveClass(const char* descriptor,
+ Class::PrimitiveType type);
Class* CreateArrayClass(const StringPiece& descriptor,
const ClassLoader* class_loader);
@@ -211,7 +223,7 @@ class ClassLinker {
const Class* klass1,
const Class* klass2);
- bool LinkClass(Class* klass, const DexFile& dex_file);
+ bool LinkClass(Class* klass);
bool LinkSuperClass(Class* klass);
@@ -227,17 +239,13 @@ class ClassLinker {
bool LinkStaticFields(Class* klass);
bool LinkInstanceFields(Class* klass);
- bool LinkFields(size_t field_offset,
- size_t& num_reference_fields,
- size_t num_fields,
- ObjectArray<Field>* fields,
- size_t& size);
+ bool LinkFields(Class *klass, bool instance);
+
void CreateReferenceInstanceOffsets(Class* klass);
void CreateReferenceStaticOffsets(Class* klass);
- void CreateReferenceOffsets(uint32_t& reference_offsets,
- size_t num_reference_fields,
- const ObjectArray<Field>* fields);
+ void CreateReferenceOffsets(Class *klass, bool instance,
+ uint32_t reference_offsets);
std::vector<const DexFile*> boot_class_path_;
@@ -298,9 +306,9 @@ class ClassLinker {
DCHECK(!init_done_);
DCHECK(klass != NULL);
- DCHECK(klass->class_loader_ == NULL);
- DCHECK(klass->descriptor_ != NULL);
- DCHECK(klass->descriptor_->Equals(GetClassRootDescriptor(class_root)));
+ DCHECK(klass->GetClassLoader() == NULL);
+ DCHECK(klass->GetDescriptor() != NULL);
+ DCHECK(klass->GetDescriptor()->Equals(GetClassRootDescriptor(class_root)));
DCHECK(class_roots_ != NULL);
DCHECK(class_roots_->Get(class_root) == NULL);
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index a34f180b90..6f894e3492 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -2,6 +2,8 @@
#include "class_linker.h"
+#include <string>
+
#include "UniquePtr.h"
#include "common_test.h"
#include "dex_cache.h"
@@ -35,14 +37,13 @@ class ClassLinkerTest : public CommonTest {
EXPECT_TRUE(primitive->GetSuperClass() == NULL);
EXPECT_FALSE(primitive->HasSuperClass());
EXPECT_TRUE(primitive->GetClassLoader() == NULL);
- EXPECT_TRUE(primitive->GetComponentType() == NULL);
EXPECT_TRUE(primitive->GetStatus() == Class::kStatusInitialized);
EXPECT_FALSE(primitive->IsErroneous());
EXPECT_TRUE(primitive->IsVerified());
EXPECT_TRUE(primitive->IsLinked());
EXPECT_FALSE(primitive->IsArrayInstance());
EXPECT_FALSE(primitive->IsArrayClass());
- EXPECT_EQ(0, primitive->array_rank_);
+ EXPECT_EQ(0, primitive->GetArrayRank());
EXPECT_FALSE(primitive->IsInterface());
EXPECT_TRUE(primitive->IsPublic());
EXPECT_TRUE(primitive->IsFinal());
@@ -60,7 +61,7 @@ class ClassLinkerTest : public CommonTest {
const StringPiece& component_type,
const ClassLoader* class_loader) {
Class* array = class_linker_->FindClass(array_descriptor, class_loader);
- EXPECT_EQ(array_rank, array->array_rank_);
+ EXPECT_EQ(array_rank, array->GetArrayRank());
EXPECT_TRUE(array->GetComponentType()->GetDescriptor()->Equals(component_type));
EXPECT_EQ(class_loader, array->GetClassLoader());
AssertArrayClass(array_descriptor, array);
@@ -83,7 +84,7 @@ class ClassLinkerTest : public CommonTest {
EXPECT_TRUE(array->IsLinked());
EXPECT_FALSE(array->IsArrayInstance());
EXPECT_TRUE(array->IsArrayClass());
- EXPECT_LE(1, array->array_rank_);
+ EXPECT_LE(1, array->GetArrayRank());
EXPECT_FALSE(array->IsInterface());
EXPECT_EQ(array->GetComponentType()->IsPublic(), array->IsPublic());
EXPECT_TRUE(array->IsFinal());
@@ -101,49 +102,49 @@ class ClassLinkerTest : public CommonTest {
EXPECT_TRUE(method->GetName() != NULL);
EXPECT_TRUE(method->GetSignature() != NULL);
- EXPECT_TRUE(method->dex_cache_strings_ != NULL);
- EXPECT_TRUE(method->dex_cache_resolved_types_ != NULL);
- EXPECT_TRUE(method->dex_cache_resolved_methods_ != NULL);
- EXPECT_TRUE(method->dex_cache_resolved_fields_ != NULL);
- EXPECT_TRUE(method->dex_cache_code_and_direct_methods_ != NULL);
- EXPECT_TRUE(method->dex_cache_initialized_static_storage_ != NULL);
- EXPECT_EQ(method->declaring_class_->dex_cache_->GetStrings(),
- method->dex_cache_strings_);
- EXPECT_EQ(method->declaring_class_->dex_cache_->GetResolvedTypes(),
- method->dex_cache_resolved_types_);
- EXPECT_EQ(method->declaring_class_->dex_cache_->GetResolvedMethods(),
- method->dex_cache_resolved_methods_);
- EXPECT_EQ(method->declaring_class_->dex_cache_->GetResolvedFields(),
- method->dex_cache_resolved_fields_);
- EXPECT_EQ(method->declaring_class_->dex_cache_->GetCodeAndDirectMethods(),
- method->dex_cache_code_and_direct_methods_);
- EXPECT_EQ(method->declaring_class_->dex_cache_->GetInitializedStaticStorage(),
- method->dex_cache_initialized_static_storage_);
+ EXPECT_TRUE(method->GetDexCacheStrings() != NULL);
+ EXPECT_TRUE(method->GetDexCacheResolvedTypes() != NULL);
+ EXPECT_TRUE(method->GetDexCacheResolvedMethods() != NULL);
+ EXPECT_TRUE(method->GetDexCacheResolvedFields() != NULL);
+ EXPECT_TRUE(method->GetDexCacheCodeAndDirectMethods() != NULL);
+ EXPECT_TRUE(method->GetDexCacheInitializedStaticStorage() != NULL);
+ EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetStrings(),
+ method->GetDexCacheStrings());
+ EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedTypes(),
+ method->GetDexCacheResolvedTypes());
+ EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedMethods(),
+ method->GetDexCacheResolvedMethods());
+ EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetResolvedFields(),
+ method->GetDexCacheResolvedFields());
+ EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetCodeAndDirectMethods(),
+ method->GetDexCacheCodeAndDirectMethods());
+ EXPECT_EQ(method->GetDeclaringClass()->GetDexCache()->GetInitializedStaticStorage(),
+ method->GetDexCacheInitializedStaticStorage());
}
void AssertField(Class* klass, Field* field) {
EXPECT_TRUE(field != NULL);
EXPECT_EQ(klass, field->GetDeclaringClass());
EXPECT_TRUE(field->GetName() != NULL);
- EXPECT_TRUE(field->GetDescriptor() != NULL);
+ EXPECT_TRUE(field->GetType() != NULL);
}
void AssertClass(const StringPiece& descriptor, Class* klass) {
EXPECT_TRUE(klass->GetDescriptor()->Equals(descriptor));
- if (klass->descriptor_->Equals(String::AllocFromModifiedUtf8("Ljava/lang/Object;"))) {
+ if (klass->GetDescriptor()->Equals(String::AllocFromModifiedUtf8("Ljava/lang/Object;"))) {
EXPECT_FALSE(klass->HasSuperClass());
} else {
EXPECT_TRUE(klass->HasSuperClass());
EXPECT_TRUE(klass->GetSuperClass() != NULL);
}
EXPECT_TRUE(klass->GetDexCache() != NULL);
- EXPECT_TRUE(klass->GetComponentType() == NULL);
- EXPECT_TRUE(klass->GetComponentType() == NULL);
EXPECT_EQ(Class::kStatusResolved, klass->GetStatus());
EXPECT_FALSE(klass->IsErroneous());
EXPECT_FALSE(klass->IsVerified());
EXPECT_TRUE(klass->IsLinked());
EXPECT_TRUE(klass->IsLoaded());
+ EXPECT_FALSE(klass->IsArrayClass());
+ EXPECT_EQ(0, klass->GetArrayRank());
EXPECT_TRUE(klass->IsInSamePackage(klass));
EXPECT_TRUE(Class::IsInSamePackage(klass->GetDescriptor(), klass->GetDescriptor()));
if (klass->IsInterface()) {
@@ -206,15 +207,13 @@ class ClassLinkerTest : public CommonTest {
EXPECT_GE(klass->NumInstanceFields(), klass->NumReferenceInstanceFields());
for (size_t i = 0; i < klass->NumReferenceInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
- Class* field_type = class_linker_->FindClass(field->GetDescriptor(),
- klass->GetClassLoader());
+ Class* field_type = field->GetType();
ASSERT_TRUE(field_type != NULL);
- EXPECT_FALSE(field_type->IsPrimitive());
+ ASSERT_TRUE(!field_type->IsPrimitive());
}
for (size_t i = klass->NumReferenceInstanceFields(); i < klass->NumInstanceFields(); i++) {
Field* field = klass->GetInstanceField(i);
- Class* field_type = class_linker_->FindClass(field->GetDescriptor(),
- klass->GetClassLoader());
+ Class* field_type = field->GetType();
ASSERT_TRUE(field_type != NULL);
EXPECT_TRUE(field_type->IsPrimitive());
}
@@ -310,13 +309,12 @@ TEST_F(ClassLinkerTest, FindClass) {
EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL);
EXPECT_FALSE(JavaLangObject->HasSuperClass());
EXPECT_TRUE(JavaLangObject->GetClassLoader() == NULL);
- EXPECT_TRUE(JavaLangObject->GetComponentType() == NULL);
EXPECT_FALSE(JavaLangObject->IsErroneous());
EXPECT_FALSE(JavaLangObject->IsVerified());
EXPECT_TRUE(JavaLangObject->IsLinked());
EXPECT_FALSE(JavaLangObject->IsArrayInstance());
EXPECT_FALSE(JavaLangObject->IsArrayClass());
- EXPECT_EQ(0, JavaLangObject->array_rank_);
+ EXPECT_EQ(0, JavaLangObject->GetArrayRank());
EXPECT_FALSE(JavaLangObject->IsInterface());
EXPECT_TRUE(JavaLangObject->IsPublic());
EXPECT_FALSE(JavaLangObject->IsFinal());
@@ -340,14 +338,13 @@ TEST_F(ClassLinkerTest, FindClass) {
EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject);
EXPECT_TRUE(MyClass->HasSuperClass());
EXPECT_EQ(class_loader, MyClass->GetClassLoader());
- EXPECT_TRUE(MyClass->GetComponentType() == NULL);
EXPECT_TRUE(MyClass->GetStatus() == Class::kStatusResolved);
EXPECT_FALSE(MyClass->IsErroneous());
EXPECT_FALSE(MyClass->IsVerified());
EXPECT_TRUE(MyClass->IsLinked());
EXPECT_FALSE(MyClass->IsArrayInstance());
EXPECT_FALSE(MyClass->IsArrayClass());
- EXPECT_EQ(0, JavaLangObject->array_rank_);
+ EXPECT_EQ(0, JavaLangObject->GetArrayRank());
EXPECT_FALSE(MyClass->IsInterface());
EXPECT_FALSE(MyClass->IsPublic());
EXPECT_FALSE(MyClass->IsFinal());
@@ -394,6 +391,13 @@ TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
EXPECT_TRUE(throwable->GetInstanceField(3)->GetName()->Equals("stackTrace"));
EXPECT_TRUE(throwable->GetInstanceField(4)->GetName()->Equals("suppressedExceptions"));
+ Class* stack_trace_element = class_linker_->FindSystemClass( "Ljava/lang/StackTraceElement;");
+ ASSERT_EQ(4U, stack_trace_element->NumInstanceFields());
+ EXPECT_TRUE(stack_trace_element->GetInstanceField(0)->GetName()->Equals("declaringClass"));
+ EXPECT_TRUE(stack_trace_element->GetInstanceField(1)->GetName()->Equals("fileName"));
+ EXPECT_TRUE(stack_trace_element->GetInstanceField(2)->GetName()->Equals("methodName"));
+ EXPECT_TRUE(stack_trace_element->GetInstanceField(3)->GetName()->Equals("lineNumber"));
+
Class* accessible_object = class_linker_->FindSystemClass("Ljava/lang/reflect/AccessibleObject;");
ASSERT_EQ(1U, accessible_object->NumInstanceFields());
EXPECT_TRUE(accessible_object->GetInstanceField(0)->GetName()->Equals("flag"));
@@ -438,7 +442,8 @@ TEST_F(ClassLinkerTest, ValidateObjectArrayElementsOffset) {
Class* array_class = class_linker_->FindSystemClass("[Ljava/lang/String;");
ObjectArray<String>* array = ObjectArray<String>::Alloc(array_class, 0);
uint32_t array_offset = reinterpret_cast<uint32_t>(array);
- uint32_t data_offset = reinterpret_cast<uint32_t>(array->GetData());
+ uint32_t data_offset =
+ array_offset + ObjectArray<String>::DataOffset().Uint32Value();
EXPECT_EQ(16U, data_offset - array_offset);
}
@@ -471,54 +476,54 @@ TEST_F(ClassLinkerTest, StaticFields) {
EXPECT_EQ(10U, statics->NumStaticFields());
- Field* s0 = statics->FindStaticField("s0", "Z");
- EXPECT_TRUE(s0->GetClass()->descriptor_->Equals("Ljava/lang/reflect/Field;"));
- EXPECT_EQ('Z', s0->GetType());
+ Field* s0 = statics->FindStaticField("s0", class_linker_->FindClass("Z", class_loader));
+ EXPECT_TRUE(s0->GetClass()->GetDescriptor()->Equals("Ljava/lang/reflect/Field;"));
+ EXPECT_TRUE(s0->GetType()->IsPrimitiveBoolean());
// EXPECT_EQ(true, s0->GetBoolean(NULL)); // TODO: needs clinit to be run?
s0->SetBoolean(NULL, false);
- Field* s1 = statics->FindStaticField("s1", "B");
- EXPECT_EQ('B', s1->GetType());
+ Field* s1 = statics->FindStaticField("s1", class_linker_->FindClass("B", class_loader));
+ EXPECT_TRUE(s1->GetType()->IsPrimitiveByte());
// EXPECT_EQ(5, s1->GetByte(NULL)); // TODO: needs clinit to be run?
s1->SetByte(NULL, 6);
- Field* s2 = statics->FindStaticField("s2", "C");
- EXPECT_EQ('C', s2->GetType());
+ Field* s2 = statics->FindStaticField("s2", class_linker_->FindClass("C", class_loader));
+ EXPECT_TRUE(s2->GetType()->IsPrimitiveChar());
// EXPECT_EQ('a', s2->GetChar(NULL)); // TODO: needs clinit to be run?
s2->SetChar(NULL, 'b');
- Field* s3 = statics->FindStaticField("s3", "S");
- EXPECT_EQ('S', s3->GetType());
+ Field* s3 = statics->FindStaticField("s3", class_linker_->FindClass("S", class_loader));
+ EXPECT_TRUE(s3->GetType()->IsPrimitiveShort());
// EXPECT_EQ(65000, s3->GetShort(NULL)); // TODO: needs clinit to be run?
s3->SetShort(NULL, 65001);
- Field* s4 = statics->FindStaticField("s4", "I");
- EXPECT_EQ('I', s4->GetType());
+ Field* s4 = statics->FindStaticField("s4", class_linker_->FindClass("I", class_loader));
+ EXPECT_TRUE(s4->GetType()->IsPrimitiveInt());
// EXPECT_EQ(2000000000, s4->GetInt(NULL)); // TODO: needs clinit to be run?
s4->SetInt(NULL, 2000000001);
- Field* s5 = statics->FindStaticField("s5", "J");
- EXPECT_EQ('J', s5->GetType());
+ Field* s5 = statics->FindStaticField("s5", class_linker_->FindClass("J", class_loader));
+ EXPECT_TRUE(s5->GetType()->IsPrimitiveLong());
// EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(NULL)); // TODO: needs clinit to be run?
s5->SetLong(NULL, 0x34567890abcdef12LL);
- Field* s6 = statics->FindStaticField("s6", "F");
- EXPECT_EQ('F', s6->GetType());
+ Field* s6 = statics->FindStaticField("s6", class_linker_->FindClass("F", class_loader));
+ EXPECT_TRUE(s6->GetType()->IsPrimitiveFloat());
// EXPECT_EQ(0.5, s6->GetFloat(NULL)); // TODO: needs clinit to be run?
s6->SetFloat(NULL, 0.75);
- Field* s7 = statics->FindStaticField("s7", "D");
- EXPECT_EQ('D', s7->GetType());
+ Field* s7 = statics->FindStaticField("s7", class_linker_->FindClass("D", class_loader));
+ EXPECT_TRUE(s7->GetType()->IsPrimitiveDouble());
// EXPECT_EQ(16777217, s7->GetDouble(NULL)); // TODO: needs clinit to be run?
s7->SetDouble(NULL, 16777219);
- Field* s8 = statics->FindStaticField("s8", "Ljava/lang/Object;");
- EXPECT_EQ('L', s8->GetType());
+ Field* s8 = statics->FindStaticField("s8", class_linker_->FindClass("Ljava/lang/Object;", class_loader));
+ EXPECT_FALSE(s8->GetType()->IsPrimitive());
// EXPECT_TRUE(s8->GetObject(NULL)->AsString()->Equals("android")); // TODO: needs clinit to be run?
s8->SetObject(NULL, String::AllocFromModifiedUtf8("robot"));
- Field* s9 = statics->FindStaticField("s9", "[Ljava/lang/Object;");
- EXPECT_EQ('[', s9->GetType());
+ Field* s9 = statics->FindStaticField("s9", class_linker_->FindClass("[Ljava/lang/Object;", class_loader));
+ EXPECT_TRUE(s9->GetType()->IsArrayClass());
// EXPECT_EQ(NULL, s9->GetObject(NULL)); // TODO: needs clinit to be run?
s9->SetObject(NULL, NULL);
diff --git a/src/class_loader.h b/src/class_loader.h
index da19539be0..3309a8a629 100644
--- a/src/class_loader.h
+++ b/src/class_loader.h
@@ -10,13 +10,14 @@
namespace art {
-// ClassLoader objects.
+// C++ mirror of java.lang.ClassLoader
class ClassLoader : public Object {
public:
static const std::vector<const DexFile*>& GetClassPath(const ClassLoader* class_loader);
void SetClassPath(std::vector<const DexFile*>& class_path) {
DCHECK_EQ(0U, class_path_.size());
+ // TODO: use setter
class_path_ = class_path;
}
@@ -31,6 +32,7 @@ class ClassLoader : public Object {
DISALLOW_IMPLICIT_CONSTRUCTORS(ClassLoader);
};
+// C++ mirror of dalvik.system.BaseDexClassLoader
class BaseDexClassLoader : public ClassLoader {
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
@@ -39,6 +41,7 @@ class BaseDexClassLoader : public ClassLoader {
DISALLOW_IMPLICIT_CONSTRUCTORS(BaseDexClassLoader);
};
+// C++ mirror of dalvik.system.PathClassLoader
class PathClassLoader : public BaseDexClassLoader {
public:
static const PathClassLoader* Alloc(std::vector<const DexFile*> dex_files);
diff --git a/src/common_test.h b/src/common_test.h
index c79cea6e10..5318008c9b 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -89,6 +89,8 @@ class CommonTest : public testing::Test {
runtime_.reset(Runtime::Create(boot_class_path_));
ASSERT_TRUE(runtime_.get() != NULL);
class_linker_ = runtime_->GetClassLinker();
+
+ Heap::VerifyHeap(); // Check for heap corruption before the test
}
virtual void TearDown() {
@@ -127,6 +129,8 @@ class CommonTest : public testing::Test {
CHECK(sym != NULL);
IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
(*icu_cleanup_fn)();
+
+ Heap::VerifyHeap(); // Check for heap corruption after the test
}
std::string GetLibCoreDexFileName() {
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index 5cfddc0546..4e3c9c4398 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -2092,11 +2092,11 @@ bool oatDoSSAConversion(CompilationUnit* cUnit, BasicBlock* bb)
* blocks.
*/
bb->dataFlowInfo->dalvikToSSAMap =
- (int *)oatNew(sizeof(int) * cUnit->method->num_registers_,
+ (int *)oatNew(sizeof(int) * cUnit->method->NumRegisters(),
false);
memcpy(bb->dataFlowInfo->dalvikToSSAMap, cUnit->dalvikToSSAMap,
- sizeof(int) * cUnit->method->num_registers_);
+ sizeof(int) * cUnit->method->NumRegisters());
return true;
}
@@ -2184,7 +2184,7 @@ bool oatDoConstantPropagation(CompilationUnit* cUnit, BasicBlock* bb)
void oatInitializeSSAConversion(CompilationUnit* cUnit)
{
int i;
- int numDalvikReg = cUnit->method->num_registers_;
+ int numDalvikReg = cUnit->method->NumRegisters();
cUnit->ssaToDalvikMap = (GrowableList *)oatNew(sizeof(GrowableList),
false);
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index 9ef2b4fe51..dbd06abe8c 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -733,7 +733,7 @@ bool oatCompileMethod(Method* method, art::InstructionSet insnSet)
const art::DexFile& dex_file = class_linker->FindDexFile(
method->GetDeclaringClass()->GetDexCache());
const art::DexFile::CodeItem* code_item =
- dex_file.GetCodeItem(method->code_off_);
+ dex_file.GetCodeItem(method->GetCodeItemOffset());
const u2* codePtr = code_item->insns_;
const u2* codeEnd = code_item->insns_ + code_item->insns_size_;
int numBlocks = 0;
@@ -878,7 +878,7 @@ bool oatCompileMethod(Method* method, art::InstructionSet insnSet)
}
/* Adjust this value accordingly once inlining is performed */
- cUnit.numDalvikRegisters = cUnit.method->num_registers_;
+ cUnit.numDalvikRegisters = cUnit.method->NumRegisters();
/* Verify if all blocks are connected as claimed */
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index a4ab76f028..6a4e663e7d 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -119,9 +119,9 @@ void oatSimpleRegAlloc(CompilationUnit* cUnit)
}
/* Figure out the frame size */
- cUnit->numIns = cUnit->method->num_ins_;
- cUnit->numRegs = cUnit->method->num_registers_ - cUnit->numIns;
- cUnit->numOuts = cUnit->method->num_outs_;
+ cUnit->numIns = cUnit->method->NumIns();
+ cUnit->numRegs = cUnit->method->NumRegisters() - cUnit->numIns;
+ cUnit->numOuts = cUnit->method->NumOuts();
cUnit->numPadding = (STACK_ALIGN_WORDS -
(cUnit->numSpills + cUnit->numRegs +
cUnit->numOuts + 2)) & (STACK_ALIGN_WORDS-1);
diff --git a/src/compiler/SSATransformation.cc b/src/compiler/SSATransformation.cc
index 42e855de29..95f6db5f9a 100644
--- a/src/compiler/SSATransformation.cc
+++ b/src/compiler/SSATransformation.cc
@@ -107,8 +107,8 @@ static void computeDefBlockMatrix(CompilationUnit* cUnit)
* Also set the incoming parameters as defs in the entry block.
* Only need to handle the parameters for the outer method.
*/
- int inReg = cUnit->method->num_registers_ - cUnit->method->num_ins_;
- for (; inReg < cUnit->method->num_registers_; inReg++) {
+ int inReg = cUnit->method->NumRegisters() - cUnit->method->NumIns();
+ for (; inReg < cUnit->method->NumRegisters(); inReg++) {
oatSetBit(cUnit->defBlockMatrix[inReg],
cUnit->entryBlock->id);
}
diff --git a/src/compiler/codegen/arm/ArchUtility.cc b/src/compiler/codegen/arm/ArchUtility.cc
index d643a9065f..dc8bdec806 100644
--- a/src/compiler/codegen/arm/ArchUtility.cc
+++ b/src/compiler/codegen/arm/ArchUtility.cc
@@ -407,7 +407,7 @@ void oatCodegenDump(CompilationUnit* cUnit)
" bytes, Dalvik size is " << insnsSize * 2;
LOG(INFO) << "expansion factor: " <<
(float)cUnit->totalSize / (float)(insnsSize * 2);
- for (int i = 0; i < method->num_registers_; i++) {
+ for (int i = 0; i < method->NumRegisters(); i++) {
RegLocation loc = cUnit->regLocation[i];
char buf[100];
if (loc.fpLocation == kLocPhysReg) {
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index 6223512f16..78d5267c61 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -94,7 +94,7 @@ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb,
for (i=0; i< ssaRep->numUses; i++) {
int origSreg = DECODE_REG(
oatConvertSSARegToDalvik(cUnit, ssaRep->uses[i]));
- assert(origSreg < cUnit->method->num_registers_);
+ assert(origSreg < cUnit->method->NumRegisters());
bool fpUse = ssaRep->fpUse ? ssaRep->fpUse[i] : false;
if (fp == fpUse) {
counts[origSreg].count++;
@@ -107,7 +107,7 @@ static void countRefs(CompilationUnit *cUnit, BasicBlock* bb,
}
int origSreg = DECODE_REG(
oatConvertSSARegToDalvik(cUnit, ssaRep->defs[i]));
- assert(origSreg < cUnit->method->num_registers_);
+ assert(origSreg < cUnit->method->NumRegisters());
bool fpDef = ssaRep->fpDef ? ssaRep->fpDef[i] : false;
if (fp == fpDef) {
counts[origSreg].count++;
@@ -139,8 +139,8 @@ static void dumpCounts(const RefCounts* arr, int size, const char* msg)
*/
extern void oatDoPromotion(CompilationUnit* cUnit)
{
- int numRegs = cUnit->method->num_registers_;
- int numIns = cUnit->method->num_ins_;
+ int numRegs = cUnit->method->NumRegisters();
+ int numIns = cUnit->method->NumIns();
/*
* Because ins don't have explicit definitions, we need to type
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index c69a27e77c..8caf0d145a 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -404,12 +404,12 @@ static int nextSDCallInsnSP(CompilationUnit* cUnit, MIR* mir,
break;
case 1: // Get the current Method->DeclaringClass() [sets r0]
loadBaseDisp(cUnit, mir, r0,
- OFFSETOF_MEMBER(art::Method, declaring_class_),
+ art::Method::DeclaringClassOffset().Int32Value(),
r0, kWord, INVALID_SREG);
break;
case 2: // Method->DeclaringClass()->GetDexCache() [sets r0]
loadBaseDisp(cUnit, mir, r0,
- OFFSETOF_MEMBER(art::Class, dex_cache_), r0, kWord,
+ art::Class::DexCacheOffset().Int32Value(), r0, kWord,
INVALID_SREG);
break;
case 3: // Method->DeclaringClass()->GetDexCache()->methodsObjectArr
@@ -425,7 +425,8 @@ static int nextSDCallInsnSP(CompilationUnit* cUnit, MIR* mir,
kWord, INVALID_SREG);
break;
case 6: // Get the target compiled code address [uses r0, sets rLR]
- loadBaseDisp(cUnit, mir, r0, art::Method::GetCodeOffset(), rLR,
+ loadBaseDisp(cUnit, mir, r0,
+ art::Method::GetCodeOffset().Int32Value(), rLR,
kWord, INVALID_SREG);
break;
default:
@@ -502,18 +503,19 @@ static int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir,
break;
case 1: // Get the current Method->DeclaringClass() [uses/sets r0]
loadBaseDisp(cUnit, mir, r0,
- OFFSETOF_MEMBER(art::Method, declaring_class_),
+ art::Method::DeclaringClassOffset().Int32Value(),
r0, kWord, INVALID_SREG);
break;
case 2: // Method->DeclaringClass()->GetDexCache() [uses/sets r0]
loadBaseDisp(cUnit, mir, r0,
- OFFSETOF_MEMBER(art::Class, dex_cache_), r0, kWord,
+ art::Class::DexCacheOffset().Int32Value(),
+ r0, kWord,
INVALID_SREG);
break;
case 3: // ...()->GetDexCache()->methodsObjectArr [uses/sets r0]
loadBaseDisp(cUnit, mir, r0,
- art::DexCache::ResolvedMethodsOffset().Int32Value(), r0,
- kWord, INVALID_SREG);
+ art::DexCache::ResolvedMethodsOffset().Int32Value(),
+ r0, kWord, INVALID_SREG);
// Load "this" [set r1]
rlArg = oatGetSrc(cUnit, mir, 0);
loadValueDirectFixed(cUnit, rlArg, r1);
@@ -524,17 +526,18 @@ static int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir,
// Is "this" null? [use r1]
genNullCheck(cUnit, oatSSASrc(mir,0), r1, mir->offset, NULL);
// get this->clazz [use r1, set rLR]
- loadBaseDisp(cUnit, mir, r1, OFFSETOF_MEMBER(Object, klass_), rLR,
- kWord, INVALID_SREG);
+ loadBaseDisp(cUnit, mir, r1, Object::ClassOffset().Int32Value(),
+ rLR, kWord, INVALID_SREG);
// Get the base Method* [uses r0, sets r0]
loadBaseDisp(cUnit, mir, r0, dInsn->vB * 4, r0,
kWord, INVALID_SREG);
// get this->clazz->vtable [use rLR, set rLR]
loadBaseDisp(cUnit, mir, rLR,
- OFFSETOF_MEMBER(Class, vtable_), rLR, kWord,
+ Class::VTableOffset().Int32Value(), rLR, kWord,
INVALID_SREG);
// Get the method index [use r0, set r12]
- loadBaseDisp(cUnit, mir, r0, OFFSETOF_MEMBER(Method, method_index_),
+ loadBaseDisp(cUnit, mir, r0,
+ Method::MethodIndexOffset().Int32Value(),
r12, kUnsignedHalf, INVALID_SREG);
// Skip past the object header
opRegImm(cUnit, kOpAdd, rLR, art::Array::DataOffset().Int32Value());
@@ -542,7 +545,8 @@ static int nextVCallInsnSP(CompilationUnit* cUnit, MIR* mir,
loadBaseIndexed(cUnit, rLR, r12, r0, 2, kWord);
break;
case 5: // Get the target compiled code address [uses r0, sets rLR]
- loadBaseDisp(cUnit, mir, r0, art::Method::GetCodeOffset(), rLR,
+ loadBaseDisp(cUnit, mir, r0,
+ art::Method::GetCodeOffset().Int32Value(), rLR,
kWord, INVALID_SREG);
break;
default:
@@ -766,7 +770,7 @@ static int genDalvikArgsRange(CompilationUnit* cUnit, MIR* mir,
* Dalvik vRegs and the ins.
*/
int highestArg = oatGetSrc(cUnit, mir, numArgs-1).sRegLow;
- int boundaryReg = cUnit->method->num_registers_ - cUnit->method->num_ins_;
+ int boundaryReg = cUnit->method->NumRegisters() - cUnit->method->NumIns();
if ((firstArg < boundaryReg) && (highestArg >= boundaryReg)) {
LOG(FATAL) << "Argument list spanned locals & args";
}
@@ -1628,11 +1632,13 @@ static void handleExtendedMethodMIR(CompilationUnit* cUnit, MIR* mir)
* home location */
static void flushIns(CompilationUnit* cUnit)
{
- if (cUnit->method->num_ins_ == 0)
+ if (cUnit->method->NumIns() == 0)
return;
- int inRegs = (cUnit->method->num_ins_ > 2) ? 3 : cUnit->method->num_ins_;
+ int inRegs = (cUnit->method->NumIns() > 2) ? 3
+ : cUnit->method->NumIns();
int startReg = r1;
- int startLoc = cUnit->method->num_registers_ - cUnit->method->num_ins_;
+ int startLoc = cUnit->method->NumRegisters() -
+ cUnit->method->NumIns();
for (int i = 0; i < inRegs; i++) {
RegLocation loc = cUnit->regLocation[startLoc + i];
//TUNING: be smarter about flushing ins to frame
@@ -1654,7 +1660,7 @@ static void flushIns(CompilationUnit* cUnit)
}
// Now, do initial assignment of all promoted arguments passed in frame
- for (int i = inRegs; i < cUnit->method->num_ins_;) {
+ for (int i = inRegs; i < cUnit->method->NumIns();) {
RegLocation loc = cUnit->regLocation[startLoc + i];
if (loc.fpLocation == kLocPhysReg) {
loc.location = kLocPhysReg;
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index 11146f7ba7..c4a1fed931 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -389,7 +389,7 @@ static void genIGetX(CompilationUnit* cUnit, MIR* mir, OpSize size,
#else
bool isVolatile = false;
#endif
- int fieldOffset = fieldPtr->GetOffset();
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
RegLocation rlResult;
RegisterClass regClass = oatRegClassBySize(size);
rlObj = loadValue(cUnit, rlObj, kCoreReg);
@@ -418,7 +418,7 @@ static void genIPutX(CompilationUnit* cUnit, MIR* mir, OpSize size,
#else
bool isVolatile = false;
#endif
- int fieldOffset = fieldPtr->GetOffset();
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
RegisterClass regClass = oatRegClassBySize(size);
rlObj = loadValue(cUnit, rlObj, kCoreReg);
rlSrc = loadValue(cUnit, rlSrc, regClass);
@@ -448,7 +448,7 @@ static void genIGetWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
#else
bool isVolatile = false;
#endif
- int fieldOffset = fieldPtr->GetOffset();
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
RegLocation rlResult;
rlObj = loadValue(cUnit, rlObj, kCoreReg);
int regPtr = oatAllocTemp(cUnit);
@@ -483,7 +483,7 @@ static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
#else
bool isVolatile = false;
#endif
- int fieldOffset = fieldPtr->GetOffset();
+ int fieldOffset = fieldPtr->GetOffset().Int32Value();
rlObj = loadValue(cUnit, rlObj, kCoreReg);
int regPtr;
@@ -504,12 +504,12 @@ static void genIPutWideX(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc,
static void genConstClass(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest, RegLocation rlSrc)
{
- art::Class* classPtr = cUnit->method->dex_cache_resolved_types_->
+ art::Class* classPtr = cUnit->method->GetDexCacheResolvedTypes()->
Get(mir->dalvikInsn.vB);
int mReg = loadCurrMethod(cUnit);
int resReg = oatAllocTemp(cUnit);
RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- loadWordDisp(cUnit, mReg, OFFSETOF_MEMBER(Method, dex_cache_strings_),
+ loadWordDisp(cUnit, mReg, Method::DexCacheStringsOffset().Int32Value(),
resReg);
loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
(sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
@@ -547,14 +547,14 @@ static void genConstString(CompilationUnit* cUnit, MIR* mir,
RegLocation rlDest, RegLocation rlSrc)
{
/* All strings should be available at compile time */
- const art::String* str = cUnit->method->dex_cache_strings_->
+ const art::String* str = cUnit->method->GetDexCacheStrings()->
Get(mir->dalvikInsn.vB);
DCHECK(str != NULL);
int mReg = loadCurrMethod(cUnit);
int resReg = oatAllocTemp(cUnit);
RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true);
- loadWordDisp(cUnit, mReg, OFFSETOF_MEMBER(Method, dex_cache_strings_),
+ loadWordDisp(cUnit, mReg, Method::DexCacheStringsOffset().Int32Value(),
resReg);
loadWordDisp(cUnit, resReg, Array::DataOffset().Int32Value() +
(sizeof(String*) * mir->dalvikInsn.vB), rlResult.lowReg);
@@ -605,8 +605,8 @@ static void genInstanceof(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest,
/* When taken r0 has NULL which can be used for store directly */
ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r0, 0);
/* r1 now contains object->clazz */
- assert(OFFSETOF_MEMBER(Object, klass_) == 0);
- loadWordDisp(cUnit, r0, OFFSETOF_MEMBER(Object, klass_), r1);
+ assert(Object::ClassOffset().Int32Value() == 0);
+ loadWordDisp(cUnit, r0, Object::ClassOffset().Int32Value(), r1);
/* r1 now contains object->clazz */
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
@@ -647,7 +647,7 @@ static void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
* with clazz.
*/
/* r0 now contains object->clazz */
- loadWordDisp(cUnit, rlSrc.lowReg, OFFSETOF_MEMBER(Object, klass_), r0);
+ loadWordDisp(cUnit, rlSrc.lowReg, Object::ClassOffset().Int32Value(), r0);
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
opRegReg(cUnit, kOpCmp, r0, r1);
@@ -799,7 +799,7 @@ static void genMonitorEnter(CompilationUnit* cUnit, MIR* mir,
genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3);
newLIR3(cUnit, kThumb2Ldrex, r2, r1,
- OFFSETOF_MEMBER(Object, monitor_) >> 2); // Get object->lock
+ Object::MonitorOffset().Int32Value() >> 2); // Get object->lock
// Align owner
opRegImm(cUnit, kOpLsl, r3, art::Monitor::kLwLockOwnerShift);
// Is lock unheld on lock or held by us (==threadId) on unlock?
@@ -809,7 +809,7 @@ static void genMonitorEnter(CompilationUnit* cUnit, MIR* mir,
art::Monitor::kLwLockOwnerShift - 1);
hopBranch = newLIR2(cUnit, kThumb2Cbnz, r2, 0);
newLIR4(cUnit, kThumb2Strex, r2, r3, r1,
- OFFSETOF_MEMBER(Object, monitor_) >> 2);
+ Object::MonitorOffset().Int32Value() >> 2);
oatGenMemBarrier(cUnit, kSY);
branch = newLIR2(cUnit, kThumb2Cbz, r2, 0);
@@ -848,7 +848,7 @@ static void genMonitorExit(CompilationUnit* cUnit, MIR* mir,
loadValueDirectFixed(cUnit, rlSrc, r1); // Get obj
oatLockCallTemps(cUnit); // Prepare for explicit register usage
genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
- loadWordDisp(cUnit, r1, OFFSETOF_MEMBER(Object, monitor_), r2); // Get lock
+ loadWordDisp(cUnit, r1, Object::MonitorOffset().Int32Value(), r2); // Get lock
loadWordDisp(cUnit, rSELF, Thread::IdOffset().Int32Value(), r3);
// Is lock unheld on lock or held by us (==threadId) on unlock?
opRegRegImm(cUnit, kOpAnd, r12, r2, (art::Monitor::kLwHashStateMask <<
@@ -860,7 +860,7 @@ static void genMonitorExit(CompilationUnit* cUnit, MIR* mir,
opRegReg(cUnit, kOpSub, r2, r3);
hopBranch = opCondBranch(cUnit, kArmCondNe);
oatGenMemBarrier(cUnit, kSY);
- storeWordDisp(cUnit, r1, OFFSETOF_MEMBER(Object, monitor_), r12);
+ storeWordDisp(cUnit, r1, Object::MonitorOffset().Int32Value(), r12);
branch = opNone(cUnit, kOpUncondBr);
hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
@@ -1152,9 +1152,9 @@ static void genArrayObjPut(CompilationUnit* cUnit, MIR* mir,
loadWordDisp(cUnit, rSELF,
OFFSETOF_MEMBER(Thread, pCanPutArrayElementFromCode), rLR);
/* Get the array's clazz */
- loadWordDisp(cUnit, r1, OFFSETOF_MEMBER(Object, klass_), r1);
+ loadWordDisp(cUnit, r1, Object::ClassOffset().Int32Value(), r1);
/* Get the object's clazz */
- loadWordDisp(cUnit, r0, OFFSETOF_MEMBER(Object, klass_), r0);
+ loadWordDisp(cUnit, r0, Object::ClassOffset().Int32Value(), r0);
opReg(cUnit, kOpBlx, rLR);
oatClobberCallRegs(cUnit);
diff --git a/src/dex_cache.h b/src/dex_cache.h
index f2cfcc7972..137f267761 100644
--- a/src/dex_cache.h
+++ b/src/dex_cache.h
@@ -109,11 +109,11 @@ class DexCache : public ObjectArray<Object> {
return GetInitializedStaticStorage()->GetLength();
}
- const String* GetResolvedString(uint32_t string_idx) const {
+ String* GetResolvedString(uint32_t string_idx) const {
return GetStrings()->Get(string_idx);
}
- void SetResolvedString(uint32_t string_idx, const String* resolved) {
+ void SetResolvedString(uint32_t string_idx, String* resolved) {
GetStrings()->Set(string_idx, resolved);
}
@@ -141,8 +141,8 @@ class DexCache : public ObjectArray<Object> {
GetResolvedFields()->Set(field_idx, resolved);
}
- ObjectArray<const String>* GetStrings() const {
- return static_cast<ObjectArray<const String>*>(GetNonNull(kStrings));
+ ObjectArray<String>* GetStrings() const {
+ return static_cast<ObjectArray<String>*>(GetNonNull(kStrings));
}
ObjectArray<Class>* GetResolvedTypes() const {
return static_cast<ObjectArray<Class>*>(GetNonNull(kResolvedTypes));
diff --git a/src/dex_file.cc b/src/dex_file.cc
index 3d66909d75..c8e7c704ed 100644
--- a/src/dex_file.cc
+++ b/src/dex_file.cc
@@ -543,11 +543,11 @@ String* DexFile::dexArtStringById(int32_t idx) const {
int32_t DexFile::GetLineNumFromPC(const art::Method* method, uint32_t rel_pc) const {
// For native method, lineno should be -2 to indicate it is native. Note that
// "line number == -2" is how libcore tells from StackTraceElement.
- if (method->code_off_ == 0) {
+ if (method->GetCodeItemOffset() == 0) {
return -2;
}
- const CodeItem* code_item = GetCodeItem(method->code_off_);
+ const CodeItem* code_item = GetCodeItem(method->GetCodeItemOffset());
DCHECK(code_item != NULL);
// A method with no line number info should return -1
@@ -573,7 +573,7 @@ void DexFile::dexDecodeDebugInfo0(const CodeItem* code_item, const art::Method*
arg_reg++;
}
- ParameterIterator *it = GetParameterIterator(GetProtoId(method->proto_idx_));
+ ParameterIterator *it = GetParameterIterator(GetProtoId(method->GetProtoIdx()));
for (uint32_t i = 0; i < parameters_size && it->HasNext(); ++i, it->Next()) {
if (arg_reg >= code_item->registers_size_) {
LOG(FATAL) << "invalid stream";
diff --git a/src/dex_verifier.cc b/src/dex_verifier.cc
index 0e62b258bd..f257e78a63 100644
--- a/src/dex_verifier.cc
+++ b/src/dex_verifier.cc
@@ -655,7 +655,7 @@ bool DexVerify::VerifyMethod(Method* method) {
const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
- const DexFile::CodeItem *code_item = dex_file.GetCodeItem(method->code_off_);
+ const DexFile::CodeItem *code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
/*
* If there aren't any instructions, make sure that's expected, then
@@ -682,29 +682,26 @@ bool DexVerify::VerifyMethod(Method* method) {
/*
* Allocate and initialize an array to hold instruction data.
*/
- uint32_t* insn_flags = new uint32_t[code_item->insns_size_]();
+ UniquePtr<uint32_t[]> insn_flags(new uint32_t[code_item->insns_size_]());
/*
* Run through the instructions and see if the width checks out.
*/
- if (!CheckInsnWidth(code_item->insns_, code_item->insns_size_, insn_flags)) {
- delete insn_flags;
+ if (!CheckInsnWidth(code_item->insns_, code_item->insns_size_, insn_flags.get())) {
return false;
}
/*
* Flag instructions guarded by a "try" block and check exception handlers.
*/
- if (!ScanTryCatchBlocks(code_item, insn_flags)) {
- delete insn_flags;
+ if (!ScanTryCatchBlocks(code_item, insn_flags.get())) {
return false;
}
/*
* Perform static instruction verification.
*/
- if (!VerifyInstructions(&dex_file, code_item, insn_flags)) {
- delete insn_flags;
+ if (!VerifyInstructions(&dex_file, code_item, insn_flags.get())) {
return false;
}
@@ -712,7 +709,6 @@ bool DexVerify::VerifyMethod(Method* method) {
* TODO: Code flow analysis
*/
- delete insn_flags;
return true;
}
diff --git a/src/exception_test.cc b/src/exception_test.cc
index 3611b6722d..439e7edd54 100644
--- a/src/exception_test.cc
+++ b/src/exception_test.cc
@@ -74,18 +74,18 @@ class ExceptionTest : public CommonTest {
ASSERT_TRUE(my_klass_ != NULL);
method_f_ = my_klass_->FindVirtualMethod("f", "()I");
ASSERT_TRUE(method_f_ != NULL);
- method_f_->SetFrameSizeInBytes(8);
+ method_f_->SetFrameSizeInBytes(kStackAlignment);
method_f_->SetReturnPcOffsetInBytes(4);
method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
ASSERT_TRUE(method_g_ != NULL);
- method_g_->SetFrameSizeInBytes(8);
+ method_g_->SetFrameSizeInBytes(kStackAlignment);
method_g_->SetReturnPcOffsetInBytes(4);
}
DexFile::CatchHandlerItem FindCatchHandlerItem(Method* method,
const char exception_type[],
uint32_t addr) {
- const DexFile::CodeItem* code_item = dex_->GetCodeItem(method->code_off_);
+ const DexFile::CodeItem* code_item = dex_->GetCodeItem(method->GetCodeItemOffset());
for (DexFile::CatchHandlerIterator iter = dex_->dexFindCatchHandler(*code_item, addr);
!iter.HasNext(); iter.Next()) {
if (strcmp(exception_type, dex_->dexStringByTypeIdx(iter.Get().type_idx_)) == 0) {
@@ -105,7 +105,7 @@ class ExceptionTest : public CommonTest {
};
TEST_F(ExceptionTest, FindCatchHandler) {
- const DexFile::CodeItem *code_item = dex_->GetCodeItem(method_f_->code_off_);
+ const DexFile::CodeItem *code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
ASSERT_TRUE(code_item != NULL);
@@ -141,12 +141,23 @@ TEST_F(ExceptionTest, StackTraceElement) {
enum {STACK_SIZE = 1000};
uint32_t top_of_stack = 0;
uintptr_t fake_stack[STACK_SIZE];
+ ASSERT_EQ(kStackAlignment, 16);
+ ASSERT_EQ(sizeof(uintptr_t), sizeof(uint32_t));
+
+ // Create/push fake 16byte stack frame for method g
fake_stack[top_of_stack++] = reinterpret_cast<uintptr_t>(method_g_);
fake_stack[top_of_stack++] = 3;
+ fake_stack[top_of_stack++] = 0;
+ fake_stack[top_of_stack++] = 0;
+
+ // Create/push fake 16byte stack frame for method f
fake_stack[top_of_stack++] = reinterpret_cast<uintptr_t>(method_f_);
fake_stack[top_of_stack++] = 3;
- fake_stack[top_of_stack++] = NULL;
fake_stack[top_of_stack++] = 0;
+ fake_stack[top_of_stack++] = 0;
+
+ // Pull Method* of NULL to terminate the trace
+ fake_stack[top_of_stack++] = NULL;
Thread* thread = Thread::Current();
thread->SetTopOfStack(fake_stack);
diff --git a/src/heap.cc b/src/heap.cc
index 1682cc580a..cb5e0dc748 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -31,11 +31,11 @@ HeapBitmap* Heap::mark_bitmap_ = NULL;
HeapBitmap* Heap::live_bitmap_ = NULL;
-size_t Heap::reference_referent_offset_ = 0; // TODO
-size_t Heap::reference_queue_offset_ = 0; // TODO
-size_t Heap::reference_queueNext_offset_ = 0; // TODO
-size_t Heap::reference_pendingNext_offset_ = 0; // TODO
-size_t Heap::finalizer_reference_zombie_offset_ = 0; // TODO
+MemberOffset Heap::reference_referent_offset_ = MemberOffset(0);
+MemberOffset Heap::reference_queue_offset_ = MemberOffset(0);
+MemberOffset Heap::reference_queueNext_offset_ = MemberOffset(0);
+MemberOffset Heap::reference_pendingNext_offset_ = MemberOffset(0);
+MemberOffset Heap::finalizer_reference_zombie_offset_ = MemberOffset(0);
bool Heap::Init(size_t initial_size, size_t maximum_size, const char* boot_image_file_name) {
Space* boot_space;
@@ -83,6 +83,9 @@ bool Heap::Init(size_t initial_size, size_t maximum_size, const char* boot_image
live_bitmap_ = live_bitmap.release();
mark_bitmap_ = mark_bitmap.release();
+ num_bytes_allocated_ = 0;
+ num_objects_allocated_ = 0;
+
// TODO: allocate the card table
// Make objects in boot_space live (after live_bitmap_ is set)
@@ -108,28 +111,17 @@ void Heap::Destroy() {
Object* Heap::AllocObject(Class* klass, size_t num_bytes) {
DCHECK(klass == NULL
- || klass->descriptor_ == NULL
+ || klass->GetDescriptor() == NULL
|| (klass->IsClassClass() && num_bytes >= sizeof(Class))
- || (klass->object_size_ == (klass->IsArrayClass() ? 0 : num_bytes)));
+ || (klass->IsVariableSize() || klass->GetObjectSize() == num_bytes));
+ DCHECK(num_bytes >= sizeof(Object));
Object* obj = Allocate(num_bytes);
if (obj != NULL) {
- obj->klass_ = klass;
+ obj->SetClass(klass);
}
return obj;
}
-void Heap::VerifyObject(const Object* obj) {
- if (!IsAligned(obj, kObjectAlignment)) {
- LOG(FATAL) << "Object isn't aligned: " << obj;
- } else if (!live_bitmap_->Test(obj)) {
- // TODO: we don't hold a lock here as it is assumed the live bit map
- // isn't changing if the mutator is running.
- LOG(FATAL) << "Object is dead: " << obj;
- } else if(obj->GetClass() == NULL) {
- LOG(FATAL) << "Object has no class: " << obj;
- }
-}
-
bool Heap::IsHeapAddress(const Object* obj) {
if (!IsAligned(obj, kObjectAlignment)) {
return false;
@@ -138,6 +130,52 @@ bool Heap::IsHeapAddress(const Object* obj) {
return true;
}
+bool Heap::verify_object_disabled_;
+
+void Heap::VerifyObject(const Object* obj) {
+ if (obj != NULL && !verify_object_disabled_) {
+ if (!IsAligned(obj, kObjectAlignment)) {
+ LOG(FATAL) << "Object isn't aligned: " << obj;
+ } else if (!live_bitmap_->Test(obj)) {
+ // TODO: we don't hold a lock here as it is assumed the live bit map
+ // isn't changing if the mutator is running.
+ LOG(FATAL) << "Object is dead: " << obj;
+ }
+ // Ignore early dawn of the universe verifications
+ if(num_objects_allocated_ > 10) {
+ const byte* raw_addr = reinterpret_cast<const byte*>(obj) +
+ Object::ClassOffset().Int32Value();
+ const Class* c = *reinterpret_cast<Class* const *>(raw_addr);
+ if (c == NULL) {
+ LOG(FATAL) << "Null class" << " in object: " << obj;
+ } else if (!IsAligned(c, kObjectAlignment)) {
+ LOG(FATAL) << "Class isn't aligned: " << c << " in object: " << obj;
+ } else if (!live_bitmap_->Test(c)) {
+ LOG(FATAL) << "Class of object is dead: " << c << " in object: " << obj;
+ }
+ // Check obj.getClass().getClass() == obj.getClass().getClass().getClass()
+ // NB we don't use the accessors here as they have internal sanity checks
+ // that we don't want to run
+ raw_addr = reinterpret_cast<const byte*>(c) +
+ Object::ClassOffset().Int32Value();
+ const Class* c_c = *reinterpret_cast<Class* const *>(raw_addr);
+ raw_addr = reinterpret_cast<const byte*>(c_c) +
+ Object::ClassOffset().Int32Value();
+ const Class* c_c_c = *reinterpret_cast<Class* const *>(raw_addr);
+ CHECK_EQ(c_c, c_c_c);
+ }
+ }
+}
+
+static void HeapVerifyCallback(Object* obj, void *arg) {
+ DCHECK(obj != NULL);
+ Heap::VerifyObject(obj);
+}
+
+void Heap::VerifyHeap() {
+ live_bitmap_->Walk(HeapVerifyCallback, NULL);
+}
+
void Heap::RecordAllocation(Space* space, const Object* obj) {
size_t size = space->AllocationSize(obj);
DCHECK_NE(size, 0u);
@@ -163,12 +201,12 @@ void Heap::RecordFree(Space* space, const Object* obj) {
void Heap::RecordImageAllocations(Space* space) {
CHECK(space != NULL);
CHECK(live_bitmap_ != NULL);
- byte* current = space->GetBase() + RoundUp(sizeof(ImageHeader), 8);
+ byte* current = space->GetBase() + RoundUp(sizeof(ImageHeader), kObjectAlignment);
while (current < space->GetLimit()) {
- DCHECK(IsAligned(current, 8));
+ DCHECK(IsAligned(current, kObjectAlignment));
const Object* obj = reinterpret_cast<const Object*>(current);
live_bitmap_->Set(obj);
- current += RoundUp(obj->SizeOf(), 8);
+ current += RoundUp(obj->SizeOf(), kObjectAlignment);
}
}
diff --git a/src/heap.h b/src/heap.h
index 6420a2ad8f..bc06289d51 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -7,6 +7,7 @@
#include "globals.h"
#include "object_bitmap.h"
+#include "offsets.h"
namespace art {
@@ -36,6 +37,9 @@ class Heap {
// Check sanity of given reference. Requires the heap lock.
static void VerifyObject(const Object *obj);
+ // Check sanity of all live references. Requires the heap lock.
+ static void VerifyHeap();
+
// A weaker test than VerifyObject that doesn't require the heap lock,
// and doesn't abort on error, allowing the caller to report more
// meaningful diagnostics.
@@ -74,16 +78,16 @@ class Heap {
return mark_bitmap_;
}
- static void SetReferenceOffsets(size_t reference_referent_offset,
- size_t reference_queue_offset,
- size_t reference_queueNext_offset,
- size_t reference_pendingNext_offset,
- size_t finalizer_reference_zombie_offset) {
- CHECK_NE(reference_referent_offset, 0U);
- CHECK_NE(reference_queue_offset, 0U);
- CHECK_NE(reference_queueNext_offset, 0U);
- CHECK_NE(reference_pendingNext_offset, 0U);
- CHECK_NE(finalizer_reference_zombie_offset, 0U);
+ static void SetReferenceOffsets(MemberOffset reference_referent_offset,
+ MemberOffset reference_queue_offset,
+ MemberOffset reference_queueNext_offset,
+ MemberOffset reference_pendingNext_offset,
+ MemberOffset finalizer_reference_zombie_offset) {
+ CHECK_NE(reference_referent_offset.Uint32Value(), 0U);
+ CHECK_NE(reference_queue_offset.Uint32Value(), 0U);
+ CHECK_NE(reference_queueNext_offset.Uint32Value(), 0U);
+ CHECK_NE(reference_pendingNext_offset.Uint32Value(), 0U);
+ CHECK_NE(finalizer_reference_zombie_offset.Uint32Value(), 0U);
reference_referent_offset_ = reference_referent_offset;
reference_queue_offset_ = reference_queue_offset;
reference_queueNext_offset_ = reference_queueNext_offset;
@@ -91,31 +95,36 @@ class Heap {
finalizer_reference_zombie_offset_ = finalizer_reference_zombie_offset;
}
- static size_t GetReferenceReferentOffset() {
- DCHECK_NE(reference_referent_offset_, 0U);
+ static MemberOffset GetReferenceReferentOffset() {
+ DCHECK_NE(reference_referent_offset_.Uint32Value(), 0U);
return reference_referent_offset_;
}
- static size_t GetReferenceQueueOffset() {
- DCHECK_NE(reference_queue_offset_, 0U);
+ static MemberOffset GetReferenceQueueOffset() {
+ DCHECK_NE(reference_queue_offset_.Uint32Value(), 0U);
return reference_queue_offset_;
}
- static size_t GetReferenceQueueNextOffset() {
- DCHECK_NE(reference_queueNext_offset_, 0U);
+ static MemberOffset GetReferenceQueueNextOffset() {
+ DCHECK_NE(reference_queueNext_offset_.Uint32Value(), 0U);
return reference_queueNext_offset_;
}
- static size_t GetReferencePendingNextOffset() {
- DCHECK_NE(reference_pendingNext_offset_, 0U);
+ static MemberOffset GetReferencePendingNextOffset() {
+ DCHECK_NE(reference_pendingNext_offset_.Uint32Value(), 0U);
return reference_pendingNext_offset_;
}
- static size_t GetFinalizerReferenceZombieOffset() {
- DCHECK_NE(finalizer_reference_zombie_offset_, 0U);
+ static MemberOffset GetFinalizerReferenceZombieOffset() {
+ DCHECK_NE(finalizer_reference_zombie_offset_.Uint32Value(), 0U);
return finalizer_reference_zombie_offset_;
}
+ static void DisableObjectValidation() {
+ // TODO: remove this hack necessary for image writing
+ verify_object_disabled_ = true;
+ }
+
private:
// Allocates uninitialized storage.
static Object* Allocate(size_t num_bytes);
@@ -158,19 +167,21 @@ class Heap {
static size_t num_objects_allocated_;
// offset of java.lang.ref.Reference.referent
- static size_t reference_referent_offset_;
+ static MemberOffset reference_referent_offset_;
// offset of java.lang.ref.Reference.queue
- static size_t reference_queue_offset_;
+ static MemberOffset reference_queue_offset_;
// offset of java.lang.ref.Reference.queueNext
- static size_t reference_queueNext_offset_;
+ static MemberOffset reference_queueNext_offset_;
// offset of java.lang.ref.Reference.pendingNext
- static size_t reference_pendingNext_offset_;
+ static MemberOffset reference_pendingNext_offset_;
// offset of java.lang.ref.FinalizerReference.zombie
- static size_t finalizer_reference_zombie_offset_;
+ static MemberOffset finalizer_reference_zombie_offset_;
+
+ static bool verify_object_disabled_;
DISALLOW_IMPLICIT_CONSTRUCTORS(Heap);
};
diff --git a/src/heap_test.cc b/src/heap_test.cc
index 568ddd2830..53489e454d 100644
--- a/src/heap_test.cc
+++ b/src/heap_test.cc
@@ -6,9 +6,9 @@ namespace art {
class HeapTest : public CommonTest {};
-TEST_F(HeapTest, GarbageCollectClassLinkerInit) {
+TEST_F(HeapTest, DISABLED_GarbageCollectClassLinkerInit) {
// garbage is created during ClassLinker::Init
Heap::CollectGarbage();
}
-} // namespace art
+} // namespace art
diff --git a/src/image_test.cc b/src/image_test.cc
index b03cbe3584..fd88b20848 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -1,5 +1,8 @@
// Copyright 2011 Google Inc. All Rights Reserved.
+#include <string>
+#include <vector>
+
#include "common_test.h"
#include "file.h"
#include "image.h"
@@ -12,7 +15,6 @@ namespace art {
class ImageTest : public CommonTest {};
TEST_F(ImageTest, WriteRead) {
-
// TODO: move the touching of classes and GC to the ImageWriter proper
for (size_t i = 0; i < java_lang_dex_file_->NumClassDefs(); i++) {
const DexFile::ClassDef& class_def = java_lang_dex_file_->GetClassDef(i);
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 887be66f4b..e0e77c70d3 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -118,6 +118,8 @@ void ImageWriter::CalculateNewObjectOffsets() {
void ImageWriter::CopyAndFixupObjects() {
HeapBitmap* heap_bitmap = Heap::GetLiveBits();
DCHECK(heap_bitmap != NULL);
+ // TODO: heap validation can't handle this fix up pass
+ Heap::DisableObjectValidation();
heap_bitmap->Walk(CopyAndFixupObjectsCallback, this);
}
@@ -140,7 +142,7 @@ void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void *arg) {
void ImageWriter::FixupObject(const Object* orig, Object* copy) {
DCHECK(orig != NULL);
DCHECK(copy != NULL);
- copy->klass_ = down_cast<Class*>(GetImageAddress(orig->klass_));
+ copy->SetClass(down_cast<Class*>(GetImageAddress(orig->GetClass())));
// TODO: special case init of pointers to malloc data (or removal of these pointers)
if (orig->IsClass()) {
FixupClass(orig->AsClass(), down_cast<Class*>(copy));
@@ -182,6 +184,13 @@ void ImageWriter::FixupMethod(const Method* orig, Method* copy) {
// TODO: remove need for this by adding "signature" to java.lang.reflect.Method
copy->signature_ = down_cast<String*>(GetImageAddress(orig->signature_));
DCHECK(copy->signature_ != NULL);
+ copy->dex_cache_strings_ = down_cast<ObjectArray<String>*>(GetImageAddress(orig->dex_cache_strings_));
+ copy->dex_cache_resolved_types_ = down_cast<ObjectArray<Class>*>(GetImageAddress(orig->dex_cache_resolved_types_));
+ copy->dex_cache_resolved_methods_ = down_cast<ObjectArray<Method>*>(GetImageAddress(orig->dex_cache_resolved_methods_));
+ copy->dex_cache_resolved_fields_ = down_cast<ObjectArray<Field>*>(GetImageAddress(orig->dex_cache_resolved_fields_));
+ copy->dex_cache_code_and_direct_methods_ = down_cast<CodeAndDirectMethods*>(GetImageAddress(orig->dex_cache_code_and_direct_methods_));
+ copy->dex_cache_initialized_static_storage_ = down_cast<ObjectArray<StaticStorageBase>*>(GetImageAddress(orig->dex_cache_initialized_static_storage_));
+
// TODO: convert shorty_ to heap allocated storage
}
@@ -193,7 +202,7 @@ void ImageWriter::FixupField(const Field* orig, Field* copy) {
void ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
for (int32_t i = 0; i < orig->GetLength(); ++i) {
const Object* element = orig->Get(i);
- copy->Set(i, GetImageAddress(element));
+ copy->SetWithoutChecks(i, GetImageAddress(element));
}
}
@@ -225,9 +234,9 @@ void ImageWriter::FixupFields(const Object* orig,
// Found a reference offset bitmap. Fixup the specified offsets.
while (ref_offsets != 0) {
size_t right_shift = CLZ(ref_offsets);
- size_t byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
- const Object* ref = orig->GetFieldObject(byte_offset);
- copy->SetFieldObject(byte_offset, GetImageAddress(ref));
+ MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
+ const Object* ref = orig->GetFieldObject<const Object*>(byte_offset, false);
+ copy->SetFieldObject(byte_offset, GetImageAddress(ref), false);
ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
}
} else {
@@ -245,9 +254,9 @@ void ImageWriter::FixupFields(const Object* orig,
Field* field = (is_static
? klass->GetStaticField(i)
: klass->GetInstanceField(i));
- size_t field_offset = field->GetOffset();
- const Object* ref = orig->GetFieldObject(field_offset);
- copy->SetFieldObject(field_offset, GetImageAddress(ref));
+ MemberOffset field_offset = field->GetOffset();
+ const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false);
+ copy->SetFieldObject(field_offset, GetImageAddress(ref), false);
}
}
}
diff --git a/src/image_writer.h b/src/image_writer.h
index 80012bcef6..b63effeb36 100644
--- a/src/image_writer.h
+++ b/src/image_writer.h
@@ -30,13 +30,13 @@ class ImageWriter {
// we use the lock word to store the offset of the object in the image
void SetImageOffset(Object* object, size_t offset) {
DCHECK(object != NULL);
- DCHECK(object->monitor_ == NULL); // should be no lock
+ DCHECK(object->GetMonitor() == NULL); // should be no lock
DCHECK_NE(0U, offset);
- object->monitor_ = reinterpret_cast<Monitor*>(offset);
+ object->SetMonitor(reinterpret_cast<Monitor*>(offset));
}
size_t GetImageOffset(const Object* object) {
DCHECK(object != NULL);
- size_t offset = reinterpret_cast<size_t>(object->monitor_);
+ size_t offset = reinterpret_cast<size_t>(object->GetMonitor());
DCHECK_NE(0U, offset);
return offset;
}
diff --git a/src/java_lang_System.cc b/src/java_lang_System.cc
index 43335ac205..e45519e4b9 100644
--- a/src/java_lang_System.cc
+++ b/src/java_lang_System.cc
@@ -183,7 +183,7 @@ void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject
// Neither class is primitive. Are the types trivially compatible?
const int width = sizeof(Object*);
- bool sameDimensions = srcArray->GetClass()->array_rank_ == dstArray->GetClass()->array_rank_;
+ bool sameDimensions = srcArray->GetClass()->GetArrayRank() == dstArray->GetClass()->GetArrayRank();
if (sameDimensions && srcComponentType->InstanceOf(dstComponentType)) {
// Yes. Bulk copy.
move32(dstBytes + dstPos * width, srcBytes + srcPos * width, length * width);
@@ -207,7 +207,7 @@ void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject
// race by modifying the source array after we check but before we copy,
// and cause us to copy incompatible elements.
- Object** srcObj = reinterpret_cast<ObjectArray<Object>*>(srcArray)->GetData() + srcPos;
+ Object* const * srcObj = reinterpret_cast<Object* const *>(srcBytes + srcPos * width);
Class* dstClass = dstArray->GetClass();
Class* initialElementClass = NULL;
diff --git a/src/jni_compiler.cc b/src/jni_compiler.cc
index adc87da84b..238b9ef350 100644
--- a/src/jni_compiler.cc
+++ b/src/jni_compiler.cc
@@ -4,6 +4,7 @@
#include "jni_compiler.h"
#include <sys/mman.h>
+#include <vector>
#include "assembler.h"
#include "calling_convention.h"
diff --git a/src/jni_compiler_test.cc b/src/jni_compiler_test.cc
index 3ffc184de9..254fbdf079 100644
--- a/src/jni_compiler_test.cc
+++ b/src/jni_compiler_test.cc
@@ -349,9 +349,12 @@ TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
int gSuspendCounterHandler_calls;
void SuspendCountHandler(Method** frame) {
+ EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
+ Thread::Current()->SetState(Thread::kRunnable);
EXPECT_TRUE((*frame)->GetName()->Equals("fooI"));
gSuspendCounterHandler_calls++;
Thread::Current()->DecrementSuspendCount();
+ Thread::Current()->SetState(Thread::kNative);
}
TEST_F(JniCompilerTest, SuspendCountAcknowledgement) {
@@ -377,9 +380,12 @@ TEST_F(JniCompilerTest, SuspendCountAcknowledgement) {
int gExceptionHandler_calls;
void ExceptionHandler(Method** frame) {
+ EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
+ Thread::Current()->SetState(Thread::kRunnable);
EXPECT_TRUE((*frame)->GetName()->Equals("throwException"));
gExceptionHandler_calls++;
Thread::Current()->ClearException();
+ Thread::Current()->SetState(Thread::kNative);
}
void Java_MyClass_throwException(JNIEnv* env, jobject) {
@@ -410,6 +416,8 @@ TEST_F(JniCompilerTest, ExceptionHandling) {
jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
if (i <= 0) {
+ EXPECT_EQ(Thread::kNative, Thread::Current()->GetState());
+ Thread::Current()->SetState(Thread::kRunnable);
ObjectArray<StackTraceElement>* trace_array = Thread::Current()->AllocStackTrace();
EXPECT_TRUE(trace_array != NULL);
EXPECT_EQ(11, trace_array->GetLength());
@@ -420,6 +428,7 @@ jint Java_MyClass_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
EXPECT_STREQ("MyClass", trace_array->Get(i)->GetDeclaringClass()->ToModifiedUtf8().c_str());
EXPECT_STREQ("fooI", trace_array->Get(i)->GetMethodName()->ToModifiedUtf8().c_str());
}
+ Thread::Current()->SetState(Thread::kNative);
return 0;
} else {
jclass jklass = env->FindClass("MyClass");
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 36787d8b2b..125401eec5 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -346,12 +346,26 @@ jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* nam
}
Field* field = NULL;
+ Class* field_type;
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ if (sig[1] != '\0') {
+ // TODO: need to get the appropriate ClassLoader.
+ const ClassLoader* cl = ts.Self()->GetClassLoaderOverride();
+ field_type = class_linker->FindClass(sig, cl);
+ } else {
+ field_type = class_linker->FindPrimitiveClass(*sig);
+ }
+ if (field_type == NULL) {
+ // Failed to find type from the signature of the field.
+ // TODO: Linkage or NoSuchFieldError?
+ CHECK(ts.Self()->IsExceptionPending());
+ return NULL;
+ }
if (is_static) {
- field = c->FindStaticField(name, sig);
+ field = c->FindStaticField(name, field_type);
} else {
- field = c->FindInstanceField(name, sig);
+ field = c->FindInstanceField(name, field_type);
}
-
if (field == NULL) {
Thread* self = Thread::Current();
std::string class_descriptor(c->GetDescriptor()->ToModifiedUtf8());
@@ -360,7 +374,9 @@ jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* nam
name, class_descriptor.c_str());
return NULL;
}
-
+ // Check invariant that all jfieldIDs have resolved types (how else would
+ // the type equality in Find...Field hold?)
+ DCHECK(field->GetType() != NULL);
jweak fid = AddWeakGlobalReference(ts, field);
return reinterpret_cast<jfieldID>(fid);
}
diff --git a/src/jni_internal_arm.cc b/src/jni_internal_arm.cc
index 0d19c1cfb5..6b4162bc79 100644
--- a/src/jni_internal_arm.cc
+++ b/src/jni_internal_arm.cc
@@ -49,7 +49,7 @@ void CreateInvokeStub(Assembler* assembler, Method* method) {
size_t reg_bytes = (method->IsStatic() ? 3 : 2) * kPointerSize;
// Bytes passed by stack
size_t stack_bytes;
- if( method->NumArgArrayBytes() > reg_bytes){
+ if (method->NumArgArrayBytes() > reg_bytes) {
stack_bytes = method->NumArgArrayBytes() - reg_bytes;
} else {
stack_bytes = 0;
@@ -61,7 +61,7 @@ void CreateInvokeStub(Assembler* assembler, Method* method) {
__ StoreToOffset(kStoreWord, IP, SP, 0);
// Copy values by stack
- for(size_t off = 0; off < stack_bytes; off += kPointerSize) {
+ for (size_t off = 0; off < stack_bytes; off += kPointerSize) {
// we're displaced off of r3 by bytes that'll go in registers
int r3_offset = reg_bytes + off;
__ LoadFromOffset(kLoadWord, IP, R3, r3_offset);
@@ -93,7 +93,7 @@ void CreateInvokeStub(Assembler* assembler, Method* method) {
}
// Load the code pointer we are about to call.
- __ LoadFromOffset(kLoadWord, IP, R0, method->GetCodeOffset());
+ __ LoadFromOffset(kLoadWord, IP, R0, method->GetCodeOffset().Int32Value());
// Do the call.
__ blx(IP);
diff --git a/src/jni_internal_test.cc b/src/jni_internal_test.cc
index 3e3e3814e8..e82b7348dd 100644
--- a/src/jni_internal_test.cc
+++ b/src/jni_internal_test.cc
@@ -2,9 +2,10 @@
#include "jni_internal.h"
-#include <cmath>
#include <sys/mman.h>
+#include <cmath>
+
#include "common_test.h"
namespace art {
@@ -1560,4 +1561,4 @@ TEST_F(JniInternalTest, DISABLED_NewDirectBuffer_GetDirectBufferAddress_GetDirec
ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes));
}
-}
+} // namespace art
diff --git a/src/jni_internal_x86.cc b/src/jni_internal_x86.cc
index ad30accd98..782ff66b19 100644
--- a/src/jni_internal_x86.cc
+++ b/src/jni_internal_x86.cc
@@ -60,7 +60,7 @@ void CreateInvokeStub(Assembler* assembler, Method* method) {
if (ch != 'V') {
// Load the result JValue pointer.
__ movl(EDI, Address(ESP, 24));
- switch(ch) {
+ switch (ch) {
case 'D':
__ fstpl(Address(EDI, 0));
break;
@@ -76,7 +76,7 @@ void CreateInvokeStub(Assembler* assembler, Method* method) {
break;
}
}
- __ popl(EDI); // restore EDI
+ __ popl(EDI); // restore EDI
__ ret();
}
diff --git a/src/mark_sweep.cc b/src/mark_sweep.cc
index af7f1a5015..ac9a7cd65a 100644
--- a/src/mark_sweep.cc
+++ b/src/mark_sweep.cc
@@ -191,8 +191,8 @@ void MarkSweep::ScanFields(const Object* obj,
// Found a reference offset bitmap. Mark the specified offsets.
while (ref_offsets != 0) {
size_t right_shift = CLZ(ref_offsets);
- size_t byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
- const Object* ref = obj->GetFieldObject(byte_offset);
+ MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
+ const Object* ref = obj->GetFieldObject<const Object*>(byte_offset, false);
MarkObject(ref);
ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
}
@@ -211,8 +211,8 @@ void MarkSweep::ScanFields(const Object* obj,
Field* field = (is_static
? klass->GetStaticField(i)
: klass->GetInstanceField(i));
- size_t field_offset = field->GetOffset();
- const Object* ref = obj->GetFieldObject(field_offset);
+ MemberOffset field_offset = field->GetOffset();
+ const Object* ref = obj->GetFieldObject<const Object*>(field_offset, false);
MarkObject(ref);
}
}
@@ -267,32 +267,33 @@ void MarkSweep::ScanArray(const Object* obj) {
void MarkSweep::EnqueuePendingReference(Object* ref, Object** list) {
DCHECK(ref != NULL);
DCHECK(list != NULL);
- size_t offset = Heap::GetReferencePendingNextOffset();
+
+ MemberOffset offset = Heap::GetReferencePendingNextOffset();
if (*list == NULL) {
- ref->SetFieldObject(offset, ref);
+ ref->SetFieldObject(offset, ref, false);
*list = ref;
} else {
- Object* head = (*list)->GetFieldObject(offset);
- ref->SetFieldObject(offset, head);
- (*list)->SetFieldObject(offset, ref);
+ Object* head = (*list)->GetFieldObject<Object*>(offset, false);
+ ref->SetFieldObject(offset, head, false);
+ (*list)->SetFieldObject(offset, ref, false);
}
}
Object* MarkSweep::DequeuePendingReference(Object** list) {
DCHECK(list != NULL);
DCHECK(*list != NULL);
- size_t offset = Heap::GetReferencePendingNextOffset();
- Object* head = (*list)->GetFieldObject(offset);
+ MemberOffset offset = Heap::GetReferencePendingNextOffset();
+ Object* head = (*list)->GetFieldObject<Object*>(offset, false);
Object* ref;
if (*list == head) {
ref = *list;
*list = NULL;
} else {
- Object* next = head->GetFieldObject(offset);
- (*list)->SetFieldObject(offset, next);
+ Object* next = head->GetFieldObject<Object*>(offset, false);
+ (*list)->SetFieldObject(offset, next, false);
ref = head;
}
- ref->SetFieldObject(offset, NULL);
+ ref->SetFieldObject(offset, NULL, false);
return ref;
}
@@ -303,18 +304,18 @@ void MarkSweep::DelayReferenceReferent(Object* obj) {
DCHECK(obj != NULL);
Class* klass = obj->GetClass();
DCHECK(klass != NULL);
- DCHECK(klass->IsReference());
- Object* pending = obj->GetFieldObject(Heap::GetReferencePendingNextOffset());
- Object* referent = obj->GetFieldObject(Heap::GetReferenceReferentOffset());
+ DCHECK(klass->IsReferenceClass());
+ Object* pending = obj->GetFieldObject<Object*>(Heap::GetReferencePendingNextOffset(), false);
+ Object* referent = obj->GetFieldObject<Object*>(Heap::GetReferenceReferentOffset(), false);
if (pending == NULL && referent != NULL && !IsMarked(referent)) {
Object** list = NULL;
- if (klass->IsSoftReference()) {
+ if (klass->IsSoftReferenceClass()) {
list = &soft_reference_list_;
- } else if (klass->IsWeakReference()) {
+ } else if (klass->IsWeakReferenceClass()) {
list = &weak_reference_list_;
- } else if (klass->IsFinalizerReference()) {
+ } else if (klass->IsFinalizerReferenceClass()) {
list = &finalizer_reference_list_;
- } else if (klass->IsPhantomReference()) {
+ } else if (klass->IsPhantomReferenceClass()) {
list = &phantom_reference_list_;
}
DCHECK(list != NULL);
@@ -331,7 +332,7 @@ void MarkSweep::ScanOther(const Object* obj) {
DCHECK(klass != NULL);
MarkObject(klass);
ScanInstanceFields(obj);
- if (klass->IsReference()) {
+ if (klass->IsReferenceClass()) {
DelayReferenceReferent(const_cast<Object*>(obj));
}
}
@@ -366,20 +367,22 @@ void MarkSweep::ScanDirtyObjects() {
void MarkSweep::ClearReference(Object* ref) {
DCHECK(ref != NULL);
- ref->SetFieldObject(Heap::GetReferenceReferentOffset(), NULL);
+ ref->SetFieldObject(Heap::GetReferenceReferentOffset(), NULL, false);
}
bool MarkSweep::IsEnqueuable(const Object* ref) {
DCHECK(ref != NULL);
- const Object* queue = ref->GetFieldObject(Heap::GetReferenceQueueOffset());
- const Object* queue_next = ref->GetFieldObject(Heap::GetReferenceQueueNextOffset());
+ const Object* queue =
+ ref->GetFieldObject<Object*>(Heap::GetReferenceQueueOffset(), false);
+ const Object* queue_next =
+ ref->GetFieldObject<Object*>(Heap::GetReferenceQueueNextOffset(), false);
return (queue != NULL) && (queue_next == NULL);
}
void MarkSweep::EnqueueReference(Object* ref) {
DCHECK(ref != NULL);
- CHECK(ref->GetFieldObject(Heap::GetReferenceQueueOffset()) != NULL);
- CHECK(ref->GetFieldObject(Heap::GetReferenceQueueNextOffset()) == NULL);
+ CHECK(ref->GetFieldObject<Object*>(Heap::GetReferenceQueueOffset(), false) != NULL);
+ CHECK(ref->GetFieldObject<Object*>(Heap::GetReferenceQueueNextOffset(), false) == NULL);
EnqueuePendingReference(ref, &cleared_reference_list_);
}
@@ -393,7 +396,7 @@ void MarkSweep::PreserveSomeSoftReferences(Object** list) {
size_t counter = 0;
while (*list != NULL) {
Object* ref = DequeuePendingReference(list);
- Object* referent = ref->GetFieldObject(Heap::GetReferenceReferentOffset());
+ Object* referent = ref->GetFieldObject<Object*>(Heap::GetReferenceReferentOffset(), false);
if (referent == NULL) {
// Referent was cleared by the user during marking.
continue;
@@ -420,10 +423,10 @@ void MarkSweep::PreserveSomeSoftReferences(Object** list) {
// scheduled for appending by the heap worker thread.
void MarkSweep::ClearWhiteReferences(Object** list) {
DCHECK(list != NULL);
- size_t offset = Heap::GetReferenceReferentOffset();
+ MemberOffset offset = Heap::GetReferenceReferentOffset();
while (*list != NULL) {
Object* ref = DequeuePendingReference(list);
- Object* referent = ref->GetFieldObject(offset);
+ Object* referent = ref->GetFieldObject<Object*>(offset, false);
if (referent != NULL && !IsMarked(referent)) {
// Referent is white, clear it.
ClearReference(ref);
@@ -440,17 +443,17 @@ void MarkSweep::ClearWhiteReferences(Object** list) {
// referent field is cleared.
void MarkSweep::EnqueueFinalizerReferences(Object** list) {
DCHECK(list != NULL);
- size_t referent_offset = Heap::GetReferenceReferentOffset();
- size_t zombie_offset = Heap::GetFinalizerReferenceZombieOffset();
+ MemberOffset referent_offset = Heap::GetReferenceReferentOffset();
+ MemberOffset zombie_offset = Heap::GetFinalizerReferenceZombieOffset();
bool has_enqueued = false;
while (*list != NULL) {
Object* ref = DequeuePendingReference(list);
- Object* referent = ref->GetFieldObject(referent_offset);
+ Object* referent = ref->GetFieldObject<Object*>(referent_offset, false);
if (referent != NULL && !IsMarked(referent)) {
MarkObject(referent);
// If the referent is non-null the reference must queuable.
DCHECK(IsEnqueuable(ref));
- ref->SetFieldObject(zombie_offset, referent);
+ ref->SetFieldObject(zombie_offset, referent, false);
ClearReference(ref);
EnqueueReference(ref);
has_enqueued = true;
diff --git a/src/mark_sweep.h b/src/mark_sweep.h
index f20cc416bf..841d8191cc 100644
--- a/src/mark_sweep.h
+++ b/src/mark_sweep.h
@@ -6,6 +6,7 @@
#include "macros.h"
#include "mark_stack.h"
#include "object_bitmap.h"
+#include "offsets.h"
namespace art {
diff --git a/src/object.cc b/src/object.cc
index cdc0e69100..39d3c25dcd 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -3,7 +3,10 @@
#include "object.h"
#include <string.h>
+
#include <algorithm>
+#include <string>
+#include <utility>
#include "class_linker.h"
#include "class_loader.h"
@@ -17,198 +20,40 @@
namespace art {
-Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
- DCHECK_GE(component_count, 0);
- DCHECK(array_class->IsArrayClass());
- size_t size = SizeOf(component_count, component_size);
- Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
- if (array != NULL) {
- DCHECK(array->IsArrayInstance());
- array->SetLength(component_count);
- }
- return array;
-}
-
-Array* Array::Alloc(Class* array_class, int32_t component_count) {
- return Alloc(array_class, component_count, array_class->GetComponentSize());
+bool Object::IsString() const {
+ // TODO use "klass_ == String::GetJavaLangString()" instead?
+ return GetClass() == GetClass()->GetDescriptor()->GetClass();
}
-Array* Array::AllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) {
- // TODO: throw on negative component_count
- Class* klass = method->dex_cache_resolved_types_->Get(type_idx);
- if (klass == NULL) {
- klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
- if (klass == NULL || !klass->IsArrayClass()) {
- UNIMPLEMENTED(FATAL) << "throw an error";
- return NULL;
- }
- }
- return Array::Alloc(klass, component_count);
-}
+// TODO: get global references for these
+Class* Field::java_lang_reflect_Field_ = NULL;
-Object* Class::AllocObjectFromCode(uint32_t type_idx, Method* method) {
- Class* klass = method->dex_cache_resolved_types_->Get(type_idx);
- if (klass == NULL) {
- klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
- if (klass == NULL) {
- UNIMPLEMENTED(FATAL) << "throw an error";
- return NULL;
- }
- }
- return klass->AllocObject();
+void Field::SetClass(Class* java_lang_reflect_Field) {
+ CHECK(java_lang_reflect_Field_ == NULL);
+ CHECK(java_lang_reflect_Field != NULL);
+ java_lang_reflect_Field_ = java_lang_reflect_Field;
}
-Object* Class::AllocObject() {
- DCHECK(!IsAbstract());
- return Heap::AllocObject(this, this->object_size_);
+void Field::ResetClass() {
+ CHECK(java_lang_reflect_Field_ != NULL);
+ java_lang_reflect_Field_ = NULL;
}
-bool Class::CanPutArrayElementFromCode(const Class* elementClass, const Class* arrayClass) {
- UNIMPLEMENTED(FATAL);
- return false;
+void Field::SetTypeIdx(uint32_t type_idx) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), type_idx, false);
}
-bool Class::Implements(const Class* klass) const {
- DCHECK(klass != NULL);
- DCHECK(klass->IsInterface());
- // All interfaces implemented directly and by our superclass, and
- // recursively all super-interfaces of those interfaces, are listed
- // in iftable_, so we can just do a linear scan through that.
- for (size_t i = 0; i < iftable_count_; i++) {
- if (iftable_[i].GetInterface() == klass) {
- return true;
- }
- }
- return false;
+Class* Field::GetTypeDuringLinking() const {
+ // We are assured that the necessary primitive types are in the dex cache
+ // early during class linking
+ return GetDeclaringClass()->GetDexCache()->GetResolvedType(GetTypeIdx());
}
-// Determine whether "this" is assignable from "klazz", where both of these
-// are array classes.
-//
-// Consider an array class, e.g. Y[][], where Y is a subclass of X.
-// Y[][] = Y[][] --> true (identity)
-// X[][] = Y[][] --> true (element superclass)
-// Y = Y[][] --> false
-// Y[] = Y[][] --> false
-// Object = Y[][] --> true (everything is an object)
-// Object[] = Y[][] --> true
-// Object[][] = Y[][] --> true
-// Object[][][] = Y[][] --> false (too many []s)
-// Serializable = Y[][] --> true (all arrays are Serializable)
-// Serializable[] = Y[][] --> true
-// Serializable[][] = Y[][] --> false (unless Y is Serializable)
-//
-// Don't forget about primitive types.
-// int[] instanceof Object[] --> false
-//
-bool Class::IsArrayAssignableFromArray(const Class* klass) const {
- DCHECK(IsArrayClass());
- DCHECK(klass->IsArrayClass());
- DCHECK_GT(array_rank_, 0);
- DCHECK_GT(klass->array_rank_, 0);
- DCHECK(component_type_ != NULL);
- DCHECK(klass->component_type_ != NULL);
- if (array_rank_ > klass->array_rank_) {
- // Too many []s.
- return false;
- }
- if (array_rank_ == klass->array_rank_) {
- return component_type_->IsAssignableFrom(klass->component_type_);
- }
- DCHECK_LT(array_rank_, klass->array_rank_);
- // The thing we might be assignable from has more dimensions. We
- // must be an Object or array of Object, or a standard array
- // interface or array of standard array interfaces (the standard
- // interfaces being java/lang/Cloneable and java/io/Serializable).
- if (component_type_->IsInterface()) {
- // See if we implement our component type. We know the
- // base element is an interface; if the array class implements
- // it, we know it's a standard array interface.
- return Implements(component_type_);
- }
- // See if this is an array of Object, Object[], etc. We know
- // that the superclass of an array is always Object, so we
- // just compare the element type to that.
- Class* java_lang_Object = GetSuperClass();
- DCHECK(java_lang_Object != NULL);
- DCHECK(java_lang_Object->GetSuperClass() == NULL);
- return (component_type_ == java_lang_Object);
-}
-
-bool Class::IsAssignableFromArray(const Class* klass) const {
- DCHECK(!IsInterface()); // handled first in IsAssignableFrom
- DCHECK(klass->IsArrayClass());
- if (!IsArrayClass()) {
- // If "this" is not also an array, it must be Object.
- // klass's super should be java_lang_Object, since it is an array.
- Class* java_lang_Object = klass->GetSuperClass();
- DCHECK(java_lang_Object != NULL);
- DCHECK(java_lang_Object->GetSuperClass() == NULL);
- return this == java_lang_Object;
- }
- return IsArrayAssignableFromArray(klass);
-}
-
-bool Class::IsSubClass(const Class* klass) const {
- DCHECK(!IsInterface());
- DCHECK(!klass->IsArrayClass());
- const Class* current = this;
- do {
- if (current == klass) {
- return true;
- }
- current = current->GetSuperClass();
- } while (current != NULL);
- return false;
-}
-
-bool Class::IsInSamePackage(const String* descriptor_string_1,
- const String* descriptor_string_2) {
- const std::string descriptor1(descriptor_string_1->ToModifiedUtf8());
- const std::string descriptor2(descriptor_string_2->ToModifiedUtf8());
-
- size_t i = 0;
- while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
- ++i;
- }
- if (descriptor1.find('/', i) != StringPiece::npos ||
- descriptor2.find('/', i) != StringPiece::npos) {
- return false;
- } else {
- return true;
- }
-}
-
-#if 0
-bool Class::IsInSamePackage(const StringPiece& descriptor1,
- const StringPiece& descriptor2) {
- size_t size = std::min(descriptor1.size(), descriptor2.size());
- std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
- pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
- descriptor2.begin());
- return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
-}
-#endif
-
-bool Class::IsInSamePackage(const Class* that) const {
- const Class* klass1 = this;
- const Class* klass2 = that;
- if (klass1 == klass2) {
- return true;
- }
- // Class loaders must match.
- if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
- return false;
- }
- // Arrays are in the same package when their element classes are.
- if (klass1->IsArrayClass()) {
- klass1 = klass1->GetComponentType();
- }
- if (klass2->IsArrayClass()) {
- klass2 = klass2->GetComponentType();
- }
- // Compare the package part of the descriptor string.
- return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
+Class* Field::GetType() const {
+ DCHECK(Runtime::Current() != NULL)
+ << "Can't call GetType without an initialized runtime";
+ // Do full linkage (which sets dex cache value to speed next call)
+ return Runtime::Current()->GetClassLinker()->ResolveType(GetTypeIdx(), this);
}
uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) {
@@ -217,6 +62,7 @@ uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer)
UNIMPLEMENTED(FATAL) << "throw an error";
return 0;
}
+ DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
return field->Get32(NULL);
}
void Field::Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint32_t new_value) {
@@ -225,6 +71,7 @@ void Field::Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint
UNIMPLEMENTED(FATAL) << "throw an error";
return;
}
+ DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
field->Set32(NULL, new_value);
}
uint64_t Field::Get64StaticFromCode(uint32_t field_idx, const Method* referrer) {
@@ -233,6 +80,7 @@ uint64_t Field::Get64StaticFromCode(uint32_t field_idx, const Method* referrer)
UNIMPLEMENTED(FATAL) << "throw an error";
return 0;
}
+ DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
return field->Get64(NULL);
}
void Field::Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint64_t new_value) {
@@ -241,6 +89,7 @@ void Field::Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint
UNIMPLEMENTED(FATAL) << "throw an error";
return;
}
+ DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
field->Set64(NULL, new_value);
}
Object* Field::GetObjStaticFromCode(uint32_t field_idx, const Method* referrer) {
@@ -249,6 +98,7 @@ Object* Field::GetObjStaticFromCode(uint32_t field_idx, const Method* referrer)
UNIMPLEMENTED(FATAL) << "throw an error";
return 0;
}
+ DCHECK(!field->GetType()->IsPrimitive());
return field->GetObj(NULL);
}
void Field::SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Object* new_value) {
@@ -257,6 +107,7 @@ void Field::SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Obj
UNIMPLEMENTED(FATAL) << "throw an error";
return;
}
+ DCHECK(!field->GetType()->IsPrimitive());
field->SetObj(NULL, new_value);
}
@@ -265,8 +116,7 @@ uint32_t Field::Get32(const Object* object) const {
if (IsStatic()) {
object = declaring_class_;
}
- // TODO: volatile
- return object->GetField32(GetOffset());
+ return object->GetField32(GetOffset(), IsVolatile());
}
void Field::Set32(Object* object, uint32_t new_value) const {
@@ -274,8 +124,7 @@ void Field::Set32(Object* object, uint32_t new_value) const {
if (IsStatic()) {
object = declaring_class_;
}
- // TODO: volatile
- object->SetField32(GetOffset(), new_value);
+ object->SetField32(GetOffset(), new_value, IsVolatile());
}
uint64_t Field::Get64(const Object* object) const {
@@ -283,8 +132,7 @@ uint64_t Field::Get64(const Object* object) const {
if (IsStatic()) {
object = declaring_class_;
}
- // TODO: volatile
- return object->GetField64(GetOffset());
+ return object->GetField64(GetOffset(), IsVolatile());
}
void Field::Set64(Object* object, uint64_t new_value) const {
@@ -292,8 +140,7 @@ void Field::Set64(Object* object, uint64_t new_value) const {
if (IsStatic()) {
object = declaring_class_;
}
- // TODO: volatile
- object->SetField64(GetOffset(), new_value);
+ object->SetField64(GetOffset(), new_value, IsVolatile());
}
Object* Field::GetObj(const Object* object) const {
@@ -301,8 +148,7 @@ Object* Field::GetObj(const Object* object) const {
if (IsStatic()) {
object = declaring_class_;
}
- // TODO: volatile
- return object->GetFieldObject(GetOffset());
+ return object->GetFieldObject<Object*>(GetOffset(), IsVolatile());
}
void Field::SetObj(Object* object, const Object* new_value) const {
@@ -310,113 +156,208 @@ void Field::SetObj(Object* object, const Object* new_value) const {
if (IsStatic()) {
object = declaring_class_;
}
- // TODO: volatile
- object->SetFieldObject(GetOffset(), new_value);
+ object->SetFieldObject(GetOffset(), new_value, IsVolatile());
}
bool Field::GetBoolean(const Object* object) const {
- CHECK_EQ(GetType(), 'Z');
+ DCHECK(GetType()->IsPrimitiveBoolean());
return Get32(object);
}
void Field::SetBoolean(Object* object, bool z) const {
- CHECK_EQ(GetType(), 'Z');
+ DCHECK(GetType()->IsPrimitiveBoolean());
Set32(object, z);
}
int8_t Field::GetByte(const Object* object) const {
- CHECK_EQ(GetType(), 'B');
+ DCHECK(GetType()->IsPrimitiveByte());
return Get32(object);
}
void Field::SetByte(Object* object, int8_t b) const {
- CHECK_EQ(GetType(), 'B');
+ DCHECK(GetType()->IsPrimitiveByte());
Set32(object, b);
}
uint16_t Field::GetChar(const Object* object) const {
- CHECK_EQ(GetType(), 'C');
+ DCHECK(GetType()->IsPrimitiveChar());
return Get32(object);
}
void Field::SetChar(Object* object, uint16_t c) const {
- CHECK_EQ(GetType(), 'C');
+ DCHECK(GetType()->IsPrimitiveChar());
Set32(object, c);
}
uint16_t Field::GetShort(const Object* object) const {
- CHECK_EQ(GetType(), 'S');
+ DCHECK(GetType()->IsPrimitiveShort());
return Get32(object);
}
void Field::SetShort(Object* object, uint16_t s) const {
- CHECK_EQ(GetType(), 'S');
+ DCHECK(GetType()->IsPrimitiveShort());
Set32(object, s);
}
int32_t Field::GetInt(const Object* object) const {
- CHECK_EQ(GetType(), 'I');
+ DCHECK(GetType()->IsPrimitiveInt());
return Get32(object);
}
void Field::SetInt(Object* object, int32_t i) const {
- CHECK_EQ(GetType(), 'I');
+ DCHECK(GetType()->IsPrimitiveInt());
Set32(object, i);
}
int64_t Field::GetLong(const Object* object) const {
- CHECK_EQ(GetType(), 'J');
+ DCHECK(GetType()->IsPrimitiveLong());
return Get64(object);
}
void Field::SetLong(Object* object, int64_t j) const {
- CHECK_EQ(GetType(), 'J');
+ DCHECK(GetType()->IsPrimitiveLong());
Set64(object, j);
}
float Field::GetFloat(const Object* object) const {
- CHECK_EQ(GetType(), 'F');
+ DCHECK(GetType()->IsPrimitiveFloat());
JValue float_bits;
float_bits.i = Get32(object);
return float_bits.f;
}
void Field::SetFloat(Object* object, float f) const {
- CHECK_EQ(GetType(), 'F');
+ DCHECK(GetType()->IsPrimitiveFloat());
JValue float_bits;
float_bits.f = f;
Set32(object, float_bits.i);
}
double Field::GetDouble(const Object* object) const {
- CHECK_EQ(GetType(), 'D');
+ DCHECK(GetType()->IsPrimitiveDouble());
JValue double_bits;
double_bits.j = Get64(object);
return double_bits.d;
}
void Field::SetDouble(Object* object, double d) const {
- CHECK_EQ(GetType(), 'D');
+ DCHECK(GetType()->IsPrimitiveDouble());
JValue double_bits;
double_bits.d = d;
Set64(object, double_bits.j);
}
Object* Field::GetObject(const Object* object) const {
- CHECK(GetType() == 'L' || GetType() == '[');
+ CHECK(!GetType()->IsPrimitive());
return GetObj(object);
}
void Field::SetObject(Object* object, const Object* l) const {
- CHECK(GetType() == 'L' || GetType() == '[');
+ CHECK(!GetType()->IsPrimitive());
SetObj(object, l);
}
-uint32_t Method::NumArgRegisters() const {
- CHECK(shorty_ != NULL);
+// TODO: get global references for these
+Class* Method::java_lang_reflect_Method_ = NULL;
+
+void Method::SetClass(Class* java_lang_reflect_Method) {
+ CHECK(java_lang_reflect_Method_ == NULL);
+ CHECK(java_lang_reflect_Method != NULL);
+ java_lang_reflect_Method_ = java_lang_reflect_Method;
+}
+
+void Method::ResetClass() {
+ CHECK(java_lang_reflect_Method_ != NULL);
+ java_lang_reflect_Method_ = NULL;
+}
+
+ObjectArray<String>* Method::GetDexCacheStrings() const {
+ return GetFieldObject<ObjectArray<String>*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_), false);
+}
+
+void Method::SetReturnTypeIdx(uint32_t new_return_type_idx) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
+ new_return_type_idx, false);
+}
+
+Class* Method::GetReturnType() const {
+ DCHECK(GetDeclaringClass()->IsLinked());
+ // Short-cut
+ Class* result = GetDexCacheResolvedTypes()->Get(GetReturnTypeIdx());
+ if (result == NULL) {
+ // Do full linkage and set cache value for next call
+ result = Runtime::Current()->GetClassLinker()->ResolveType(GetReturnTypeIdx(), this);
+ }
+ CHECK(result != NULL);
+ return result;
+}
+
+void Method::SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_),
+ new_dex_cache_strings, false);
+}
+
+ObjectArray<Class>* Method::GetDexCacheResolvedTypes() const {
+ return GetFieldObject<ObjectArray<Class>*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_), false);
+}
+
+void Method::SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_classes) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_types_),
+ new_dex_cache_classes, false);
+}
+
+ObjectArray<Method>* Method::GetDexCacheResolvedMethods() const {
+ return GetFieldObject<ObjectArray<Method>*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_), false);
+}
+
+void Method::SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_methods_),
+ new_dex_cache_methods, false);
+}
+
+ObjectArray<Field>* Method::GetDexCacheResolvedFields() const {
+ return GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_), false);
+}
+
+void Method::SetDexCacheResolvedFields(ObjectArray<Field>* new_dex_cache_fields) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_resolved_fields_),
+ new_dex_cache_fields, false);
+}
+
+CodeAndDirectMethods* Method::GetDexCacheCodeAndDirectMethods() const {
+ return GetFieldPtr<CodeAndDirectMethods*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
+ false);
+}
+
+void Method::SetDexCacheCodeAndDirectMethods(CodeAndDirectMethods* new_value) {
+ SetFieldPtr<CodeAndDirectMethods*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_code_and_direct_methods_),
+ new_value, false);
+}
+
+ObjectArray<StaticStorageBase>* Method::GetDexCacheInitializedStaticStorage() const {
+ return GetFieldObject<ObjectArray<StaticStorageBase>*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
+ false);
+}
+
+void Method::SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value) {
+ SetFieldObject(
+ OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_initialized_static_storage_),
+ new_value, false);
+
+}
+
+size_t Method::NumArgRegisters(const StringPiece& shorty) {
+ CHECK_LE(1, shorty.length());
uint32_t num_registers = 0;
- for (int i = 1; i < shorty_.length(); ++i) {
- char ch = shorty_[i];
+ for (int i = 1; i < shorty.length(); ++i) {
+ char ch = shorty[i];
if (ch == 'D' || ch == 'J') {
num_registers += 2;
} else {
@@ -429,7 +370,7 @@ uint32_t Method::NumArgRegisters() const {
size_t Method::NumArgArrayBytes() const {
const StringPiece& shorty = GetShorty();
size_t num_bytes = 0;
- for (int i = 1; i < shorty.size(); ++i) {
+ for (int i = 1; i < shorty.length(); ++i) {
char ch = shorty[i];
if (ch == 'D' || ch == 'J') {
num_bytes += 8;
@@ -447,9 +388,10 @@ size_t Method::NumArgArrayBytes() const {
// The number of reference arguments to this method including implicit this
// pointer
size_t Method::NumReferenceArgs() const {
+ const StringPiece& shorty = GetShorty();
size_t result = IsStatic() ? 0 : 1; // The implicit this pointer.
- for (int i = 1; i < shorty_.length(); i++) {
- if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
+ for (int i = 1; i < shorty.length(); i++) {
+ if ((shorty[i] == 'L') || (shorty[i] == '[')) {
result++;
}
}
@@ -458,9 +400,10 @@ size_t Method::NumReferenceArgs() const {
// The number of long or double arguments
size_t Method::NumLongOrDoubleArgs() const {
+ const StringPiece& shorty = GetShorty();
size_t result = 0;
- for (int i = 1; i < shorty_.length(); i++) {
- if ((shorty_[i] == 'D') || (shorty_[i] == 'J')) {
+ for (int i = 1; i < shorty.length(); i++) {
+ if ((shorty[i] == 'D') || (shorty[i] == 'J')) {
result++;
}
}
@@ -470,11 +413,12 @@ size_t Method::NumLongOrDoubleArgs() const {
// The number of reference arguments to this method before the given parameter
// index
size_t Method::NumReferenceArgsBefore(unsigned int param) const {
+ const StringPiece& shorty = GetShorty();
CHECK_LT(param, NumArgs());
unsigned int result = IsStatic() ? 0 : 1;
- for (unsigned int i = 1; (i < (unsigned int)shorty_.length()) &&
+ for (unsigned int i = 1; (i < (unsigned int)shorty.length()) &&
(i < (param + 1)); i++) {
- if ((shorty_[i] == 'L') || (shorty_[i] == '[')) {
+ if (shorty[i] == 'L') {
result++;
}
}
@@ -489,7 +433,7 @@ bool Method::IsParamAReference(unsigned int param) const {
} else if (param == 0) {
return true; // this argument
}
- return ((shorty_[param] == 'L') || (shorty_[param] == '['));
+ return GetShorty()[param] == 'L';
}
// Is the given method parameter a long or double?
@@ -500,7 +444,7 @@ bool Method::IsParamALongOrDouble(unsigned int param) const {
} else if (param == 0) {
return false; // this argument
}
- return (shorty_[param] == 'J') || (shorty_[param] == 'D');
+ return (GetShorty()[param] == 'J') || (GetShorty()[param] == 'D');
}
static size_t ShortyCharToSize(char x) {
@@ -521,11 +465,11 @@ size_t Method::ParamSize(unsigned int param) const {
} else if (param == 0) {
return kPointerSize; // this argument
}
- return ShortyCharToSize(shorty_[param]);
+ return ShortyCharToSize(GetShorty()[param]);
}
size_t Method::ReturnSize() const {
- return ShortyCharToSize(shorty_[0]);
+ return ShortyCharToSize(GetShorty()[0]);
}
bool Method::HasSameNameAndDescriptor(const Method* that) const {
@@ -533,6 +477,278 @@ bool Method::HasSameNameAndDescriptor(const Method* that) const {
this->GetSignature()->Equals(that->GetSignature()));
}
+void Method::SetCode(const byte* compiled_code,
+ size_t byte_count,
+ InstructionSet set) {
+ // Copy the code into an executable region.
+ code_instruction_set_ = set;
+ code_area_.reset(MemMap::Map(byte_count,
+ PROT_READ | PROT_WRITE | PROT_EXEC));
+ CHECK(code_area_.get());
+ byte* code = code_area_->GetAddress();
+ memcpy(code, compiled_code, byte_count);
+ __builtin___clear_cache(code, code + byte_count);
+
+ uintptr_t address = reinterpret_cast<uintptr_t>(code);
+ if (code_instruction_set_ == kThumb2) {
+ // Set the low-order bit so a BLX will switch to Thumb mode
+ address |= 0x1;
+ }
+ SetFieldPtr<uintptr_t>(OFFSET_OF_OBJECT_MEMBER(Method, code_), address, false);
+}
+
+void Class::SetStatus(Status new_status) {
+ CHECK(new_status > GetStatus() || new_status == kStatusError ||
+ Runtime::Current() == NULL); // no runtime implies we're not initialized
+ CHECK(sizeof(Status) == sizeof(uint32_t));
+ return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_),
+ new_status, false);
+}
+
+DexCache* Class::GetDexCache() const {
+ return GetFieldObject<DexCache*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), false);
+}
+
+void Class::SetDexCache(DexCache* new_dex_cache) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_),
+ new_dex_cache, false);
+}
+
+Object* Class::AllocObjectFromCode(uint32_t type_idx, Method* method) {
+ Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+ if (klass == NULL) {
+ klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+ if (klass == NULL) {
+ UNIMPLEMENTED(FATAL) << "throw an error";
+ return NULL;
+ }
+ }
+ return klass->AllocObject();
+}
+
+Object* Class::AllocObject() {
+ DCHECK(!IsAbstract());
+ return Heap::AllocObject(this, this->object_size_);
+}
+
+void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
+ if (new_reference_offsets != CLASS_WALK_SUPER) {
+ // Sanity check that the number of bits set in the reference offset bitmap
+ // agrees with the number of references
+ Class* cur = this;
+ size_t cnt = 0;
+ while (cur) {
+ cnt += cur->NumReferenceInstanceFieldsDuringLinking();
+ cur = cur->GetSuperClass();
+ }
+ CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets), cnt);
+ }
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
+ new_reference_offsets, false);
+}
+
+void Class::SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
+ if (new_reference_offsets != CLASS_WALK_SUPER) {
+ // Sanity check that the number of bits set in the reference offset bitmap
+ // agrees with the number of references
+ CHECK_EQ((size_t)__builtin_popcount(new_reference_offsets),
+ NumReferenceStaticFieldsDuringLinking());
+ }
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, reference_static_offsets_),
+ new_reference_offsets, false);
+}
+
+size_t Class::PrimitiveSize() const {
+ switch (GetPrimitiveType()) {
+ case kPrimBoolean:
+ case kPrimByte:
+ case kPrimChar:
+ case kPrimShort:
+ case kPrimInt:
+ case kPrimFloat:
+ return sizeof(int32_t);
+ case kPrimLong:
+ case kPrimDouble:
+ return sizeof(int64_t);
+ default:
+ LOG(FATAL) << "Primitive type size calculation on invalid type " << this;
+ return 0;
+ }
+}
+
+size_t Class::GetTypeSize(const String* descriptor) {
+ switch (descriptor->CharAt(0)) {
+ case 'B': return 1; // byte
+ case 'C': return 2; // char
+ case 'D': return 8; // double
+ case 'F': return 4; // float
+ case 'I': return 4; // int
+ case 'J': return 8; // long
+ case 'S': return 2; // short
+ case 'Z': return 1; // boolean
+ case 'L': return sizeof(Object*);
+ case '[': return sizeof(Array*);
+ default:
+ LOG(ERROR) << "Unknown type " << descriptor;
+ return 0;
+ }
+}
+
+bool Class::Implements(const Class* klass) const {
+ DCHECK(klass != NULL);
+ DCHECK(klass->IsInterface());
+ // All interfaces implemented directly and by our superclass, and
+ // recursively all super-interfaces of those interfaces, are listed
+ // in iftable_, so we can just do a linear scan through that.
+ for (size_t i = 0; i < iftable_count_; i++) {
+ if (iftable_[i].GetInterface() == klass) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Class::CanPutArrayElementFromCode(const Class* elementClass, const Class* arrayClass) {
+ UNIMPLEMENTED(FATAL);
+ return false;
+}
+
+// Determine whether "this" is assignable from "klazz", where both of these
+// are array classes.
+//
+// Consider an array class, e.g. Y[][], where Y is a subclass of X.
+// Y[][] = Y[][] --> true (identity)
+// X[][] = Y[][] --> true (element superclass)
+// Y = Y[][] --> false
+// Y[] = Y[][] --> false
+// Object = Y[][] --> true (everything is an object)
+// Object[] = Y[][] --> true
+// Object[][] = Y[][] --> true
+// Object[][][] = Y[][] --> false (too many []s)
+// Serializable = Y[][] --> true (all arrays are Serializable)
+// Serializable[] = Y[][] --> true
+// Serializable[][] = Y[][] --> false (unless Y is Serializable)
+//
+// Don't forget about primitive types.
+// int[] instanceof Object[] --> false
+//
+bool Class::IsArrayAssignableFromArray(const Class* klass) const {
+ DCHECK(IsArrayClass());
+ DCHECK(klass->IsArrayClass());
+ DCHECK_GT(GetArrayRank(), 0);
+ DCHECK_GT(klass->GetArrayRank(), 0);
+ DCHECK(GetComponentType() != NULL);
+ DCHECK(klass->GetComponentType() != NULL);
+ if (GetArrayRank() > klass->GetArrayRank()) {
+ // Too many []s.
+ return false;
+ }
+ if (GetArrayRank() == klass->GetArrayRank()) {
+ return GetComponentType()->IsAssignableFrom(klass->GetComponentType());
+ }
+ DCHECK_LT(GetArrayRank(), klass->GetArrayRank());
+ // The thing we might be assignable from has more dimensions. We
+ // must be an Object or array of Object, or a standard array
+ // interface or array of standard array interfaces (the standard
+ // interfaces being java/lang/Cloneable and java/io/Serializable).
+ if (GetComponentType()->IsInterface()) {
+ // See if we implement our component type. We know the
+ // base element is an interface; if the array class implements
+ // it, we know it's a standard array interface.
+ return Implements(GetComponentType());
+ }
+ // See if this is an array of Object, Object[], etc.
+ return GetComponentType()->IsObjectClass();
+}
+
+bool Class::IsAssignableFromArray(const Class* klass) const {
+ DCHECK(!IsInterface()); // handled first in IsAssignableFrom
+ DCHECK(klass->IsArrayClass());
+ if (!IsArrayClass()) {
+ // If "this" is not also an array, it must be Object.
+ // klass's super should be java_lang_Object, since it is an array.
+ Class* java_lang_Object = klass->GetSuperClass();
+ DCHECK(java_lang_Object != NULL);
+ DCHECK(java_lang_Object->GetSuperClass() == NULL);
+ return this == java_lang_Object;
+ }
+ return IsArrayAssignableFromArray(klass);
+}
+
+bool Class::IsSubClass(const Class* klass) const {
+ DCHECK(!IsInterface());
+ DCHECK(!klass->IsArrayClass());
+ const Class* current = this;
+ do {
+ if (current == klass) {
+ return true;
+ }
+ current = current->GetSuperClass();
+ } while (current != NULL);
+ return false;
+}
+
+bool Class::IsInSamePackage(const String* descriptor_string_1,
+ const String* descriptor_string_2) {
+ const std::string descriptor1(descriptor_string_1->ToModifiedUtf8());
+ const std::string descriptor2(descriptor_string_2->ToModifiedUtf8());
+
+ size_t i = 0;
+ while (descriptor1[i] != '\0' && descriptor1[i] == descriptor2[i]) {
+ ++i;
+ }
+ if (descriptor1.find('/', i) != StringPiece::npos ||
+ descriptor2.find('/', i) != StringPiece::npos) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+#if 0
+bool Class::IsInSamePackage(const StringPiece& descriptor1,
+ const StringPiece& descriptor2) {
+ size_t size = std::min(descriptor1.size(), descriptor2.size());
+ std::pair<StringPiece::const_iterator, StringPiece::const_iterator> pos;
+ pos = std::mismatch(descriptor1.begin(), descriptor1.begin() + size,
+ descriptor2.begin());
+ return !(*(pos.second).rfind('/') != npos && descriptor2.rfind('/') != npos);
+}
+#endif
+
+bool Class::IsInSamePackage(const Class* that) const {
+ const Class* klass1 = this;
+ const Class* klass2 = that;
+ if (klass1 == klass2) {
+ return true;
+ }
+ // Class loaders must match.
+ if (klass1->GetClassLoader() != klass2->GetClassLoader()) {
+ return false;
+ }
+ // Arrays are in the same package when their element classes are.
+ if (klass1->IsArrayClass()) {
+ klass1 = klass1->GetComponentType();
+ }
+ if (klass2->IsArrayClass()) {
+ klass2 = klass2->GetComponentType();
+ }
+ // Compare the package part of the descriptor string.
+ return IsInSamePackage(klass1->descriptor_, klass2->descriptor_);
+}
+
+const ClassLoader* Class::GetClassLoader() const {
+ return GetFieldObject<const ClassLoader*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, class_loader_), false);
+}
+
+void Class::SetClassLoader(const ClassLoader* new_cl) {
+ ClassLoader* new_class_loader = const_cast<ClassLoader*>(new_cl);
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, class_loader_),
+ new_class_loader, false);
+}
+
Method* Class::FindVirtualMethodForInterface(Method* method) {
Class* declaring_class = method->GetDeclaringClass();
DCHECK(declaring_class->IsInterface());
@@ -540,7 +756,8 @@ Method* Class::FindVirtualMethodForInterface(Method* method) {
for (size_t i = 0; i < iftable_count_; i++) {
InterfaceEntry& interface_entry = iftable_[i];
if (interface_entry.GetInterface() == declaring_class) {
- return vtable_->Get(interface_entry.method_index_array_[method->method_index_]);
+ return GetVTable()->Get(
+ interface_entry.GetMethodIndexArray()[method->GetMethodIndex()]);
}
}
UNIMPLEMENTED(FATAL) << "Need to throw an error of some kind";
@@ -593,23 +810,23 @@ Method* Class::FindVirtualMethod(const StringPiece& name,
return NULL;
}
-Field* Class::FindDeclaredInstanceField(const StringPiece& name, const StringPiece& descriptor) {
+Field* Class::FindDeclaredInstanceField(const StringPiece& name, Class* type) {
// Is the field in this class?
// Interfaces are not relevant because they can't contain instance fields.
for (size_t i = 0; i < NumInstanceFields(); ++i) {
Field* f = GetInstanceField(i);
- if (f->GetName()->Equals(name) && f->GetDescriptor() == descriptor) {
+ if (f->GetName()->Equals(name) && type == f->GetType()) {
return f;
}
}
return NULL;
}
-Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& descriptor) {
+Field* Class::FindInstanceField(const StringPiece& name, Class* type) {
// Is the field in this class, or any of its superclasses?
// Interfaces are not relevant because they can't contain instance fields.
for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
- Field* f = c->FindDeclaredInstanceField(name, descriptor);
+ Field* f = c->FindDeclaredInstanceField(name, type);
if (f != NULL) {
return f;
}
@@ -617,22 +834,23 @@ Field* Class::FindInstanceField(const StringPiece& name, const StringPiece& desc
return NULL;
}
-Field* Class::FindDeclaredStaticField(const StringPiece& name, const StringPiece& descriptor) {
+Field* Class::FindDeclaredStaticField(const StringPiece& name, Class* type) {
+ DCHECK(type != NULL);
for (size_t i = 0; i < NumStaticFields(); ++i) {
Field* f = GetStaticField(i);
- if (f->GetName()->Equals(name) && f->GetDescriptor() == descriptor) {
+ if (f->GetName()->Equals(name) && f->GetType() == type) {
return f;
}
}
return NULL;
}
-Field* Class::FindStaticField(const StringPiece& name, const StringPiece& descriptor) {
+Field* Class::FindStaticField(const StringPiece& name, Class* type) {
// Is the field in this class (or its interfaces), or any of its
// superclasses (or their interfaces)?
for (Class* c = this; c != NULL; c = c->GetSuperClass()) {
// Is the field in this class?
- Field* f = c->FindDeclaredStaticField(name, descriptor);
+ Field* f = c->FindDeclaredStaticField(name, type);
if (f != NULL) {
return f;
}
@@ -640,7 +858,7 @@ Field* Class::FindStaticField(const StringPiece& name, const StringPiece& descri
// Is this field in any of this class' interfaces?
for (size_t i = 0; i < c->NumInterfaces(); ++i) {
Class* interface = c->GetInterface(i);
- f = interface->FindDeclaredStaticField(name, descriptor);
+ f = interface->FindDeclaredStaticField(name, type);
if (f != NULL) {
return f;
}
@@ -649,6 +867,35 @@ Field* Class::FindStaticField(const StringPiece& name, const StringPiece& descri
return NULL;
}
+Array* Array::Alloc(Class* array_class, int32_t component_count, size_t component_size) {
+ DCHECK_GE(component_count, 0);
+ DCHECK(array_class->IsArrayClass());
+ size_t size = SizeOf(component_count, component_size);
+ Array* array = down_cast<Array*>(Heap::AllocObject(array_class, size));
+ if (array != NULL) {
+ DCHECK(array->IsArrayInstance());
+ array->SetLength(component_count);
+ }
+ return array;
+}
+
+Array* Array::Alloc(Class* array_class, int32_t component_count) {
+ return Alloc(array_class, component_count, array_class->GetComponentSize());
+}
+
+Array* Array::AllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) {
+ // TODO: throw on negative component_count
+ Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
+ if (klass == NULL) {
+ klass = Runtime::Current()->GetClassLinker()->ResolveType(type_idx, method);
+ if (klass == NULL || !klass->IsArrayClass()) {
+ UNIMPLEMENTED(FATAL) << "throw an error";
+ return NULL;
+ }
+ }
+ return Array::Alloc(klass, component_count);
+}
+
template<typename T>
PrimitiveArray<T>* PrimitiveArray<T>::Alloc(size_t length) {
DCHECK(array_class_ != NULL);
@@ -676,6 +923,7 @@ void String::SetClass(Class* java_lang_String) {
CHECK(java_lang_String != NULL);
java_lang_String_ = java_lang_String;
}
+
void String::ResetClass() {
CHECK(java_lang_String_ != NULL);
java_lang_String_ = NULL;
@@ -685,6 +933,135 @@ const String* String::Intern() const {
return Runtime::Current()->GetInternTable()->InternWeak(this);
}
+int32_t String::GetHashCode() const {
+ int32_t result = GetField32(
+ OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
+ DCHECK(result != 0 ||
+ ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0);
+ return result;
+}
+
+int32_t String::GetLength() const {
+ int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), false);
+ DCHECK(result >= 0 && result <= GetCharArray()->GetLength());
+ return result;
+}
+
+uint16_t String::CharAt(int32_t index) const {
+ // TODO: do we need this? Equals is the only caller, and could
+ // bounds check itself.
+ if (index < 0 || index >= count_) {
+ Thread* self = Thread::Current();
+ self->ThrowNewException("Ljava/lang/StringIndexOutOfBoundsException;",
+ "length=%i; index=%i", count_, index);
+ return 0;
+ }
+ return GetCharArray()->Get(index + GetOffset());
+}
+
+String* String::AllocFromUtf16(int32_t utf16_length,
+ const uint16_t* utf16_data_in,
+ int32_t hash_code) {
+ String* string = Alloc(GetJavaLangString(), utf16_length);
+ // TODO: use 16-bit wide memset variant
+ CharArray* array = const_cast<CharArray*>(string->GetCharArray());
+ for (int i = 0; i < utf16_length; i++) {
+ array->Set(i, utf16_data_in[i]);
+ }
+ if (hash_code != 0) {
+ string->SetHashCode(hash_code);
+ } else {
+ string->ComputeHashCode();
+ }
+ return string;
+}
+
+String* String::AllocFromModifiedUtf8(const char* utf) {
+ size_t char_count = CountModifiedUtf8Chars(utf);
+ return AllocFromModifiedUtf8(char_count, utf);
+}
+
+String* String::AllocFromModifiedUtf8(int32_t utf16_length,
+ const char* utf8_data_in) {
+ String* string = Alloc(GetJavaLangString(), utf16_length);
+ uint16_t* utf16_data_out =
+ const_cast<uint16_t*>(string->GetCharArray()->GetData());
+ ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in);
+ string->ComputeHashCode();
+ return string;
+}
+
+String* String::Alloc(Class* java_lang_String, int32_t utf16_length) {
+ return Alloc(java_lang_String, CharArray::Alloc(utf16_length));
+}
+
+String* String::Alloc(Class* java_lang_String, CharArray* array) {
+ String* string = down_cast<String*>(java_lang_String->AllocObject());
+ string->SetArray(array);
+ string->SetCount(array->GetLength());
+ return string;
+}
+
+bool String::Equals(const String* that) const {
+ if (this == that) {
+ // Quick reference equality test
+ return true;
+ } else if (that == NULL) {
+ // Null isn't an instanceof anything
+ return false;
+ } else if (this->GetLength() != that->GetLength()) {
+ // Quick length inequality test
+ return false;
+ } else {
+ // NB don't short circuit on hash code as we're presumably here as the
+ // hash code was already equal
+ for (int32_t i = 0; i < that->GetLength(); ++i) {
+ if (this->CharAt(i) != that->CharAt(i)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+bool String::Equals(const uint16_t* that_chars, int32_t that_offset,
+ int32_t that_length) const {
+ if (this->GetLength() != that_length) {
+ return false;
+ } else {
+ for (int32_t i = 0; i < that_length; ++i) {
+ if (this->CharAt(i) != that_chars[that_offset + i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+bool String::Equals(const char* modified_utf8) const {
+ for (int32_t i = 0; i < GetLength(); ++i) {
+ uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
+ if (ch == '\0' || ch != CharAt(i)) {
+ return false;
+ }
+ }
+ return *modified_utf8 == '\0';
+}
+
+bool String::Equals(const StringPiece& modified_utf8) const {
+ // TODO: do not assume C-string representation.
+ return Equals(modified_utf8.data());
+}
+
+// Create a modified UTF-8 encoded std::string from a java/lang/String object.
+std::string String::ToModifiedUtf8() const {
+ const uint16_t* chars = GetCharArray()->GetData() + GetOffset();
+ size_t byte_count(CountUtf8Bytes(chars, GetLength()));
+ std::string result(byte_count, char(0));
+ ConvertUtf16ToModifiedUtf8(&result[0], chars, GetLength());
+ return result;
+}
+
Class* StackTraceElement::java_lang_StackTraceElement_ = NULL;
void StackTraceElement::SetClass(Class* java_lang_StackTraceElement) {
@@ -698,6 +1075,23 @@ void StackTraceElement::ResetClass() {
java_lang_StackTraceElement_ = NULL;
}
+StackTraceElement* StackTraceElement::Alloc(const String* declaring_class,
+ const String* method_name,
+ const String* file_name,
+ int32_t line_number) {
+ StackTraceElement* trace =
+ down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject());
+ trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_),
+ const_cast<String*>(declaring_class), false);
+ trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_),
+ const_cast<String*>(method_name), false);
+ trace->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_),
+ const_cast<String*>(file_name), false);
+ trace->SetField32(OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_),
+ line_number, false);
+ return trace;
+}
+
static const char* kClassStatusNames[] = {
"Error",
"NotReady",
diff --git a/src/object.h b/src/object.h
index bc6e7e515b..5a47c46d73 100644
--- a/src/object.h
+++ b/src/object.h
@@ -9,11 +9,13 @@
#include "casts.h"
#include "constants.h"
#include "globals.h"
+#include "heap.h"
#include "logging.h"
#include "macros.h"
#include "monitor.h"
#include "monitor.h"
#include "offsets.h"
+#include "runtime.h"
#include "stringpiece.h"
#include "thread.h"
#include "utf.h"
@@ -163,9 +165,13 @@ static const uint32_t kAccReferenceFlagsMask = (kAccClassIsReference
* Return an offset, given a bit number as returned from CLZ.
*/
#define CLASS_OFFSET_FROM_CLZ(rshift) \
- ((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT) + CLASS_SMALLEST_OFFSET)
+ MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT) + \
+ CLASS_SMALLEST_OFFSET)
+#define OFFSET_OF_OBJECT_MEMBER(type, field) \
+ MemberOffset(OFFSETOF_MEMBER(type, field))
+// C++ mirror of java.lang.Object
class Object {
public:
static bool InstanceOf(const Object* object, const Class* klass) {
@@ -175,11 +181,17 @@ class Object {
return object->InstanceOf(klass);
}
+ static MemberOffset ClassOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
+ }
+
Class* GetClass() const {
- DCHECK(klass_ != NULL);
- return klass_;
+ return
+ GetFieldObject<Class*>(OFFSET_OF_OBJECT_MEMBER(Object, klass_), false);
}
+ void SetClass(Class* new_klass);
+
bool InstanceOf(const Class* klass) const;
size_t SizeOf() const;
@@ -189,63 +201,46 @@ class Object {
return NULL;
}
+ static MemberOffset MonitorOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Object, monitor_);
+ }
+
+ Monitor* GetMonitor() const {
+ return GetFieldPtr<Monitor*>(
+ OFFSET_OF_OBJECT_MEMBER(Object, monitor_), false);
+ }
+
+ void SetMonitor(Monitor* monitor) {
+ // TODO: threading - compare-and-set
+ SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Object, monitor_), monitor, false);
+ }
+
void MonitorEnter() {
- monitor_->Enter();
+ GetMonitor()->Enter();
}
void MonitorExit() {
- monitor_->Exit();
+ GetMonitor()->Exit();
}
void Notify() {
- monitor_->Notify();
+ GetMonitor()->Notify();
}
void NotifyAll() {
- monitor_->NotifyAll();
+ GetMonitor()->NotifyAll();
}
void Wait() {
- monitor_->Wait();
+ GetMonitor()->Wait();
}
void Wait(int64_t timeout) {
- monitor_->Wait(timeout);
+ GetMonitor()->Wait(timeout);
}
void Wait(int64_t timeout, int32_t nanos) {
- monitor_->Wait(timeout, nanos);
- }
-
- Object* GetFieldObject(size_t field_offset) const {
- const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset;
- return *reinterpret_cast<Object* const *>(raw_addr);
- }
-
- void SetFieldObject(size_t offset, const Object* new_value) {
- byte* raw_addr = reinterpret_cast<byte*>(this) + offset;
- *reinterpret_cast<const Object**>(raw_addr) = new_value;
- // TODO: write barrier
- }
-
- uint32_t GetField32(size_t field_offset) const {
- const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset;
- return *reinterpret_cast<const uint32_t*>(raw_addr);
- }
-
- void SetField32(size_t offset, uint32_t new_value) {
- byte* raw_addr = reinterpret_cast<byte*>(this) + offset;
- *reinterpret_cast<uint32_t*>(raw_addr) = new_value;
- }
-
- uint64_t GetField64(size_t field_offset) const {
- const byte* raw_addr = reinterpret_cast<const byte*>(this) + field_offset;
- return *reinterpret_cast<const uint64_t*>(raw_addr);
- }
-
- void SetField64(size_t offset, uint64_t new_value) {
- byte* raw_addr = reinterpret_cast<byte*>(this) + offset;
- *reinterpret_cast<uint64_t*>(raw_addr) = new_value;
+ GetMonitor()->Wait(timeout, nanos);
}
bool IsClass() const;
@@ -319,12 +314,133 @@ class Object {
return down_cast<const Field*>(this);
}
- public:
+ 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 {
+ Heap::VerifyObject(this);
+ DCHECK(Thread::Current() == NULL ||
+ Thread::Current()->CanAccessDirectReferences());
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) +
+ field_offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ T result = *reinterpret_cast<T const *>(raw_addr);
+ Heap::VerifyObject(result);
+ return result;
+ }
+
+ void SetFieldObject(MemberOffset offset, const Object* new_value,
+ bool is_volatile) {
+ // Avoid verifying this when initializing the Class*
+ if (offset.Int32Value() != ClassOffset().Int32Value()) {
+ Heap::VerifyObject(this);
+ }
+ Heap::VerifyObject(new_value);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ *reinterpret_cast<const Object**>(raw_addr) = new_value;
+ // TODO: write barrier
+ }
+
+ uint32_t GetField32(MemberOffset field_offset, bool is_volatile) const {
+ Heap::VerifyObject(this);
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) +
+ field_offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ return *reinterpret_cast<const uint32_t*>(raw_addr);
+ }
+
+ void SetField32(MemberOffset offset, uint32_t new_value, bool is_volatile) {
+ Heap::VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ *reinterpret_cast<uint32_t*>(raw_addr) = new_value;
+ }
+
+ uint64_t GetField64(MemberOffset field_offset, bool is_volatile) const {
+ Heap::VerifyObject(this);
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) +
+ field_offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ return *reinterpret_cast<const uint64_t*>(raw_addr);
+ }
+
+ void SetField64(MemberOffset offset, uint64_t new_value,
+ bool is_volatile = false) {
+ Heap::VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ *reinterpret_cast<uint64_t*>(raw_addr) = new_value;
+ }
+
+ protected:
+ // Accessors for non-Java type fields
+ uint16_t GetField16(MemberOffset field_offset, bool is_volatile) const {
+ Heap::VerifyObject(this);
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) +
+ field_offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ return *reinterpret_cast<const uint16_t*>(raw_addr);
+ }
+
+ void SetField16(MemberOffset offset, uint16_t new_value, bool is_volatile) {
+ Heap::VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ *reinterpret_cast<uint16_t*>(raw_addr) = new_value;
+ }
+
+ template<class T>
+ T GetFieldPtr(MemberOffset field_offset, bool is_volatile) const {
+ Heap::VerifyObject(this);
+ const byte* raw_addr = reinterpret_cast<const byte*>(this) +
+ field_offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ return *reinterpret_cast<T const *>(raw_addr);
+ }
+
+ template<typename T>
+ void SetFieldPtr(MemberOffset offset, T new_value, bool is_volatile) {
+ Heap::VerifyObject(this);
+ byte* raw_addr = reinterpret_cast<byte*>(this) + offset.Int32Value();
+ if (is_volatile) {
+ UNIMPLEMENTED(WARNING);
+ }
+ *reinterpret_cast<T*>(raw_addr) = new_value;
+ }
+
+ private:
Class* klass_;
Monitor* monitor_;
- private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Object);
};
@@ -356,44 +472,53 @@ class ObjectLock {
DISALLOW_COPY_AND_ASSIGN(ObjectLock);
};
+// C++ mirror of java.lang.reflect.AccessibleObject
class AccessibleObject : public Object {
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- uint32_t java_flag_;
+ uint32_t java_flag_; // can accessibility checks be bypassed
};
+// C++ mirror of java.lang.reflect.Field
class Field : public AccessibleObject {
public:
- Class* GetDeclaringClass() const {
- DCHECK(declaring_class_ != NULL);
- return declaring_class_;
- }
+ Class* GetDeclaringClass() const;
- const String* GetName() const {
- DCHECK(name_ != NULL);
- return name_;
+ void SetDeclaringClass(Class *new_declaring_class);
+
+ const String* GetName() const;
+
+ void SetName(String* new_name);
+
+ uint32_t GetAccessFlags() const;
+
+ void SetAccessFlags(uint32_t new_access_flags) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), new_access_flags,
+ false);
}
bool IsStatic() const {
- return (access_flags_ & kAccStatic) != 0;
+ return (GetAccessFlags() & kAccStatic) != 0;
}
- char GetType() const { // TODO: return type
- return GetDescriptor()[0];
- }
+ uint32_t GetTypeIdx() const;
- const StringPiece& GetDescriptor() const {
- DCHECK_NE(0, descriptor_.size());
- return descriptor_;
- }
+ void SetTypeIdx(uint32_t type_idx);
- uint32_t GetOffset() const {
- return offset_;
- }
+ // Gets type using type index and resolved types in the dex cache, may be null
+ // if type isn't yet resolved
+ Class* GetTypeDuringLinking() const;
- void SetOffset(size_t num_bytes) {
- offset_ = num_bytes;
- }
+ // Performs full resolution, may return null and set exceptions if type cannot
+ // be resolved
+ Class* GetType() const;
+
+ // Offset to field within an Object
+ MemberOffset GetOffset() const;
+
+ MemberOffset GetOffsetDuringLinking() const;
+
+ void SetOffset(MemberOffset num_bytes);
// field access, null object for static fields
bool GetBoolean(const Object* object) const;
@@ -415,15 +540,33 @@ class Field : public AccessibleObject {
Object* GetObject(const Object* object) const;
void SetObject(Object* object, const Object* l) const;
- // slow path routines for static field access when field was unresolved at compile time
- static uint32_t Get32StaticFromCode(uint32_t field_idx, const Method* referrer);
- static void Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint32_t new_value);
- static uint64_t Get64StaticFromCode(uint32_t field_idx, const Method* referrer);
- static void Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint64_t new_value);
- static Object* GetObjStaticFromCode(uint32_t field_idx, const Method* referrer);
- static void SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Object* new_value);
+ // Slow path routines for static field access when field was unresolved at
+ // compile time
+ static uint32_t Get32StaticFromCode(uint32_t field_idx,
+ const Method* referrer);
+ static void Set32StaticFromCode(uint32_t field_idx, const Method* referrer,
+ uint32_t new_value);
+ static uint64_t Get64StaticFromCode(uint32_t field_idx,
+ const Method* referrer);
+ static void Set64StaticFromCode(uint32_t field_idx, const Method* referrer,
+ uint64_t new_value);
+ static Object* GetObjStaticFromCode(uint32_t field_idx,
+ const Method* referrer);
+ static void SetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
+ Object* new_value);
+
+ 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();
- public: // TODO: private
+ private:
+ bool IsVolatile() const {
+ return (GetAccessFlags() & kAccVolatile) != 0;
+ }
// private implementation of field access using raw data
uint32_t Get32(const Object* object) const;
@@ -439,18 +582,23 @@ class Field : public AccessibleObject {
Object* generic_type_;
uint32_t generic_types_are_initialized_;
const String* name_;
+ // Offset of field within an instance or in the Class' static fields
uint32_t offset_;
+ // Type of the field
+ // TODO: unused by ART (which uses the type_idx below), remove
Class* type_;
- // e.g. "I", "[C", "Landroid/os/Debug;"
- StringPiece descriptor_;
-
+ // TODO: expose these fields in the Java version of this Object
uint32_t access_flags_;
+ // Dex cache index of resolved type
+ uint32_t type_idx_;
+
+ static Class* java_lang_reflect_Field_;
- private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Field);
};
+// C++ mirror of java.lang.reflect.Method
class Method : public AccessibleObject {
public:
// An function that invokes a method with an array of its arguments.
@@ -460,39 +608,54 @@ class Method : public AccessibleObject {
byte* args,
JValue* result);
- // Returns the method name, e.g. "<init>" or "eatLunch"
- const String* GetName() const {
- DCHECK(name_ != NULL);
- return name_;
- }
+ Class* GetDeclaringClass() const;
- const String* GetSignature() const {
- DCHECK(signature_ != NULL);
- return signature_;
+ void SetDeclaringClass(Class *new_declaring_class);
+
+ static MemberOffset DeclaringClassOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Method, declaring_class_));
}
- Class* GetDeclaringClass() const {
- DCHECK(declaring_class_ != NULL);
- return declaring_class_;
+ // Returns the method name, e.g. "<init>" or "eatLunch"
+ const String* GetName() const;
+
+ void SetName(String* new_name);
+
+ const char* GetShorty() const;
+
+ void SetShorty(const char* new_shorty) {
+ DCHECK(NULL == GetFieldPtr<const char*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false));
+ DCHECK_LE(1u, strlen(new_shorty));
+ SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Method, shorty_), new_shorty, false);
}
- static MemberOffset DeclaringClassOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Method, declaring_class_));
+ const String* GetSignature() const;
+
+ void SetSignature(String* new_signature);
+
+ bool HasSameNameAndDescriptor(const Method* that) const;
+
+ uint32_t GetAccessFlags() const;
+
+ void SetAccessFlags(uint32_t new_access_flags) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, access_flags_), new_access_flags,
+ false);
}
// Returns true if the method is declared public.
bool IsPublic() const {
- return (access_flags_ & kAccPublic) != 0;
+ return (GetAccessFlags() & kAccPublic) != 0;
}
// Returns true if the method is declared private.
bool IsPrivate() const {
- return (access_flags_ & kAccPrivate) != 0;
+ return (GetAccessFlags() & kAccPrivate) != 0;
}
// Returns true if the method is declared static.
bool IsStatic() const {
- return (access_flags_ & kAccStatic) != 0;
+ return (GetAccessFlags() & kAccStatic) != 0;
}
// Returns true if the method is a constructor.
@@ -508,90 +671,126 @@ class Method : public AccessibleObject {
// Returns true if the method is declared synchronized.
bool IsSynchronized() const {
uint32_t synchonized = kAccSynchronized | kAccDeclaredSynchronized;
- return (access_flags_ & synchonized) != 0;
+ return (GetAccessFlags() & synchonized) != 0;
}
// Returns true if the method is declared final.
bool IsFinal() const {
- return (access_flags_ & kAccFinal) != 0;
+ return (GetAccessFlags() & kAccFinal) != 0;
}
// Returns true if the method is declared native.
bool IsNative() const {
- return (access_flags_ & kAccNative) != 0;
+ return (GetAccessFlags() & kAccNative) != 0;
}
// Returns true if the method is declared abstract.
bool IsAbstract() const {
- return (access_flags_ & kAccAbstract) != 0;
+ return (GetAccessFlags() & kAccAbstract) != 0;
}
bool IsSynthetic() const {
- return (access_flags_ & kAccSynthetic) != 0;
+ return (GetAccessFlags() & kAccSynthetic) != 0;
}
- // Number of argument registers required by the prototype.
- uint32_t NumArgRegisters() const;
+ uint16_t GetMethodIndex() const;
- // Number of argument bytes required for densely packing the
- // arguments into an array of arguments.
- size_t NumArgArrayBytes() const;
+ size_t GetVtableIndex() const {
+ return GetMethodIndex();
+ }
- // Converts a native PC to a virtual PC. TODO: this is a no-op
- // until we associate a PC mapping table with each method.
- uintptr_t ToDexPC(const uintptr_t pc) const {
- return pc;
+ void SetMethodIndex(uint16_t new_method_index) {
+ SetField16(OFFSET_OF_OBJECT_MEMBER(Method, method_index_),
+ new_method_index, false);
}
- // Converts a virtual PC to a native PC. TODO: this is a no-op
- // until we associate a PC mapping table with each method.
- uintptr_t ToNativePC(const uintptr_t pc) const {
- return pc;
+ static MemberOffset MethodIndexOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Method, method_index_);
}
- public: // TODO: private
- // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
- // the class we are a part of
- Class* declaring_class_;
- ObjectArray<Class>* java_exception_types_;
- Object* java_formal_type_parameters_;
- Object* java_generic_exception_types_;
- Object* java_generic_parameter_types_;
- Object* java_generic_return_type_;
- Class* java_return_type_;
- const String* name_;
- ObjectArray<Class>* java_parameter_types_;
- uint32_t java_generic_types_are_initialized_;
- uint32_t java_slot_;
+ uint32_t GetCodeItemOffset() const {
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, code_item_offset_), false);
+ }
- const StringPiece& GetShorty() const {
- return shorty_;
+ void SetCodeItemOffset(uint32_t new_code_off) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, code_item_offset_),
+ new_code_off, false);
}
- bool IsReturnAReference() const {
- return (shorty_[0] == 'L') || (shorty_[0] == '[');
+ // Number of 32bit registers that would be required to hold all the arguments
+ static size_t NumArgRegisters(const StringPiece& shorty);
+
+ // Number of argument bytes required for densely packing the
+ // arguments into an array of arguments.
+ size_t NumArgArrayBytes() const;
+
+ uint16_t NumRegisters() const;
+
+ void SetNumRegisters(uint16_t new_num_registers) {
+ SetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_),
+ new_num_registers, false);
}
- bool IsReturnAFloatOrDouble() const {
- return (shorty_[0] == 'F') || (shorty_[0] == 'D');
+ uint16_t NumIns() const;
+
+ void SetNumIns(uint16_t new_num_ins) {
+ SetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_),
+ new_num_ins, false);
}
- bool IsReturnAFloat() const {
- return shorty_[0] == 'F';
+ uint16_t NumOuts() const;
+
+ void SetNumOuts(uint16_t new_num_outs) {
+ SetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_),
+ new_num_outs, false);
}
- bool IsReturnADouble() const {
- return shorty_[0] == 'D';
+ uint32_t GetProtoIdx() const;
+
+ void SetProtoIdx(uint32_t new_proto_idx) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, proto_idx_), new_proto_idx, false);
}
- bool IsReturnALong() const {
- return shorty_[0] == 'J';
+ ObjectArray<String>* GetDexCacheStrings() const;
+ void SetDexCacheStrings(ObjectArray<String>* new_dex_cache_strings);
+
+ static MemberOffset DexCacheStringsOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Method, dex_cache_strings_);
}
- bool IsReturnVoid() const {
- return shorty_[0] == 'V';
+ ObjectArray<Class>* GetDexCacheResolvedTypes() const;
+ void SetDexCacheResolvedTypes(ObjectArray<Class>* new_dex_cache_types);
+
+ ObjectArray<Method>* GetDexCacheResolvedMethods() const;
+ void SetDexCacheResolvedMethods(ObjectArray<Method>* new_dex_cache_methods);
+
+ ObjectArray<Field>* GetDexCacheResolvedFields() const;
+ void SetDexCacheResolvedFields(ObjectArray<Field>* new_dex_cache_fields);
+
+ CodeAndDirectMethods* GetDexCacheCodeAndDirectMethods() const;
+ void SetDexCacheCodeAndDirectMethods(CodeAndDirectMethods* new_value);
+
+ ObjectArray<StaticStorageBase>* GetDexCacheInitializedStaticStorage() const;
+ void SetDexCacheInitializedStaticStorage(ObjectArray<StaticStorageBase>* new_value);
+
+ void SetReturnTypeIdx(uint32_t new_return_type_idx);
+
+ Class* GetReturnType() const;
+
+ bool IsReturnAReference() const;
+
+ bool IsReturnAFloat() const;
+
+ bool IsReturnADouble() const;
+
+ bool IsReturnAFloatOrDouble() const {
+ return IsReturnAFloat() || IsReturnADouble();
}
+ bool IsReturnALong() const;
+
+ bool IsReturnVoid() const;
+
// "Args" may refer to any of the 3 levels of "Args."
// To avoid confusion, our code will denote which "Args" clearly:
// 1. UserArgs: Args that a user see.
@@ -607,7 +806,7 @@ class Method : public AccessibleObject {
size_t NumArgs() const {
// "1 +" because the first in Args is the receiver.
// "- 1" because we don't count the return type.
- return (IsStatic() ? 0 : 1) + shorty_.length() - 1;
+ return (IsStatic() ? 0 : 1) + strlen(GetShorty()) - 1;
}
// The number of reference arguments to this method including implicit this
@@ -633,90 +832,137 @@ class Method : public AccessibleObject {
// Size in bytes of the return value
size_t ReturnSize() const;
- bool HasCode() {
- return code_ != NULL;
+ const void* GetCode() const {
+ return GetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, code_), false);
}
- const void* GetCode() {
- return code_;
+ bool HasCode() const {
+ return GetCode() != NULL;
}
void SetCode(const byte* compiled_code,
size_t byte_count,
- InstructionSet set) {
- // Copy the code into an executable region.
- code_instruction_set_ = set;
- code_area_.reset(MemMap::Map(byte_count,
- PROT_READ | PROT_WRITE | PROT_EXEC));
- CHECK(code_area_.get());
- byte* code = code_area_->GetAddress();
- memcpy(code, compiled_code, byte_count);
- __builtin___clear_cache(code, code + byte_count);
-
- uintptr_t address = reinterpret_cast<uintptr_t>(code);
- if (code_instruction_set_ == kThumb2) {
- // Set the low-order bit so a BLX will switch to Thumb mode
- address |= 0x1;
- }
- code_ = reinterpret_cast<void*>(address);
- }
+ InstructionSet set);
- void SetFrameSizeInBytes(size_t frame_size_in_bytes) {
- frame_size_in_bytes_ = frame_size_in_bytes;
- }
-
- void SetReturnPcOffsetInBytes(size_t return_pc_offset_in_bytes) {
- return_pc_offset_in_bytes_ = return_pc_offset_in_bytes;
+ static MemberOffset GetCodeOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Method, code_);
}
size_t GetFrameSizeInBytes() const {
- return frame_size_in_bytes_;
- }
-
- size_t GetReturnPcOffsetInBytes() const {
- return return_pc_offset_in_bytes_;
+ DCHECK(sizeof(size_t) == sizeof(uint32_t));
+ size_t result = GetField32(
+ OFFSET_OF_OBJECT_MEMBER(Method, frame_size_in_bytes_), false);
+ DCHECK_LE(static_cast<size_t>(kStackAlignment), result);
+ return result;
}
- void SetCoreSpillMask(uint32_t core_spill_mask) {
- core_spill_mask_ = core_spill_mask;
+ void SetFrameSizeInBytes(size_t new_frame_size_in_bytes) {
+ DCHECK(sizeof(size_t) == sizeof(uint32_t));
+ DCHECK_LE(static_cast<size_t>(kStackAlignment), new_frame_size_in_bytes);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, frame_size_in_bytes_),
+ new_frame_size_in_bytes, false);
}
- static size_t GetCodeOffset() {
- return OFFSETOF_MEMBER(Method, code_);
+ size_t GetReturnPcOffsetInBytes() const {
+ DCHECK(sizeof(size_t) == sizeof(uint32_t));
+ return GetField32(
+ OFFSET_OF_OBJECT_MEMBER(Method, return_pc_offset_in_bytes_), false);
}
- void SetFpSpillMask(uint32_t fp_spill_mask) {
- fp_spill_mask_ = fp_spill_mask;
+ void SetReturnPcOffsetInBytes(size_t return_pc_offset_in_bytes) {
+ DCHECK(sizeof(size_t) == sizeof(uint32_t));
+ DCHECK_LT(return_pc_offset_in_bytes, GetFrameSizeInBytes());
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, return_pc_offset_in_bytes_),
+ return_pc_offset_in_bytes, false);
}
void RegisterNative(const void* native_method) {
CHECK(native_method != NULL);
- native_method_ = native_method;
+ SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
+ native_method, false);
}
void UnregisterNative() {
- native_method_ = NULL;
+ SetFieldPtr<const void*>(OFFSET_OF_OBJECT_MEMBER(Method, native_method_),
+ NULL, false);
}
static MemberOffset NativeMethodOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Method, native_method_));
+ return OFFSET_OF_OBJECT_MEMBER(Method, native_method_);
}
+ // Native to managed invocation stub entry point
InvokeStub* GetInvokeStub() const {
- return invoke_stub_;
+ InvokeStub* result = GetFieldPtr<InvokeStub*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), false);
+ // TODO: DCHECK(result != NULL); should be ahead of time compiled
+ return result;
}
- void SetInvokeStub(const InvokeStub* invoke_stub) {
- invoke_stub_ = invoke_stub;
+ static MemberOffset GetInvokeStubOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_);
}
- static size_t GetInvokeStubOffset() {
- return OFFSETOF_MEMBER(Method, invoke_stub_);
+ void SetInvokeStub(const InvokeStub* new_invoke_stub) {
+ SetFieldPtr<const InvokeStub*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, invoke_stub_), new_invoke_stub, false);
}
- bool HasSameNameAndDescriptor(const Method* that) const;
+ void SetFpSpillMask(uint32_t fp_spill_mask) {
+ // Computed during compilation
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, fp_spill_mask_),
+ fp_spill_mask, false);
+ }
+
+ void SetCoreSpillMask(uint32_t core_spill_mask) {
+ // Computed during compilation
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Method, core_spill_mask_),
+ core_spill_mask, false);
+ }
+
+ // Converts a native PC to a dex PC. TODO: this is a no-op
+ // until we associate a PC mapping table with each method.
+ uintptr_t ToDexPC(const uintptr_t pc) const {
+ return pc;
+ }
+
+ // Converts a dex PC to a native PC. TODO: this is a no-op
+ // until we associate a PC mapping table with each method.
+ uintptr_t ToNativePC(const uintptr_t pc) const {
+ return pc;
+ }
+
+ static Class* GetJavaLangReflectMethod() {
+ DCHECK(java_lang_reflect_Method_ != NULL);
+ return java_lang_reflect_Method_;
+ }
+
+ static void SetClass(Class* java_lang_reflect_Method);
+ static void ResetClass();
+
+ private:
+ uint32_t GetReturnTypeIdx() const;
+
+ // TODO: the image writer should know the offsets of these fields as they
+ // should appear in the libcore Java mirror
+ friend class ImageWriter;
+
+ // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
+ // the class we are a part of
+ Class* declaring_class_;
+ ObjectArray<Class>* java_exception_types_;
+ Object* java_formal_type_parameters_;
+ Object* java_generic_exception_types_;
+ Object* java_generic_parameter_types_;
+ Object* java_generic_return_type_;
+ Class* java_return_type_; // Unused by ART
+ String* name_;
+ ObjectArray<Class>* java_parameter_types_;
+ uint32_t java_generic_types_are_initialized_;
+ uint32_t java_slot_;
+
+ // TODO: start of non-Java mirror fields, place these in the Java piece
- public: // TODO: private/const
// access flags; low 16 bits are defined by spec (could be uint16_t?)
uint32_t access_flags_;
@@ -758,14 +1004,17 @@ class Method : public AccessibleObject {
uint32_t proto_idx_;
// Offset to the CodeItem.
- uint32_t code_off_;
+ uint32_t code_item_offset_;
- // The short-form method descriptor string.
- StringPiece shorty_;
+ // Index of the return type
+ uint32_t java_return_type_idx_;
+
+ // The short-form method descriptor string. TODO: make String*
+ const char* shorty_;
// short cuts to declaring_class_->dex_cache_ members for fast compiled code
// access
- ObjectArray<const String>* dex_cache_strings_;
+ ObjectArray<String>* dex_cache_strings_;
ObjectArray<Class>* dex_cache_resolved_types_;
ObjectArray<Method>* dex_cache_resolved_methods_;
ObjectArray<Field>* dex_cache_resolved_fields_;
@@ -776,6 +1025,7 @@ class Method : public AccessibleObject {
// Compiled code associated with this method
UniquePtr<MemMap> code_area_;
const void* code_;
+
// Instruction set of the compiled code
InstructionSet code_instruction_set_;
@@ -792,6 +1042,8 @@ class Method : public AccessibleObject {
// Native invocation stub entry point.
const InvokeStub* invoke_stub_;
+ static Class* java_lang_reflect_Method_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(Method);
};
@@ -816,19 +1068,20 @@ class Array : public Object {
size_t SizeOf() const;
int32_t GetLength() const {
- return length_;
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), false);
}
- void SetLength(uint32_t length) {
- length_ = length;
+ void SetLength(int32_t length) {
+ CHECK_LE(0, length);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Array, length_), length, false);
}
static MemberOffset LengthOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Array, length_));
+ return OFFSET_OF_OBJECT_MEMBER(Array, length_);
}
static MemberOffset DataOffset() {
- return MemberOffset(OFFSETOF_MEMBER(Array, first_element_));
+ return OFFSET_OF_OBJECT_MEMBER(Array, first_element_);
}
void* GetRawData() {
@@ -860,61 +1113,54 @@ class Array : public Object {
template<class T>
class ObjectArray : public Array {
public:
- static ObjectArray<T>* Alloc(Class* object_array_class,
- int32_t length) {
- return Array::Alloc(object_array_class, length, sizeof(uint32_t))->AsObjectArray<T>();
- }
+ static ObjectArray<T>* Alloc(Class* object_array_class, int32_t length);
- T* const * GetData() const {
- return reinterpret_cast<T* const *>(&elements_);
- }
+ T* Get(int32_t i) const;
- T** GetData() {
- return reinterpret_cast<T**>(&elements_);
- }
+ void Set(int32_t i, T* object);
- T* Get(int32_t i) const {
- if (!IsValidIndex(i)) {
- return NULL;
- }
- return GetData()[i];
- }
+ // 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);
- void Set(int32_t i, T* object) {
- if (IsValidIndex(i)) {
- // TODO: ArrayStoreException
- GetData()[i] = object; // TODO: write barrier
- }
- }
-
- static void Copy(ObjectArray<T>* src, int src_pos,
+ static void Copy(const ObjectArray<T>* src, int src_pos,
ObjectArray<T>* dst, int dst_pos,
- size_t length) {
- for (size_t i = 0; i < length; i++) {
- dst->Set(dst_pos + i, src->Get(src_pos + i));
- }
- }
+ size_t length);
- ObjectArray<T>* CopyOf(int32_t new_length) {
- ObjectArray<T>* new_array = Alloc(klass_, new_length);
- Copy(this, 0, new_array, 0, std::min(GetLength(), new_length));
- return new_array;
- }
+ ObjectArray<T>* CopyOf(int32_t new_length);
private:
- // Location of first element.
- T* elements_[0];
-
DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectArray);
};
+template<class T>
+ObjectArray<T>* ObjectArray<T>::Alloc(Class* object_array_class, int32_t length) {
+ return Array::Alloc(object_array_class, length, sizeof(uint32_t))->AsObjectArray<T>();
+}
+
+template<class T>
+T* ObjectArray<T>::Get(int32_t i) const {
+ if (!IsValidIndex(i)) {
+ return NULL;
+ }
+ MemberOffset data_offset(DataOffset().Int32Value() + i * sizeof(Object*));
+ return GetFieldObject<T*>(data_offset, false);
+}
+
+template<class T>
+ObjectArray<T>* ObjectArray<T>::CopyOf(int32_t new_length) {
+ ObjectArray<T>* new_array = Alloc(GetClass(), new_length);
+ Copy(this, 0, new_array, 0, std::min(GetLength(), new_length));
+ return new_array;
+}
+
// Type for the InitializedStaticStorage table. Currently the Class
// provides the static storage. However, this might change to improve
// image sharing, so we use this type to avoid assumptions on the
// current storage.
class StaticStorageBase {};
-// Class objects.
+// C++ mirror of java.lang.Class
class Class : public Object, public StaticStorageBase {
public:
@@ -938,9 +1184,10 @@ class Class : public Object, public StaticStorageBase {
// using ResolveClass to initialize the super_class_ and interfaces_.
//
// kStatusResolved: Still holding the lock on Class, the ClassLinker
- // will use LinkClass to link all members, creating Field and Method
- // objects, setting up the vtable, etc. On success, the class is
- // marked kStatusResolved.
+ // 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.
enum Status {
kStatusError = -1,
@@ -955,210 +1202,422 @@ class Class : public Object, public StaticStorageBase {
};
enum PrimitiveType {
- kPrimNot = -1
+ kPrimNot = 0,
+ kPrimBoolean,
+ kPrimByte,
+ kPrimChar,
+ kPrimShort,
+ kPrimInt,
+ kPrimLong,
+ kPrimFloat,
+ kPrimDouble,
+ kPrimVoid,
};
- // Given the context of a calling Method, use its DexCache to
- // resolve a type to a Class. If it cannot be resolved, throw an
- // error. If it can, use it to create an instance.
- static Object* AllocObjectFromCode(uint32_t type_idx, Method* method);
+ Status GetStatus() const {
+ CHECK(sizeof(Status) == sizeof(uint32_t));
+ return static_cast<Status>(
+ GetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), false));
+ }
- // Creates a raw object instance but does not invoke the default constructor.
- Object* AllocObject();
+ void SetStatus(Status new_status);
- Class* GetSuperClass() const {
- return super_class_;
+ // Returns true if the class has failed to link.
+ bool IsErroneous() const {
+ return GetStatus() == kStatusError;
}
- uint32_t GetSuperClassTypeIdx() const {
- return super_class_type_idx_;
+ // Returns true if the class has been loaded.
+ bool IsIdxLoaded() const {
+ return GetStatus() >= kStatusIdx;
}
- bool HasSuperClass() const {
- return super_class_ != NULL;
+ // Returns true if the class has been loaded.
+ bool IsLoaded() const {
+ return GetStatus() >= kStatusLoaded;
}
- bool IsAssignableFrom(const Class* klass) const {
- DCHECK(klass != NULL);
- if (this == klass) {
- return true;
- }
- if (IsInterface()) {
- return klass->Implements(this);
- }
- if (klass->IsArrayClass()) {
- return IsAssignableFromArray(klass);
- }
- return klass->IsSubClass(this);
+ // Returns true if the class has been linked.
+ bool IsLinked() const {
+ return GetStatus() >= kStatusResolved;
}
- const ClassLoader* GetClassLoader() const {
- return class_loader_;
+ // Returns true if the class has been verified.
+ bool IsVerified() const {
+ return GetStatus() >= kStatusVerified;
}
- DexCache* GetDexCache() const {
- return dex_cache_;
+ // Returns true if the class is initialized.
+ bool IsInitialized() const {
+ return GetStatus() == kStatusInitialized;
}
- Class* GetComponentType() const {
- return component_type_;
+ uint32_t GetAccessFlags() const;
+
+ void SetAccessFlags(uint32_t new_access_flags) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), new_access_flags,
+ false);
}
- static size_t GetTypeSize(String* descriptor);
+ // Returns true if the class is an interface.
+ bool IsInterface() const {
+ return (GetAccessFlags() & kAccInterface) != 0;
+ }
- size_t GetComponentSize() const {
- return GetTypeSize(component_type_->descriptor_);
+ // Returns true if the class is declared public.
+ bool IsPublic() const {
+ return (GetAccessFlags() & kAccPublic) != 0;
}
- const String* GetDescriptor() const {
- DCHECK(descriptor_ != NULL);
- // DCHECK_NE(0, descriptor_->GetLength()); // TODO: keep?
- return descriptor_;
+ // Returns true if the class is declared final.
+ bool IsFinal() const {
+ return (GetAccessFlags() & kAccFinal) != 0;
}
- size_t SizeOf() const {
- return class_size_;
+ // Returns true if the class is abstract.
+ bool IsAbstract() const {
+ return (GetAccessFlags() & kAccAbstract) != 0;
}
- Status GetStatus() const {
- return status_;
+ // Returns true if the class is an annotation.
+ bool IsAnnotation() const {
+ return (GetAccessFlags() & kAccAnnotation) != 0;
}
- void SetStatus(Status new_status) {
- // TODO: validate transition
- status_ = new_status;
+ // Returns true if the class is synthetic.
+ bool IsSynthetic() const {
+ return (GetAccessFlags() & kAccSynthetic) != 0;
}
- // Returns true if the class has failed to link.
- bool IsErroneous() const {
- return GetStatus() == kStatusError;
+ bool IsReferenceClass() const {
+ return (GetAccessFlags() & kAccClassIsReference) != 0;
}
- // Returns true if the class has been verified.
- bool IsVerified() const {
- return GetStatus() >= kStatusVerified;
+ bool IsWeakReferenceClass() const {
+ return (GetAccessFlags() & kAccClassIsWeakReference) != 0;
}
- // Returns true if the class has been linked.
- bool IsLinked() const {
- return GetStatus() >= kStatusResolved;
+ bool IsSoftReferenceClass() const {
+ return (GetAccessFlags() & ~kAccReferenceFlagsMask) == kAccClassIsReference;
}
- // Returns true if the class has been loaded.
- bool IsLoaded() const {
- return GetStatus() >= kStatusLoaded;
+ bool IsFinalizerReferenceClass() const {
+ return (GetAccessFlags() & kAccClassIsFinalizerReference) != 0;
}
- // Returns true if the class is initialized.
- bool IsInitialized() const {
- return GetStatus() == kStatusInitialized;
+ bool IsPhantomReferenceClass() const {
+ return (GetAccessFlags() & kAccClassIsPhantomReference) != 0;
}
- // Returns true if this class is in the same packages as that class.
- bool IsInSamePackage(const Class* that) const;
+ PrimitiveType GetPrimitiveType() const {
+ CHECK(sizeof(PrimitiveType) == sizeof(int32_t));
+ return static_cast<PrimitiveType>(
+ GetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), false));
+ }
- static bool IsInSamePackage(const String* descriptor1,
- const String* descriptor2);
+ void SetPrimitiveType(PrimitiveType new_type) {
+ CHECK(sizeof(PrimitiveType) == sizeof(int32_t));
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, primitive_type_), new_type,
+ false);
+ }
- // Returns true if this class represents an array class.
- bool IsArrayClass() const;
+ // Returns true if the class is a primitive type.
+ bool IsPrimitive() const {
+ return GetPrimitiveType() != kPrimNot;
+ }
- // Returns true if the class is an interface.
- bool IsInterface() const {
- return (access_flags_ & kAccInterface) != 0;
+ bool IsPrimitiveBoolean() const {
+ return GetPrimitiveType() == kPrimBoolean;
}
- // Returns true if the class is declared public.
- bool IsPublic() const {
- return (access_flags_ & kAccPublic) != 0;
+ bool IsPrimitiveByte() const {
+ return GetPrimitiveType() == kPrimByte;
}
- // Returns true if the class is declared final.
- bool IsFinal() const {
- return (access_flags_ & kAccFinal) != 0;
+ bool IsPrimitiveChar() const {
+ return GetPrimitiveType() == kPrimChar;
}
- // Returns true if the class is abstract.
- bool IsAbstract() const {
- return (access_flags_ & kAccAbstract) != 0;
+ bool IsPrimitiveShort() const {
+ return GetPrimitiveType() == kPrimShort;
}
- // Returns true if the class is an annotation.
- bool IsAnnotation() const {
- return (access_flags_ & kAccAnnotation) != 0;
+ bool IsPrimitiveInt() const {
+ return GetPrimitiveType() == kPrimInt;
}
- // Returns true if the class is a primitive type.
- bool IsPrimitive() const {
- return primitive_type_ != kPrimNot;
+ bool IsPrimitiveLong() const {
+ return GetPrimitiveType() == kPrimLong;
}
- // Returns true if the class is synthetic.
- bool IsSynthetic() const {
- return (access_flags_ & kAccSynthetic) != 0;
+ bool IsPrimitiveFloat() const {
+ return GetPrimitiveType() == kPrimFloat;
+ }
+
+ bool IsPrimitiveDouble() const {
+ return GetPrimitiveType() == kPrimDouble;
+ }
+
+ bool IsPrimitiveVoid() const {
+ return GetPrimitiveType() == kPrimVoid;
+ }
+
+ size_t PrimitiveSize() const;
+
+ bool IsArrayClass() const {
+ return GetArrayRank() != 0;
+ }
+
+ int32_t GetArrayRank() const {
+ int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, array_rank_),
+ false);
+ return result;
+ }
+
+ void SetArrayRank(int32_t new_array_rank) {
+ DCHECK_EQ(0, GetArrayRank());
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, array_rank_), new_array_rank,
+ false);
+ }
+
+ Class* GetComponentType() const {
+ DCHECK(IsArrayClass());
+ return GetFieldObject<Class*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, component_type_), false);
+ }
+
+ void SetComponentType(Class* new_component_type) {
+ DCHECK(GetComponentType() == NULL);
+ DCHECK(new_component_type != NULL);
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, component_type_),
+ new_component_type, false);
}
- bool IsReference() const {
- return (access_flags_ & kAccClassIsReference) != 0;
+ size_t GetComponentSize() const {
+ return GetTypeSize(GetComponentType()->GetDescriptor());
+ }
+
+ bool IsObjectClass() const {
+ return !IsPrimitive() && GetSuperClass() == NULL;
+ }
+
+ static bool CanPutArrayElementFromCode(const Class* elementClass, const Class* arrayClass);
+
+ // Given the context of a calling Method, use its DexCache to
+ // resolve a type to a Class. If it cannot be resolved, throw an
+ // error. If it can, use it to create an instance.
+ static Object* AllocObjectFromCode(uint32_t type_idx, Method* method);
+
+ // Creates a raw object instance but does not invoke the default constructor.
+ Object* AllocObject();
+
+ static size_t GetTypeSize(const String* descriptor);
+
+ const String* GetDescriptor() const {
+ const String* result = GetFieldObject<const String*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, descriptor_), false);
+ // DCHECK(result != NULL); // may be NULL prior to class linker initialization
+ // DCHECK_NE(0, result->GetLength()); // TODO: keep?
+ return result;
+ }
+
+ void SetDescriptor(String* new_descriptor);
+
+ 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 {
+ CHECK(sizeof(size_t) == sizeof(int32_t));
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
- bool IsWeakReference() const {
- return (access_flags_ & kAccClassIsWeakReference) != 0;
+ size_t GetClassSize() const {
+ CHECK(sizeof(size_t) == sizeof(uint32_t));
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), false);
}
- bool IsSoftReference() const {
- return (access_flags_ & ~kAccReferenceFlagsMask) == kAccClassIsReference;
+ void SetClassSize(size_t new_class_size) {
+ DCHECK_GE(new_class_size, GetClassSize());
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, class_size_), new_class_size,
+ false);
}
- bool IsFinalizerReference() const {
- return (access_flags_ & kAccClassIsFinalizerReference) != 0;
+ size_t GetObjectSize() const {
+ CHECK(!IsVariableSize());
+ CHECK(sizeof(size_t) == sizeof(int32_t));
+ size_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(Class, object_size_),
+ false);
+ CHECK_GE(result, sizeof(Object));
+ return result;
}
- bool IsPhantomReference() const {
- return (access_flags_ & kAccClassIsPhantomReference) != 0;
+ void SetObjectSize(size_t new_object_size) {
+ DCHECK(!IsVariableSize());
+ CHECK(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;
+
+ static bool IsInSamePackage(const String* descriptor1,
+ const String* descriptor2);
+
// Returns true if this class can access that class.
bool CanAccess(const Class* that) const {
return that->IsPublic() || this->IsInSamePackage(that);
}
- static bool CanPutArrayElementFromCode(const Class* elementClass, const Class* arrayClass);
+ bool IsAssignableFrom(const Class* klass) const {
+ DCHECK(klass != NULL);
+ if (this == klass) {
+ // Can always assign to things of the same type
+ return true;
+ } else if(IsObjectClass()) {
+ // Can assign any reference to java.lang.Object
+ return !klass->IsPrimitive();
+ } else if (IsInterface()) {
+ return klass->Implements(this);
+ } else if (klass->IsArrayClass()) {
+ return IsAssignableFromArray(klass);
+ } else {
+ return klass->IsSubClass(this);
+ }
+ }
- // Returns the number of static, private, and constructor methods.
- size_t NumDirectMethods() const {
- return (direct_methods_ != NULL) ? direct_methods_->GetLength() : 0;
+ Class* GetSuperClass() const {
+ // Can only get super class for loaded classes (hack for when runtime is
+ // initializing)
+ DCHECK(IsLoaded() || Runtime::Current() == NULL);
+ return GetFieldObject<Class*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
+ }
+
+ void SetSuperClass(Class *new_super_class) {
+ // 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;
+ }
+
+ uint32_t GetSuperClassTypeIdx() const {
+ DCHECK(IsIdxLoaded());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, super_class_type_idx_),
+ false);
+ }
+
+ void SetSuperClassTypeIdx(int32_t new_super_class_idx) {
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, super_class_type_idx_),
+ new_super_class_idx, false);
+ }
+
+ const ClassLoader* GetClassLoader() const;
+
+ void SetClassLoader(const ClassLoader* new_cl);
+
+ static MemberOffset DexCacheOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Class, dex_cache_));
+ }
+
+ DexCache* GetDexCache() const;
+
+ void SetDexCache(DexCache* new_dex_cache);
+
+ ObjectArray<Method>* GetDirectMethods() const {
+ DCHECK(IsLoaded());
+ return GetFieldObject<ObjectArray<Method>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
+ }
+
+ void SetDirectMethods(ObjectArray<Method>* new_direct_methods) {
+ DCHECK(NULL == GetFieldObject<ObjectArray<Method>*>(
+ 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);
}
Method* GetDirectMethod(int32_t i) const {
- DCHECK_NE(NumDirectMethods(), 0U);
- return direct_methods_->Get(i);
+ return GetDirectMethods()->Get(i);
}
void SetDirectMethod(uint32_t i, Method* f) { // TODO: uint16_t
- DCHECK_NE(NumDirectMethods(), 0U);
- direct_methods_->Set(i, f);
+ ObjectArray<Method>* direct_methods =
+ GetFieldObject<ObjectArray<Method>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, direct_methods_), false);
+ direct_methods->Set(i, f);
}
- Method* FindDeclaredDirectMethod(const StringPiece& name,
- const StringPiece& signature);
+ // Returns the number of static, private, and constructor methods.
+ size_t NumDirectMethods() const {
+ return (GetDirectMethods() != NULL) ? GetDirectMethods()->GetLength() : 0;
+ }
- Method* FindDirectMethod(const StringPiece& name,
- const StringPiece& signature);
+ ObjectArray<Method>* GetVirtualMethods() const {
+ DCHECK(IsLoaded());
+ return GetFieldObject<ObjectArray<Method>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
+ }
+
+ void SetVirtualMethods(ObjectArray<Method>* new_virtual_methods) {
+ // 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 (virtual_methods_ != NULL) ? virtual_methods_->GetLength() : 0;
+ return (GetVirtualMethods() != NULL) ? GetVirtualMethods()->GetLength() : 0;
}
Method* GetVirtualMethod(uint32_t i) const {
- DCHECK_NE(NumVirtualMethods(), 0U);
- return virtual_methods_->Get(i);
+ DCHECK(IsLinked());
+ return GetVirtualMethods()->Get(i);
+ }
+
+ Method* GetVirtualMethodDuringLinking(uint32_t i) const {
+ DCHECK(IsLoaded());
+ return GetVirtualMethods()->Get(i);
}
void SetVirtualMethod(uint32_t i, Method* f) { // TODO: uint16_t
- DCHECK_NE(NumVirtualMethods(), 0U);
- virtual_methods_->Set(i, f);
+ ObjectArray<Method>* virtual_methods =
+ GetFieldObject<ObjectArray<Method>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, virtual_methods_), false);
+ virtual_methods->Set(i, f);
+ }
+
+ ObjectArray<Method>* GetVTable() const {
+ DCHECK(IsLinked());
+ return GetFieldObject<ObjectArray<Method>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+ }
+
+ ObjectArray<Method>* GetVTableDuringLinking() const {
+ DCHECK(IsLoaded());
+ return GetFieldObject<ObjectArray<Method>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, vtable_), false);
+ }
+
+ void SetVTable(ObjectArray<Method>* new_vtable) {
+ 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
@@ -1167,8 +1626,8 @@ class Class : public Object, public StaticStorageBase {
Method* FindVirtualMethodForVirtual(Method* method) {
DCHECK(!method->GetDeclaringClass()->IsInterface());
// The argument method may from a super class.
- // Use the index to a potentially overriden one for this instance's class.
- return vtable_->Get(method->method_index_);
+ // 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, but potentially from a
@@ -1189,94 +1648,256 @@ class Class : public Object, public StaticStorageBase {
Method* FindVirtualMethod(const StringPiece& name,
const StringPiece& descriptor);
- size_t NumInstanceFields() const {
- return (ifields_ != NULL) ? ifields_->GetLength() : 0;
+ Method* FindDeclaredDirectMethod(const StringPiece& name,
+ const StringPiece& signature);
+
+ Method* FindDirectMethod(const StringPiece& name,
+ const StringPiece& signature);
+
+ size_t NumInterfaces() const {
+ CHECK(IsIdxLoaded()); // used during loading
+ ObjectArray<Class>* interfaces = GetFieldObject<ObjectArray<Class>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
+ return (interfaces != NULL) ? interfaces->GetLength() : 0;
}
- // Returns the number of instance fields containing reference types.
- size_t NumReferenceInstanceFields() const {
- return num_reference_instance_fields_;
+ IntArray* GetInterfacesTypeIdx() const {
+ CHECK(IsIdxLoaded());
+ return GetFieldObject<IntArray*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, interfaces_type_idx_), false);
}
- // Returns the number of static fields containing reference types.
- size_t NumReferenceStaticFields() const {
- return num_reference_static_fields_;
+ void SetInterfacesTypeIdx(IntArray* new_interfaces_idx);
+
+ ObjectArray<Class>* GetInterfaces() const {
+ CHECK(IsLoaded());
+ return GetFieldObject<ObjectArray<Class>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
}
- // Finds the given instance field in this class or a superclass.
- Field* FindInstanceField(const StringPiece& name,
- const StringPiece& descriptor);
+ void SetInterfaces(ObjectArray<Class>* new_interfaces) {
+ DCHECK(NULL == GetFieldObject<Object*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false));
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, interfaces_),
+ new_interfaces, false);
+ }
- // Finds the given instance field in this class.
- Field* FindDeclaredInstanceField(const StringPiece& name,
- const StringPiece& descriptor);
+ void SetInterface(uint32_t i, Class* f) { // TODO: uint16_t
+ DCHECK_NE(NumInterfaces(), 0U);
+ ObjectArray<Class>* interfaces =
+ GetFieldObject<ObjectArray<Class>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, interfaces_), false);
+ interfaces->Set(i, f);
+ }
- // Finds the given static field in this class or a superclass.
- Field* FindStaticField(const StringPiece& name,
- const StringPiece& descriptor);
+ Class* GetInterface(uint32_t i) const {
+ DCHECK_NE(NumInterfaces(), 0U);
+ return GetInterfaces()->Get(i);
+ }
+
+ size_t GetIFTableCount() const {
+ DCHECK(IsLinked());
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, iftable_count_), false);
+ }
+
+ void SetIFTableCount(size_t new_iftable_count) {
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, iftable_count_),
+ new_iftable_count, false);
+ }
+
+ InterfaceEntry* GetIFTable() const {
+ DCHECK(IsLinked());
+ return GetFieldPtr<InterfaceEntry*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, iftable_), false);
+ }
+
+ void SetIFTable(InterfaceEntry* new_iftable) {
+ SetFieldPtr<InterfaceEntry*>(OFFSET_OF_OBJECT_MEMBER(Class, iftable_),
+ new_iftable, false);
+ }
+
+ size_t GetIfviPoolCount() const {
+ DCHECK(IsLinked());
+ CHECK(sizeof(size_t) == sizeof(int32_t));
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_count_), false);
+ }
+
+ void SetIfviPoolCount(size_t new_count) {
+ CHECK(sizeof(size_t) == sizeof(int32_t));
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_count_), new_count,
+ false);
+ }
+
+ uint32_t* GetIfviPool() const {
+ DCHECK(IsLinked());
+ return GetFieldPtr<uint32_t*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_), false);
+ }
- // Finds the given static field in this class.
- Field* FindDeclaredStaticField(const StringPiece& name,
- const StringPiece& descriptor);
+ void SetIfviPool(uint32_t* new_pool) {
+ SetFieldPtr(OFFSET_OF_OBJECT_MEMBER(Class, ifvi_pool_), new_pool, false);
+ }
+
+ // Get instance fields
+ ObjectArray<Field>* GetIFields() const {
+ DCHECK(IsLoaded());
+ return GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
+ }
+
+ void SetIFields(ObjectArray<Field>* new_ifields) {
+ 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
DCHECK_NE(NumInstanceFields(), 0U);
- return ifields_->Get(i);
+ return GetIFields()->Get(i);
}
void SetInstanceField(uint32_t i, Field* f) { // TODO: uint16_t
- DCHECK_NE(NumInstanceFields(), 0U);
- ifields_->Set(i, f);
+ ObjectArray<Field>* ifields= GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, ifields_), false);
+ ifields->Set(i, f);
}
- size_t NumStaticFields() const {
- return (sfields_ != NULL) ? sfields_->GetLength() : 0;
+ // Returns the number of instance fields containing reference types.
+ size_t NumReferenceInstanceFields() const {
+ DCHECK(IsLinked());
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ return GetField32(
+ OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
}
- Field* GetStaticField(uint32_t i) const { // TODO: uint16_t
- DCHECK_NE(NumStaticFields(), 0U);
- return sfields_->Get(i);
+ size_t NumReferenceInstanceFieldsDuringLinking() const {
+ DCHECK(IsLoaded());
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ return GetField32(
+ OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), false);
}
- void SetStaticField(uint32_t i, Field* f) { // TODO: uint16_t
- DCHECK_NE(NumStaticFields(), 0U);
- sfields_->Set(i, f);
+ void SetNumReferenceInstanceFields(size_t new_num) {
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_),
+ new_num, false);
}
uint32_t GetReferenceInstanceOffsets() const {
- return reference_instance_offsets_;
+ DCHECK(IsLinked());
+ return GetField32(
+ OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_), false);
}
- void SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
- reference_instance_offsets_ = new_reference_offsets;
+ void SetReferenceInstanceOffsets(uint32_t new_reference_offsets);
+
+ // Beginning of static field data
+ static MemberOffset FieldsOffset() {
+ return OFFSET_OF_OBJECT_MEMBER(Class, fields_);
}
- uint32_t GetReferenceStaticOffsets() const {
- return reference_static_offsets_;
+ // Returns the number of static fields containing reference types.
+ size_t NumReferenceStaticFields() const {
+ DCHECK(IsLinked());
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ return GetField32(
+ OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
}
- void SetReferenceStaticOffsets(uint32_t new_reference_offsets) {
- reference_static_offsets_ = new_reference_offsets;
+ size_t NumReferenceStaticFieldsDuringLinking() const {
+ DCHECK(IsLoaded());
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ return GetField32(
+ OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_), false);
}
- size_t NumInterfaces() const {
- return (interfaces_ != NULL) ? interfaces_->GetLength() : 0;
+ void SetNumReferenceStaticFields(size_t new_num) {
+ DCHECK(sizeof(size_t) == sizeof(int32_t));
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_static_fields_),
+ new_num, false);
}
- Class* GetInterface(uint32_t i) const {
- DCHECK_NE(NumInterfaces(), 0U);
- return interfaces_->Get(i);
+ ObjectArray<Field>* GetSFields() const {
+ DCHECK(IsLoaded());
+ return GetFieldObject<ObjectArray<Field>*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, sfields_), false);
}
- void SetInterface(uint32_t i, Class* f) { // TODO: uint16_t
- DCHECK_NE(NumInterfaces(), 0U);
- interfaces_->Set(i, f);
+ void SetSFields(ObjectArray<Field>* new_sfields) {
+ 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
+ return GetSFields()->Get(i);
+ }
+
+ void SetStaticField(uint32_t i, Field* f) { // TODO: uint16_t
+ 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);
+
+ // Finds the given instance field in this class or a superclass.
+ Field* FindInstanceField(const StringPiece& name, Class* type);
+
+ Field* FindDeclaredInstanceField(const StringPiece& name, Class* type);
+
+ // Finds the given static field in this class or a superclass.
+ Field* FindStaticField(const StringPiece& name, Class* type);
+
+ Field* FindDeclaredStaticField(const StringPiece& name, Class* type);
+
+ uint32_t GetClinitThreadId() const {
+ DCHECK(IsIdxLoaded());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, clinit_thread_id_), false);
+ }
+
+ void SetClinitThreadId(uint32_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);
}
void SetVerifyErrorClass(Class* klass) {
- // Note SetFieldObject is used rather than verify_error_class_ directly for the barrier
- size_t field_offset = OFFSETOF_MEMBER(Class, verify_error_class_);
- klass->SetFieldObject(field_offset, klass);
+ klass->SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, verify_error_class_),
+ klass, false);
+ }
+
+ const char* GetSourceFile() const {
+ DCHECK(IsLoaded());
+ return GetFieldPtr<const char*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, source_file_), false);
+ }
+
+ void SetSourceFile(const char* new_source_file) {
+ SetFieldPtr<const char*>(OFFSET_OF_OBJECT_MEMBER(Class, source_file_),
+ new_source_file, false);
}
private:
@@ -1285,7 +1906,10 @@ class Class : public Object, public StaticStorageBase {
bool IsAssignableFromArray(const Class* klass) const;
bool IsSubClass(const Class* klass) const;
- public: // TODO: private
+ // TODO: the image writer should know the offsets of these fields as they
+ // should appear in the libcore Java mirror
+ friend class ImageWriter;
+
// descriptor for the class such as "java.lang.Class" or "[C"
String* name_; // TODO initialize
@@ -1416,56 +2040,210 @@ class Class : public Object, public StaticStorageBase {
private:
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
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Object, klass_), new_klass, false);
+}
+
inline bool Object::InstanceOf(const Class* klass) const {
DCHECK(klass != NULL);
- DCHECK(klass_ != NULL);
- return klass->IsAssignableFrom(klass_);
+ DCHECK(GetClass() != NULL);
+ return klass->IsAssignableFrom(GetClass());
}
inline bool Object::IsClass() const {
- Class* java_lang_Class = klass_->klass_;
- return klass_ == java_lang_Class;
+ Class* java_lang_Class = GetClass()->GetClass();
+ return GetClass() == java_lang_Class;
}
inline bool Object::IsClassClass() const {
- Class* java_lang_Class = klass_->klass_;
+ Class* java_lang_Class = GetClass()->GetClass();
return this == java_lang_Class;
}
inline bool Object::IsObjectArray() const {
- return IsArrayInstance() && !klass_->component_type_->IsPrimitive();
+ return IsArrayInstance() && !GetClass()->GetComponentType()->IsPrimitive();
}
inline bool Object::IsArrayInstance() const {
- return klass_->IsArrayClass();
+ return GetClass()->IsArrayClass();
}
inline bool Object::IsField() const {
Class* java_lang_Class = klass_->klass_;
- Class* java_lang_reflect_Field = java_lang_Class->GetInstanceField(0)->klass_;
- return klass_ == java_lang_reflect_Field;
+ Class* java_lang_reflect_Field =
+ java_lang_Class->GetInstanceField(0)->GetClass();
+ return GetClass() == java_lang_reflect_Field;
}
inline bool Object::IsMethod() const {
- Class* java_lang_Class = klass_->klass_;
- Class* java_lang_reflect_Method = java_lang_Class->GetDirectMethod(0)->klass_;
- return klass_ == java_lang_reflect_Method;
+ Class* java_lang_Class = GetClass()->GetClass();
+ Class* java_lang_reflect_Method =
+ java_lang_Class->GetDirectMethod(0)->GetClass();
+ return GetClass() == java_lang_reflect_Method;
+}
+
+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()) {
- return AsArray()->SizeOf();
- }
- if (IsClass()) {
- return AsClass()->SizeOf();
+ result = AsArray()->SizeOf();
+ } else if (IsClass()) {
+ result = AsClass()->SizeOf();
+ } else {
+ result = GetClass()->GetObjectSize();
+ }
+ DCHECK(!IsField() || result == sizeof(Field));
+ DCHECK(!IsMethod() || result == sizeof(Method));
+ return result;
+}
+
+inline void Field::SetOffset(MemberOffset num_bytes) {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ DCHECK_LE(CLASS_SMALLEST_OFFSET, num_bytes.Uint32Value());
+ Class* type = GetTypeDuringLinking();
+ if (type != NULL && (type->IsPrimitiveDouble() || type->IsPrimitiveLong())) {
+ DCHECK(IsAligned(num_bytes.Uint32Value(), 8));
}
- return klass_->object_size_;
+ SetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_),
+ num_bytes.Uint32Value(), false);
+}
+
+inline Class* Field::GetDeclaringClass() const {
+ Class* result = GetFieldObject<Class*>(
+ OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_), false);
+ DCHECK(result != NULL);
+ DCHECK(result->IsLoaded());
+ return result;
+}
+
+inline void Field::SetDeclaringClass(Class *new_declaring_class) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, declaring_class_),
+ new_declaring_class, false);
+}
+
+inline Class* Method::GetDeclaringClass() const {
+ Class* result =
+ GetFieldObject<Class*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_), false);
+ DCHECK(result != NULL);
+ DCHECK(result->IsLoaded());
+ return result;
+}
+
+inline void Method::SetDeclaringClass(Class *new_declaring_class) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, declaring_class_),
+ new_declaring_class, false);
+}
+
+inline uint32_t Method::GetReturnTypeIdx() const {
+ DCHECK(GetDeclaringClass()->IsLinked());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, java_return_type_idx_),
+ false);
+}
+
+inline bool Method::IsReturnAReference() const {
+ return !GetReturnType()->IsPrimitive();
+}
+
+inline bool Method::IsReturnAFloat() const {
+ return GetReturnType()->IsPrimitiveFloat();
+}
+
+inline bool Method::IsReturnADouble() const {
+ return GetReturnType()->IsPrimitiveDouble();
+}
+
+inline bool Method::IsReturnALong() const {
+ return GetReturnType()->IsPrimitiveLong();
+}
+
+inline bool Method::IsReturnVoid() const {
+ return GetReturnType()->IsPrimitiveVoid();
}
inline size_t Array::SizeOf() const {
- return SizeOf(GetLength(), klass_->GetComponentSize());
+ return SizeOf(GetLength(), GetClass()->GetComponentSize());
+}
+
+template<class T>
+void ObjectArray<T>::Set(int32_t i, T* object) {
+ if (IsValidIndex(i)) {
+ if (object != NULL) {
+ Class* element_class = GetClass()->GetComponentType();
+ DCHECK(!element_class->IsPrimitive());
+ // TODO: ArrayStoreException
+ CHECK(object->InstanceOf(element_class));
+ }
+ MemberOffset data_offset(DataOffset().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().Int32Value() + i * sizeof(Object*));
+ SetFieldObject(data_offset, object, 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().Int32Value() +
+ src_pos * sizeof(Object*));
+ MemberOffset dst_offset(DataOffset().Int32Value() +
+ dst_pos * sizeof(Object*));
+ Class* array_class = dst->GetClass();
+ 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);
+ dst->SetFieldObject(dst_offset, object, false);
+ 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);
+ // TODO: ArrayStoreException
+ CHECK(object == NULL || object->InstanceOf(element_class));
+ dst->SetFieldObject(dst_offset, object, false);
+ src_offset = MemberOffset(src_offset.Uint32Value() + sizeof(Object*));
+ dst_offset = MemberOffset(dst_offset.Uint32Value() + sizeof(Object*));
+ }
+ }
+ // TODO: bulk write barrier
+ }
}
class ClassClass : public Class {
@@ -1563,145 +2341,105 @@ class PrimitiveArray : public Array {
DISALLOW_IMPLICIT_CONSTRUCTORS(PrimitiveArray);
};
+inline void Class::SetInterfacesTypeIdx(IntArray* new_interfaces_idx) {
+ DCHECK(NULL == GetFieldObject<IntArray*>(
+ OFFSET_OF_OBJECT_MEMBER(Class, interfaces_type_idx_), false));
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, interfaces_type_idx_),
+ new_interfaces_idx, false);
+}
+
+// C++ mirror of java.lang.String
class String : public Object {
public:
const CharArray* GetCharArray() const {
- DCHECK(array_ != NULL);
- return array_;
- }
-
- uint32_t GetHashCode() const {
- return hash_code_;
+ const CharArray* result = GetFieldObject<const CharArray*>(
+ OFFSET_OF_OBJECT_MEMBER(String, array_), false);
+ DCHECK(result != NULL);
+ return result;
}
int32_t GetOffset() const {
- return offset_;
+ int32_t result = GetField32(
+ OFFSET_OF_OBJECT_MEMBER(String, offset_), false);
+ DCHECK_LE(0, result);
+ return result;
}
- int32_t GetLength() const {
- return count_;
+ int32_t GetLength() const;
+
+ int32_t GetHashCode() const;
+
+ void ComputeHashCode() {
+ SetHashCode(ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()));
}
int32_t GetUtfLength() const {
- return CountUtf8Bytes(array_->GetData(), count_);
+ return CountUtf8Bytes(GetCharArray()->GetData(), GetLength());
}
- // TODO: do we need this? Equals is the only caller, and could
- // bounds check itself.
- uint16_t CharAt(int32_t index) const {
- if (index < 0 || index >= count_) {
- Thread* self = Thread::Current();
- self->ThrowNewException("Ljava/lang/StringIndexOutOfBoundsException;",
- "length=%i; index=%i", count_, index);
- return 0;
- }
- return GetCharArray()->Get(index + GetOffset());
- }
+ uint16_t CharAt(int32_t index) const;
+
+ const String* Intern() const;
static String* AllocFromUtf16(int32_t utf16_length,
const uint16_t* utf16_data_in,
- int32_t hash_code = 0) {
- String* string = Alloc(GetJavaLangString(),
- utf16_length);
- // TODO: use 16-bit wide memset variant
- for (int i = 0; i < utf16_length; i++ ) {
- string->array_->Set(i, utf16_data_in[i]);
- }
- if (hash_code != 0) {
- string->hash_code_ = hash_code;
- } else {
- string->ComputeHashCode();
- }
- return string;
- }
+ int32_t hash_code = 0);
- static String* AllocFromModifiedUtf8(const char* utf) {
- size_t char_count = CountModifiedUtf8Chars(utf);
- return AllocFromModifiedUtf8(char_count, utf);
- }
+ static String* AllocFromModifiedUtf8(const char* utf);
static String* AllocFromModifiedUtf8(int32_t utf16_length,
- const char* utf8_data_in) {
- String* string = Alloc(GetJavaLangString(), utf16_length);
- uint16_t* utf16_data_out = string->array_->GetData();
- ConvertModifiedUtf8ToUtf16(utf16_data_out, utf8_data_in);
- string->ComputeHashCode();
- return string;
- }
+ const char* utf8_data_in);
- static void SetClass(Class* java_lang_String);
- static void ResetClass();
+ static String* Alloc(Class* java_lang_String, int32_t utf16_length);
- static String* Alloc(Class* java_lang_String, int32_t utf16_length) {
- return Alloc(java_lang_String, CharArray::Alloc(utf16_length));
- }
+ static String* Alloc(Class* java_lang_String, CharArray* array);
- static String* Alloc(Class* java_lang_String, CharArray* array) {
- String* string = down_cast<String*>(java_lang_String->AllocObject());
- string->array_ = array;
- string->count_ = array->GetLength();
- return string;
- }
-
- void ComputeHashCode() {
- hash_code_ = ComputeUtf16Hash(array_->GetData(), count_);
- }
+ bool Equals(const char* modified_utf8) const;
// TODO: do we need this overload? give it a more intention-revealing name.
- bool Equals(const char* modified_utf8) const {
- for (int32_t i = 0; i < GetLength(); ++i) {
- uint16_t ch = GetUtf16FromUtf8(&modified_utf8);
- if (ch == '\0' || ch != CharAt(i)) {
- return false;
- }
- }
- return *modified_utf8 == '\0';
- }
+ bool Equals(const StringPiece& modified_utf8) const;
+
+ bool Equals(const String* that) const;
// TODO: do we need this overload? give it a more intention-revealing name.
- bool Equals(const StringPiece& modified_utf8) const {
- // TODO: do not assume C-string representation.
- return Equals(modified_utf8.data());
+ bool Equals(const uint16_t* that_chars, int32_t that_offset,
+ int32_t that_length) const;
+
+ // Create a modified UTF-8 encoded std::string from a java/lang/String object.
+ std::string ToModifiedUtf8() const;
+
+ static Class* GetJavaLangString() {
+ DCHECK(java_lang_String_ != NULL);
+ return java_lang_String_;
}
- bool Equals(const String* that) const {
- // TODO: short circuit on hash_code_
- if (this->GetLength() != that->GetLength()) {
- return false;
- }
- for (int32_t i = 0; i < that->GetLength(); ++i) {
- if (this->CharAt(i) != that->CharAt(i)) {
- return false;
- }
- }
- return true;
+ 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);
}
- // 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 {
- if (this->GetLength() != that_length) {
- return false;
- }
- for (int32_t i = 0; i < that_length; ++i) {
- if (this->CharAt(i) != that_chars[that_offset + i]) {
- return false;
- }
- }
- return true;
+ void SetCount(int32_t new_count) {
+ DCHECK_LE(0, new_count);
+ SetField32(OFFSET_OF_OBJECT_MEMBER(String, count_), new_count, false);
}
- // Create a modified UTF-8 encoded std::string from a java/lang/String object.
- std::string ToModifiedUtf8() const {
- uint16_t* chars = array_->GetData() + offset_;
- size_t byte_count(CountUtf8Bytes(chars, count_));
- std::string result(byte_count, char(0));
- ConvertUtf16ToModifiedUtf8(&result[0], chars, count_);
- return result;
+ 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);
}
- const String* Intern() const;
+ void SetArray(CharArray* new_array) {
+ DCHECK(new_array != NULL);
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(String, array_), new_array, false);
+ }
- private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
CharArray* array_;
@@ -1711,16 +2449,129 @@ class String : public Object {
int32_t count_;
- static Class* GetJavaLangString() {
- DCHECK(java_lang_String_ != NULL);
- return java_lang_String_;
- }
-
static Class* java_lang_String_;
DISALLOW_IMPLICIT_CONSTRUCTORS(String);
};
+inline const String* Field::GetName() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ String* result =
+ GetFieldObject<String*>(OFFSET_OF_OBJECT_MEMBER(Field, name_), false);
+ DCHECK(result != NULL);
+ return result;
+}
+
+inline void Field::SetName(String* new_name) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Field, name_),
+ new_name, false);
+
+}
+
+inline uint32_t Field::GetAccessFlags() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, access_flags_), false);
+}
+
+inline uint32_t Field::GetTypeIdx() const {
+ DCHECK(GetDeclaringClass()->IsIdxLoaded());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Field, type_idx_), false);
+}
+
+inline MemberOffset Field::GetOffset() const {
+ DCHECK(GetDeclaringClass()->IsLinked());
+ return MemberOffset(
+ GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
+}
+
+inline MemberOffset Field::GetOffsetDuringLinking() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return MemberOffset(
+ GetField32(OFFSET_OF_OBJECT_MEMBER(Field, offset_), false));
+}
+
+inline const String* Method::GetName() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ const String* result =
+ GetFieldObject<const String*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, name_), false);
+ DCHECK(result != NULL);
+ return result;
+}
+
+inline void Method::SetName(String* new_name) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, name_),
+ new_name, false);
+
+}
+
+inline const char* Method::GetShorty() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return GetFieldPtr<const char*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, shorty_), false);
+}
+
+inline const String* Method::GetSignature() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ const String* result =
+ GetFieldObject<const String*>(
+ OFFSET_OF_OBJECT_MEMBER(Method, signature_), false);
+ DCHECK(result != NULL);
+ return result;
+}
+
+inline void Method::SetSignature(String* new_signature) {
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Method, signature_),
+ new_signature, 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() || this == String::GetJavaLangString() ||
+ this == Field::GetJavaLangReflectField() ||
+ this == Method::GetJavaLangReflectMethod());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_), false);
+}
+
+inline void Class::SetDescriptor(String* new_descriptor) {
+ DCHECK(new_descriptor != NULL);
+ DCHECK_NE(0, new_descriptor->GetLength());
+ SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Class, descriptor_),
+ new_descriptor, false);
+}
+
+inline uint32_t Method::GetAccessFlags() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, access_flags_), false);
+}
+
+inline uint16_t Method::GetMethodIndex() const {
+ DCHECK(GetDeclaringClass()->IsLinked());
+ return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, method_index_), false);
+}
+
+inline uint16_t Method::NumRegisters() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_registers_), false);
+}
+
+inline uint16_t Method::NumIns() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_ins_), false);
+}
+
+inline uint16_t Method::NumOuts() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return GetField16(OFFSET_OF_OBJECT_MEMBER(Method, num_outs_), false);
+}
+
+inline uint32_t Method::GetProtoIdx() const {
+ DCHECK(GetDeclaringClass()->IsLoaded());
+ return GetField32(OFFSET_OF_OBJECT_MEMBER(Method, proto_idx_), false);
+}
+
+// C++ mirror of java.lang.Throwable
class Throwable : public Object {
private:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
@@ -1733,42 +2584,43 @@ class Throwable : public Object {
DISALLOW_IMPLICIT_CONSTRUCTORS(Throwable);
};
+// C++ mirror of java.lang.StackTraceElement
class StackTraceElement : public Object {
public:
const String* GetDeclaringClass() const {
- return declaring_class_;
+ return GetFieldObject<const String*>(
+ OFFSET_OF_OBJECT_MEMBER(StackTraceElement, declaring_class_), false);
}
const String* GetMethodName() const {
- return method_name_;
+ return GetFieldObject<const String*>(
+ OFFSET_OF_OBJECT_MEMBER(StackTraceElement, method_name_), false);
}
const String* GetFileName() const {
- return file_name_;
+ return GetFieldObject<const String*>(
+ OFFSET_OF_OBJECT_MEMBER(StackTraceElement, file_name_), false);
}
int32_t GetLineNumber() const {
- return line_number_;
+ return GetField32(
+ OFFSET_OF_OBJECT_MEMBER(StackTraceElement, line_number_), false);
}
- static StackTraceElement* Alloc(const String* declaring_class, const String* method_name,
- const String* file_name, int32_t line_number) {
- StackTraceElement* trace = down_cast<StackTraceElement*>(GetStackTraceElement()->AllocObject());
- trace->declaring_class_ = declaring_class;
- trace->method_name_ = method_name;
- trace->file_name_ = file_name;
- trace->line_number_ = line_number;
- return trace;
- }
+ static StackTraceElement* Alloc(const String* declaring_class,
+ const String* method_name,
+ const String* file_name,
+ int32_t line_number);
static void SetClass(Class* java_lang_StackTraceElement);
static void ResetClass();
private:
+ // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
const String* declaring_class_;
- const String* method_name_;
const String* file_name_;
+ const String* method_name_;
int32_t line_number_;
static Class* GetStackTraceElement() {
@@ -1780,33 +2632,6 @@ class StackTraceElement : public Object {
DISALLOW_IMPLICIT_CONSTRUCTORS(StackTraceElement);
};
-inline bool Object::IsString() const {
- // TODO use "klass_ == String::GetJavaLangString()" instead?
- return klass_ == klass_->descriptor_->klass_;
-}
-
-inline size_t Class::GetTypeSize(String* descriptor) {
- switch (descriptor->CharAt(0)) {
- case 'B': return 1; // byte
- case 'C': return 2; // char
- case 'D': return 8; // double
- case 'F': return 4; // float
- case 'I': return 4; // int
- case 'J': return 8; // long
- case 'S': return 2; // short
- case 'Z': return 1; // boolean
- case 'L': return sizeof(Object*);
- case '[': return sizeof(Array*);
- default:
- LOG(ERROR) << "Unknown type " << descriptor;
- return 0;
- }
-}
-
-inline bool Class::IsArrayClass() const {
- return array_rank_ != 0;
-}
-
class InterfaceEntry {
public:
InterfaceEntry() : interface_(NULL), method_index_array_(NULL) {
@@ -1822,17 +2647,23 @@ class InterfaceEntry {
interface_ = interface;
}
+ uint32_t* GetMethodIndexArray() const {
+ return method_index_array_;
+ }
+
+ void SetMethodIndexArray(uint32_t* new_mia) {
+ method_index_array_ = new_mia;
+ }
+
private:
// Points to the interface class.
Class* interface_;
- public: // TODO: private
// Index into array of vtable offsets. This points into the
// ifvi_pool_, which holds the vtables for all interfaces declared by
// this class.
uint32_t* method_index_array_;
- private:
DISALLOW_COPY_AND_ASSIGN(InterfaceEntry);
};
diff --git a/src/object_test.cc b/src/object_test.cc
index f397b2e506..d485c2e59d 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -18,7 +18,7 @@ class ObjectTest : public CommonTest {
void AssertString(int32_t length,
const char* utf8_in,
const char* utf16_expected_le,
- uint32_t hash_expected) {
+ int32_t expected_hash) {
uint16_t utf16_expected[length];
for (int32_t i = 0; i < length; i++) {
uint16_t ch = (((utf16_expected_le[i*2 + 0] & 0xff) << 8) |
@@ -35,7 +35,7 @@ class ObjectTest : public CommonTest {
for (int32_t i = 0; i < length; i++) {
EXPECT_EQ(utf16_expected[i], string->CharAt(i));
}
- EXPECT_EQ(hash_expected, string->GetHashCode());
+ EXPECT_EQ(expected_hash, string->GetHashCode());
}
uint32_t FindTypeIdxByDescriptor(const DexFile& dex_file, const StringPiece& descriptor) {
@@ -317,9 +317,9 @@ TEST_F(ObjectTest, DescriptorCompare) {
TEST_F(ObjectTest, StringHashCode) {
- EXPECT_EQ(0U, String::AllocFromModifiedUtf8("")->GetHashCode());
- EXPECT_EQ(65U, String::AllocFromModifiedUtf8("A")->GetHashCode());
- EXPECT_EQ(64578U, String::AllocFromModifiedUtf8("ABC")->GetHashCode());
+ EXPECT_EQ(0, String::AllocFromModifiedUtf8("")->GetHashCode());
+ EXPECT_EQ(65, String::AllocFromModifiedUtf8("A")->GetHashCode());
+ EXPECT_EQ(64578, String::AllocFromModifiedUtf8("ABC")->GetHashCode());
}
TEST_F(ObjectTest, InstanceOf) {
@@ -420,16 +420,16 @@ TEST_F(ObjectTest, FindInstanceField) {
ASSERT_TRUE(c != NULL);
// Wrong type.
- EXPECT_TRUE(c->FindDeclaredInstanceField("count", "J") == NULL);
- EXPECT_TRUE(c->FindInstanceField("count", "J") == NULL);
+ EXPECT_TRUE(c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("J")) == NULL);
+ EXPECT_TRUE(c->FindInstanceField("count", class_linker_->FindSystemClass("J")) == NULL);
// Wrong name.
- EXPECT_TRUE(c->FindDeclaredInstanceField("Count", "I") == NULL);
- EXPECT_TRUE(c->FindInstanceField("Count", "I") == NULL);
+ EXPECT_TRUE(c->FindDeclaredInstanceField("Count", class_linker_->FindSystemClass("I")) == NULL);
+ EXPECT_TRUE(c->FindInstanceField("Count", class_linker_->FindSystemClass("I")) == NULL);
// Right name and type.
- Field* f1 = c->FindDeclaredInstanceField("count", "I");
- Field* f2 = c->FindInstanceField("count", "I");
+ Field* f1 = c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("I"));
+ Field* f2 = c->FindInstanceField("count", class_linker_->FindSystemClass("I"));
EXPECT_TRUE(f1 != NULL);
EXPECT_TRUE(f2 != NULL);
EXPECT_EQ(f1, f2);
@@ -440,9 +440,9 @@ TEST_F(ObjectTest, FindInstanceField) {
c = class_linker_->FindSystemClass("Ljava/lang/StringBuilder;");
ASSERT_TRUE(c != NULL);
// No StringBuilder.count...
- EXPECT_TRUE(c->FindDeclaredInstanceField("count", "I") == NULL);
+ EXPECT_TRUE(c->FindDeclaredInstanceField("count", class_linker_->FindSystemClass("I")) == NULL);
// ...but there is an AbstractStringBuilder.count.
- EXPECT_TRUE(c->FindInstanceField("count", "I") != NULL);
+ EXPECT_TRUE(c->FindInstanceField("count", class_linker_->FindSystemClass("I")) != NULL);
}
TEST_F(ObjectTest, FindStaticField) {
@@ -452,16 +452,16 @@ TEST_F(ObjectTest, FindStaticField) {
ASSERT_TRUE(c != NULL);
// Wrong type.
- EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
- EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", "I") == NULL);
+ EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("I")) == NULL);
+ EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("I")) == NULL);
// Wrong name.
- EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
- EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == NULL);
+ EXPECT_TRUE(c->FindDeclaredStaticField("cASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;")) == NULL);
+ EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;")) == NULL);
// Right name and type.
- Field* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
- Field* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
+ Field* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;"));
+ Field* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", class_linker_->FindSystemClass("Ljava/util/Comparator;"));
EXPECT_TRUE(f1 != NULL);
EXPECT_TRUE(f2 != NULL);
EXPECT_EQ(f1, f2);
diff --git a/src/runtime.h b/src/runtime.h
index 9bb60d92b8..4ae15bf762 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -57,7 +57,7 @@ class Runtime {
}
private:
- ParsedOptions() {};
+ ParsedOptions() {}
};
// Creates and initializes a new runtime.
diff --git a/src/thread.cc b/src/thread.cc
index f5c1343c4c..7f48fa1637 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -146,7 +146,7 @@ void Mutex::Unlock() {
void Frame::Next() {
byte* next_sp = reinterpret_cast<byte*>(sp_) +
GetMethod()->GetFrameSizeInBytes();
- sp_ = reinterpret_cast<const Method**>(next_sp);
+ sp_ = reinterpret_cast<Method**>(next_sp);
}
uintptr_t Frame::GetPC() const {
@@ -155,10 +155,10 @@ uintptr_t Frame::GetPC() const {
return *reinterpret_cast<uintptr_t*>(pc_addr);
}
-const Method* Frame::NextMethod() const {
+Method* Frame::NextMethod() const {
byte* next_sp = reinterpret_cast<byte*>(sp_) +
GetMethod()->GetFrameSizeInBytes();
- return *reinterpret_cast<const Method**>(next_sp);
+ return *reinterpret_cast<Method**>(next_sp);
}
void* ThreadStart(void *arg) {
@@ -285,8 +285,7 @@ bool Thread::SirtContains(jobject obj) {
}
Object* Thread::DecodeJObject(jobject obj) {
- // TODO: Only allowed to hold Object* when in the runnable state
- // DCHECK(state_ == kRunnable);
+ DCHECK(CanAccessDirectReferences());
if (obj == NULL) {
return NULL;
}
@@ -325,7 +324,7 @@ Object* Thread::DecodeJObject(jobject obj) {
// TODO: make stack indirect reference table lookup more efficient
// Check if this is a local reference in the SIRT
if (SirtContains(obj)) {
- result = *reinterpret_cast<Object**>(obj); // Read from SIRT
+ result = *reinterpret_cast<Object**>(obj); // Read from SIRT
} else if (jni_env_->work_around_app_jni_bugs) {
// Assume an invalid local reference is actually a direct pointer.
result = reinterpret_cast<Object*>(obj);
@@ -363,8 +362,8 @@ class CountStackDepthVisitor : public Thread::StackVisitor {
class BuildStackTraceVisitor : public Thread::StackVisitor {
public:
- BuildStackTraceVisitor(int depth) : count(0) {
- method_trace = Runtime::Current()->GetClassLinker()->AllocObjectArray<const Method>(depth);
+ explicit BuildStackTraceVisitor(int depth) : count(0) {
+ method_trace = Runtime::Current()->GetClassLinker()->AllocObjectArray<Method>(depth);
pc_trace = IntArray::Alloc(depth);
}
@@ -389,7 +388,7 @@ class BuildStackTraceVisitor : public Thread::StackVisitor {
private:
uint32_t count;
- ObjectArray<const Method>* method_trace;
+ ObjectArray<Method>* method_trace;
IntArray* pc_trace;
};
@@ -406,7 +405,7 @@ void Thread::WalkStack(StackVisitor* visitor) {
if (record == NULL) {
break;
}
- frame.SetSP(reinterpret_cast<const art::Method**>(record->last_top_of_managed_stack)); // last_tos should return Frame instead of sp?
+ frame.SetSP(reinterpret_cast<art::Method**>(record->last_top_of_managed_stack)); // last_tos should return Frame instead of sp?
record = record->link;
}
}
@@ -429,13 +428,12 @@ ObjectArray<StackTraceElement>* Thread::AllocStackTrace() {
const Class* klass = method->GetDeclaringClass();
const DexFile& dex_file = class_linker->FindDexFile(klass->GetDexCache());
String* readable_descriptor = String::AllocFromModifiedUtf8(
- PrettyDescriptor(klass->GetDescriptor()).c_str()
- );
+ PrettyDescriptor(klass->GetDescriptor()).c_str());
StackTraceElement* obj =
StackTraceElement::Alloc(readable_descriptor,
method->GetName(),
- String::AllocFromModifiedUtf8(klass->source_file_),
+ String::AllocFromModifiedUtf8(klass->GetSourceFile()),
dex_file.GetLineNumFromPC(method,
method->ToDexPC(build_trace_visitor.GetPC(i))));
java_traces->Set(i, obj);
@@ -451,9 +449,9 @@ void Thread::ThrowNewException(const char* exception_class_descriptor, const cha
va_end(args);
// Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
- CHECK(exception_class_descriptor[0] == 'L');
+ CHECK_EQ('L', exception_class_descriptor[0]);
std::string descriptor(exception_class_descriptor + 1);
- CHECK(descriptor[descriptor.length() - 1] == ';');
+ CHECK_EQ(';', descriptor[descriptor.length() - 1]);
descriptor.erase(descriptor.length() - 1);
JNIEnv* env = GetJniEnv();
@@ -506,7 +504,7 @@ void* Thread::FindExceptionHandlerInMethod(const Method* method,
exception_ = NULL;
intptr_t dex_pc = -1;
- const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
+ const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->GetCodeItemOffset());
DexFile::CatchHandlerIterator iter;
for (iter = dex_file.dexFindCatchHandler(*code_item,
method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
diff --git a/src/thread.h b/src/thread.h
index 6933962764..87cfb6c5d5 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -127,7 +127,7 @@ class Frame {
public:
Frame() : sp_(NULL) {}
- const Method* GetMethod() const {
+ Method* GetMethod() const {
return (sp_ != NULL) ? *sp_ : NULL;
}
@@ -139,22 +139,22 @@ class Frame {
uintptr_t GetPC() const;
- const Method** GetSP() const {
+ Method** GetSP() const {
return sp_;
}
// TODO: this is here for testing, remove when we have exception unit tests
// that use the real stack
- void SetSP(const Method** sp) {
+ void SetSP(Method** sp) {
sp_ = sp;
}
private:
- const Method* NextMethod() const;
+ Method* NextMethod() const;
friend class Thread;
- const Method** sp_;
+ Method** sp_;
};
class Thread {
@@ -221,7 +221,7 @@ class Thread {
class StackVisitor {
public:
- virtual ~StackVisitor() {};
+ virtual ~StackVisitor() {}
virtual bool VisitFrame(const Frame& frame) = 0;
};
@@ -238,6 +238,20 @@ class Thread {
void Dump(std::ostream& os) const;
+ State GetState() const {
+ return state_;
+ }
+
+ State SetState(State new_state) {
+ State old_state = state_;
+ state_ = new_state;
+ return old_state;
+ }
+
+ bool CanAccessDirectReferences() const {
+ return state_ == kRunnable;
+ }
+
uint32_t GetId() const {
return id_;
}
@@ -248,18 +262,30 @@ class Thread {
return handle_;
}
+ // Returns the Method* for the current method.
+ // This is used by the JNI implementation for logging and diagnostic purposes.
+ const Method* GetCurrentMethod() const {
+ return top_of_managed_stack_.GetMethod();
+ }
+
bool IsExceptionPending() const {
return exception_ != NULL;
}
Throwable* GetException() const {
+ DCHECK(CanAccessDirectReferences());
return exception_;
}
- // Returns the Method* for the current method.
- // This is used by the JNI implementation for logging and diagnostic purposes.
- const Method* GetCurrentMethod() const {
- return top_of_managed_stack_.GetMethod();
+ void SetException(Throwable* new_exception) {
+ DCHECK(CanAccessDirectReferences());
+ CHECK(new_exception != NULL);
+ // TODO: CHECK(exception_ == NULL);
+ exception_ = new_exception; // TODO
+ }
+
+ void ClearException() {
+ exception_ = NULL;
}
Frame GetTopOfStack() const {
@@ -269,13 +295,7 @@ class Thread {
// TODO: this is here for testing, remove when we have exception unit tests
// that use the real stack
void SetTopOfStack(void* stack) {
- top_of_managed_stack_.SetSP(reinterpret_cast<const Method**>(stack));
- }
-
- void SetException(Throwable* new_exception) {
- CHECK(new_exception != NULL);
- // TODO: CHECK(exception_ == NULL);
- exception_ = new_exception; // TODO
+ top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(stack));
}
void ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...)
@@ -284,10 +304,6 @@ class Thread {
// This exception is special, because we need to pre-allocate an instance.
void ThrowOutOfMemoryError();
- void ClearException() {
- exception_ = NULL;
- }
-
Frame FindExceptionHandler(void* throw_pc, void** handler_pc);
void* FindExceptionHandlerInMethod(const Method* method,
@@ -321,16 +337,6 @@ class Thread {
static bool Startup();
static void Shutdown();
- State GetState() const {
- return state_;
- }
-
- State SetState(State new_state) {
- State old_state = state_;
- state_ = new_state;
- return old_state;
- }
-
static ThreadOffset SuspendCountOffset() {
return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_));
}
@@ -402,10 +408,12 @@ class Thread {
}
void PopNativeToManagedRecord(const NativeToManagedRecord& record) {
native_to_managed_record_ = record.link;
- top_of_managed_stack_.SetSP( reinterpret_cast<const Method**>(record.last_top_of_managed_stack) );
+ top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(record.last_top_of_managed_stack));
}
const ClassLoader* GetClassLoaderOverride() {
+ // TODO: need to place the class_loader_override_ in a handle
+ // DCHECK(CanAccessDirectReferences());
return class_loader_override_;
}
@@ -432,7 +440,7 @@ class Thread {
}
~Thread();
- friend class Runtime; // For ~Thread.
+ friend class Runtime; // For ~Thread.
void InitCpu();
void InitFunctionPointers();
diff --git a/src/utf.cc b/src/utf.cc
index 9356197d64..31fbe97da0 100644
--- a/src/utf.cc
+++ b/src/utf.cc
@@ -3,6 +3,7 @@
#include "utf.h"
#include "logging.h"
+#include "object.h"
namespace art {
@@ -51,6 +52,15 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t
}
}
+int32_t ComputeUtf16Hash(const CharArray* chars, int32_t offset,
+ size_t char_count) {
+ int32_t hash = 0;
+ for (size_t i = 0; i < char_count; i++) {
+ hash = hash * 31 + chars->Get(offset + i);
+ }
+ return hash;
+}
+
int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count) {
int32_t hash = 0;
while (char_count--) {
@@ -59,6 +69,7 @@ int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count) {
return hash;
}
+
uint16_t GetUtf16FromUtf8(const char** utf8_data_in) {
uint8_t one = *(*utf8_data_in)++;
if ((one & 0x80) == 0) {
diff --git a/src/utf.h b/src/utf.h
index 2c22f8765a..7b9b90e11e 100644
--- a/src/utf.h
+++ b/src/utf.h
@@ -14,6 +14,9 @@
*/
namespace art {
+template<class T> class PrimitiveArray;
+typedef PrimitiveArray<uint16_t> CharArray;
+
/*
* Returns the number of UTF-16 characters in the given modified UTF-8 string.
*/
@@ -41,6 +44,7 @@ void ConvertUtf16ToModifiedUtf8(char* utf8_out, const uint16_t* utf16_in, size_t
/*
* The java.lang.String hashCode() algorithm.
*/
+int32_t ComputeUtf16Hash(const CharArray* chars, int32_t offset, size_t char_count);
int32_t ComputeUtf16Hash(const uint16_t* chars, size_t char_count);
/*