diff options
author | Brian Carlstrom <bdc@google.com> | 2011-07-12 23:42:50 -0700 |
---|---|---|
committer | Brian Carlstrom <bdc@google.com> | 2011-07-13 10:32:00 -0700 |
commit | 934486cf07c578b6494417ca5dcbae89cf04b019 (patch) | |
tree | fce6df4c3daca71151052961ad6191f0b5854ffc | |
parent | b557353b22c728eecbd1c68593b482622c7782a8 (diff) | |
download | art-934486cf07c578b6494417ca5dcbae89cf04b019.zip art-934486cf07c578b6494417ca5dcbae89cf04b019.tar.gz art-934486cf07c578b6494417ca5dcbae89cf04b019.tar.bz2 |
Make ClassLinker set Class::super_class_ plus test and build improvements
Create placeholder ClassLinker::java_lang_Object_ for use a
super-class of java_lang_Class_ instances.
src/class_linker.cc
src/class_linker.h
Expand ClassLinker FindClass test to verify Class::GetSuperClass
src/class_linker_test.cc
Move DexFile::Load* methods to ClassLinker so they can reference
java_lang_Object_ and java_lang_Class_
src/class_linker.cc
src/class_linker.h
src/dex_file.cc
src/dex_file.h
Move corresponding Load tests from class_linker_test to dex_file_test
src/class_linker_test.cc
src/dex_file_test.cc
Tracking change to object_test to use ClassLinker::Load* methods
src/object_test.cc
Move base64 to new src/common_test.h for reuse accross tests. Add
missing example source for MyClass dex.
src/common_test.h
src/class_linker_test.cc
src/dex_file_test.cc
src/object_test.cc
Change Heap::AllocClass to take DexFile argument
src/heap.h
Remove Method::dex_file_ in favor of using Method::GetClass::GetDexFile
src/object.cc
src/object.h
Made a few more RawDexFile methods const
src/raw_dex_file.cc
src/raw_dex_file.h
Add convenience targets for build-art and test-art-host
Android.mk
Drop use of _LOCAL_ from make variants, which isn't the appropriate
here, where we aren't differentiating between LOCAL_ and PRIVATE_.
Avoid redefinition of variables based on now removed
LIBART_TARGET_ARCH and TEST_TARGET_ARCH to support phony targets in
Android.mk
build/Android.aexec.host.mk
build/Android.aexec.mk
build/Android.common.mk
build/Android.libart.host.mk
build/Android.libart.mk
build/Android.test.host.mk
build/Android.test.mk
Change-Id: I84ce2b7a2b4e37799d4d782b97c02d5e97ac081c
-rw-r--r-- | Android.mk | 15 | ||||
-rw-r--r-- | build/Android.aexec.host.mk | 2 | ||||
-rw-r--r-- | build/Android.aexec.mk | 2 | ||||
-rw-r--r-- | build/Android.common.mk | 26 | ||||
-rw-r--r-- | build/Android.libart.host.mk | 3 | ||||
-rw-r--r-- | build/Android.libart.mk | 3 | ||||
-rw-r--r-- | build/Android.test.host.mk | 3 | ||||
-rw-r--r-- | build/Android.test.mk | 3 | ||||
-rw-r--r-- | src/class_linker.cc | 178 | ||||
-rw-r--r-- | src/class_linker.h | 11 | ||||
-rw-r--r-- | src/class_linker_test.cc | 90 | ||||
-rw-r--r-- | src/common_test.h | 89 | ||||
-rw-r--r-- | src/dex_file.cc | 143 | ||||
-rw-r--r-- | src/dex_file.h | 10 | ||||
-rw-r--r-- | src/dex_file_test.cc | 47 | ||||
-rw-r--r-- | src/heap.h | 6 | ||||
-rw-r--r-- | src/object.cc | 8 | ||||
-rw-r--r-- | src/object.h | 6 | ||||
-rw-r--r-- | src/object_test.cc | 73 | ||||
-rw-r--r-- | src/raw_dex_file.cc | 6 | ||||
-rw-r--r-- | src/raw_dex_file.h | 8 | ||||
-rw-r--r-- | src/raw_dex_file_test.cc | 24 |
22 files changed, 412 insertions, 344 deletions
@@ -27,3 +27,18 @@ ifeq ($(WITH_HOST_DALVIK),true) include $(build_path)/Android.test.host.mk include $(build_path)/Android.aexec.host.mk endif + + +# "m build-art" for quick minimal build +.PHONY: build-art +build-art: \ + $(TARGET_OUT_EXECUTABLES)/aexec \ + $(foreach file,$(TEST_TARGET_SRC_FILES),$(TARGET_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%))) \ + $(HOST_OUT_EXECUTABLES)/aexec \ + $(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%))) \ +# + +# "mm test-art-host" to build and run all host tests +.PHONY: test-art-host +test-art-host: $(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%))) + $(foreach file,$(TEST_HOST_SRC_FILES),$(HOST_OUT_EXECUTABLES)/$(notdir $(file:%.cc=%)) &&) true diff --git a/build/Android.aexec.host.mk b/build/Android.aexec.host.mk index a4d072e..6efc9e9 100644 --- a/build/Android.aexec.host.mk +++ b/build/Android.aexec.host.mk @@ -20,7 +20,7 @@ LOCAL_MODULE := aexec LOCAL_MODULE_TAGS := optional include $(build_path)/Android.common.mk -LOCAL_SRC_FILES := $(AEXEC_LOCAL_SRC_FILES) +LOCAL_SRC_FILES := $(AEXEC_SRC_FILES) LOCAL_C_INCLUDES := diff --git a/build/Android.aexec.mk b/build/Android.aexec.mk index 2268cbf..411128e 100644 --- a/build/Android.aexec.mk +++ b/build/Android.aexec.mk @@ -20,7 +20,7 @@ LOCAL_MODULE := aexec LOCAL_MODULE_TAGS := optional include $(build_path)/Android.common.mk -LOCAL_SRC_FILES := $(AEXEC_LOCAL_SRC_FILES) +LOCAL_SRC_FILES := $(AEXEC_SRC_FILES) include external/stlport/libstlport.mk LOCAL_C_INCLUDES += diff --git a/build/Android.common.mk b/build/Android.common.mk index 30a63ca..bf442a3 100644 --- a/build/Android.common.mk +++ b/build/Android.common.mk @@ -35,10 +35,10 @@ ifeq ($(TARGET_ARCH),x86) LOCAL_CFLAGS += endif -AEXEC_LOCAL_SRC_FILES := \ +AEXEC_SRC_FILES := \ src/main.cc -LIBART_LOCAL_SRC_FILES := \ +LIBART_COMMON_SRC_FILES := \ src/assembler.cc \ src/base64.cc \ src/class_linker.cc \ @@ -52,28 +52,24 @@ LIBART_LOCAL_SRC_FILES := \ src/stringpiece.cc \ src/thread.cc -ifeq ($(LIBART_TARGET_ARCH),arm) -LIBART_LOCAL_SRC_FILES += \ +LIBART_TARGET_SRC_FILES := \ + $(LIBART_COMMON_SRC_FILES) \ src/assembler_arm.cc -endif -ifeq ($(LIBART_TARGET_ARCH),x86) -LIBART_LOCAL_SRC_FILES += \ +LIBART_HOST_SRC_FILES := \ + $(LIBART_COMMON_SRC_FILES) \ src/assembler_x86.cc -endif -TEST_LOCAL_SRC_FILES := \ +TEST_COMMON_SRC_FILES := \ src/class_linker_test.cc \ src/dex_file_test.cc \ src/dex_instruction_visitor_test.cc \ src/object_test.cc \ src/raw_dex_file_test.cc -ifeq ($(TEST_TARGET_ARCH),arm) -TEST_LOCAL_SRC_FILES += -endif +TEST_TARGET_SRC_FILES := \ + $(TEST_COMMON_SRC_FILES) -ifeq ($(TEST_TARGET_ARCH),x86) -TEST_LOCAL_SRC_FILES += \ +TEST_HOST_SRC_FILES := \ + $(TEST_COMMON_SRC_FILES) \ src/assembler_x86_test.cc -endif diff --git a/build/Android.libart.host.mk b/build/Android.libart.host.mk index cd13677..1612bf8 100644 --- a/build/Android.libart.host.mk +++ b/build/Android.libart.host.mk @@ -19,9 +19,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := libart LOCAL_MODULE_TAGS := optional -LIBART_TARGET_ARCH := $(HOST_ARCH) include $(build_path)/Android.common.mk -LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES) +LOCAL_SRC_FILES := $(LIBART_HOST_SRC_FILES) LOCAL_WHOLE_STATIC_LIBRARIES := \ libcutils \ diff --git a/build/Android.libart.mk b/build/Android.libart.mk index 404f0c6..e9dcfb6 100644 --- a/build/Android.libart.mk +++ b/build/Android.libart.mk @@ -19,9 +19,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := libart LOCAL_MODULE_TAGS := optional -LIBART_TARGET_ARCH := $(TARGET_ARCH) include $(build_path)/Android.common.mk -LOCAL_SRC_FILES := $(LIBART_LOCAL_SRC_FILES) +LOCAL_SRC_FILES := $(LIBART_TARGET_SRC_FILES) include external/stlport/libstlport.mk diff --git a/build/Android.test.host.mk b/build/Android.test.host.mk index 5c32a04..23346d9 100644 --- a/build/Android.test.host.mk +++ b/build/Android.test.host.mk @@ -18,7 +18,6 @@ include $(CLEAR_VARS) local_module_tags := tests -TEST_TARGET_ARCH := $(HOST_ARCH) include $(build_path)/Android.common.mk local_cpp_extension := $(LOCAL_CPP_EXTENSION) local_cflags := $(LOCAL_CFLAGS) @@ -33,7 +32,7 @@ local_whole_static_libraries := \ libgtest_host \ libgtest_main_host -$(foreach file,$(TEST_LOCAL_SRC_FILES), \ +$(foreach file,$(TEST_HOST_SRC_FILES), \ $(eval include $(CLEAR_VARS)) \ $(eval LOCAL_CPP_EXTENSION := $(local_cpp_extension)) \ $(eval LOCAL_MODULE := $(notdir $(file:%.cc=%))) \ diff --git a/build/Android.test.mk b/build/Android.test.mk index fc3917c..7d7b2ce 100644 --- a/build/Android.test.mk +++ b/build/Android.test.mk @@ -18,7 +18,6 @@ include $(CLEAR_VARS) local_module_tags := tests -TEST_TARGET_ARCH := $(TARGET_ARCH) include $(build_path)/Android.common.mk local_cpp_extension := $(LOCAL_CPP_EXTENSION) local_cflags := $(LOCAL_CFLAGS) @@ -34,7 +33,7 @@ local_static_libraries := \ libgtest \ libgtest_main -$(foreach file,$(TEST_LOCAL_SRC_FILES), \ +$(foreach file,$(TEST_TARGET_SRC_FILES), \ $(eval include $(CLEAR_VARS)) \ $(eval LOCAL_CPP_EXTENSION := $(local_cpp_extension)) \ $(eval LOCAL_MODULE := $(notdir $(file:%.cc=%))) \ diff --git a/src/class_linker.cc b/src/class_linker.cc index cf72a11..5b50113 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -20,10 +20,11 @@ namespace art { void ClassLinker::Init() { - // Allocate and partially initialize the class Class. This object - // will complete its initialization when its definition is loaded. - java_lang_Class_ = Heap::AllocClass(); - java_lang_Class_->super_class_ = java_lang_Class_; + // Allocate and partially initialize the Object and Class classes. + // Initialization will be completed when the definitions are loaded. + java_lang_Object_ = Heap::AllocClass(NULL); + java_lang_Object_->descriptor_ = "Ljava/lang/Object;"; + java_lang_Class_ = Heap::AllocClass(NULL); java_lang_Class_->descriptor_ = "Ljava/lang/Class;"; // Allocate and initialize the primitive type classes. @@ -56,12 +57,16 @@ Class* ClassLinker::FindClass(const char* descriptor, } } // Load the class from the dex file. - if (!strcmp(descriptor, "Ljava/lang/Class;")) { + if (!strcmp(descriptor, "Ljava/lang/Object;")) { + klass = java_lang_Object_; + klass->dex_file_ = dex_file; + } else if (!strcmp(descriptor, "Ljava/lang/Class;")) { klass = java_lang_Class_; + klass->dex_file_ = dex_file; } else { - klass = Heap::AllocClass(); + klass = Heap::AllocClass(dex_file); } - bool is_loaded = dex_file->LoadClass(descriptor, klass); + bool is_loaded = LoadClass(descriptor, klass); if (!is_loaded) { // TODO: this occurs only when a dex file is provided. LG << "Class not found"; // TODO: NoClassDefFoundError @@ -116,6 +121,153 @@ Class* ClassLinker::FindClass(const char* descriptor, return klass; } +bool ClassLinker::LoadClass(const char* descriptor, Class* klass) { + const RawDexFile* raw = klass->GetDexFile()->GetRaw(); + const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor); + if (class_def == NULL) { + return false; + } else { + return LoadClass(*class_def, klass); + } +} + +bool ClassLinker::LoadClass(const RawDexFile::ClassDef& class_def, Class* klass) { + CHECK(klass != NULL); + CHECK(klass->dex_file_ != NULL); + const RawDexFile* raw = klass->GetDexFile()->GetRaw(); + const byte* class_data = raw->GetClassData(class_def); + RawDexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data); + + const char* descriptor = raw->GetClassDescriptor(class_def); + CHECK(descriptor != NULL); + + klass->klass_ = java_lang_Class_; + klass->descriptor_.set(descriptor); + klass->descriptor_alloc_ = NULL; + klass->access_flags_ = class_def.access_flags_; + klass->class_loader_ = NULL; // TODO + klass->primitive_type_ = Class::kPrimNot; + klass->status_ = Class::kStatusIdx; + + klass->super_class_ = NULL; + klass->super_class_idx_ = class_def.superclass_idx_; + + klass->num_sfields_ = header.static_fields_size_; + klass->num_ifields_ = header.instance_fields_size_; + klass->num_direct_methods_ = header.direct_methods_size_; + klass->num_virtual_methods_ = header.virtual_methods_size_; + + klass->source_file_ = raw->dexGetSourceFile(class_def); + + // Load class interfaces. + LoadInterfaces(class_def, klass); + + // Load static fields. + if (klass->num_sfields_ != 0) { + // TODO: allocate on the object heap. + klass->sfields_ = new StaticField[klass->NumStaticFields()](); + uint32_t last_idx = 0; + for (size_t i = 0; i < klass->num_sfields_; ++i) { + RawDexFile::Field raw_field; + raw->dexReadClassDataField(&class_data, &raw_field, &last_idx); + LoadField(klass, raw_field, &klass->sfields_[i]); + } + } + + // Load instance fields. + if (klass->NumInstanceFields() != 0) { + // TODO: allocate on the object heap. + klass->ifields_ = new InstanceField[klass->NumInstanceFields()](); + uint32_t last_idx = 0; + for (size_t i = 0; i < klass->NumInstanceFields(); ++i) { + RawDexFile::Field raw_field; + raw->dexReadClassDataField(&class_data, &raw_field, &last_idx); + LoadField(klass, raw_field, klass->GetInstanceField(i)); + } + } + + // Load direct methods. + if (klass->NumDirectMethods() != 0) { + // TODO: append direct methods to class object + klass->direct_methods_ = new Method[klass->NumDirectMethods()](); + uint32_t last_idx = 0; + for (size_t i = 0; i < klass->NumDirectMethods(); ++i) { + RawDexFile::Method raw_method; + raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx); + LoadMethod(klass, raw_method, klass->GetDirectMethod(i)); + // TODO: register maps + } + } + + // Load virtual methods. + if (klass->NumVirtualMethods() != 0) { + // TODO: append virtual methods to class object + klass->virtual_methods_ = new Method[klass->NumVirtualMethods()](); + uint32_t last_idx = 0; + for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) { + RawDexFile::Method raw_method; + raw->dexReadClassDataMethod(&class_data, &raw_method, &last_idx); + LoadMethod(klass, raw_method, klass->GetVirtualMethod(i)); + // TODO: register maps + } + } + + return klass; +} + +void ClassLinker::LoadInterfaces(const RawDexFile::ClassDef& class_def, + Class* klass) { + const RawDexFile* raw = klass->GetDexFile()->GetRaw(); + const RawDexFile::TypeList* list = raw->GetInterfacesList(class_def); + if (list != NULL) { + klass->interface_count_ = list->Size(); + // TODO: allocate the interfaces array on the object heap. + klass->interfaces_ = new Class*[list->Size()](); + for (size_t i = 0; i < list->Size(); ++i) { + const RawDexFile::TypeItem& type_item = list->GetTypeItem(i); + klass->interfaces_[i] = reinterpret_cast<Class*>(type_item.type_idx_); + } + } +} + +void ClassLinker::LoadField(Class* klass, const RawDexFile::Field& src, + Field* dst) { + const RawDexFile* raw = klass->GetDexFile()->GetRaw(); + const RawDexFile::FieldId& field_id = raw->GetFieldId(src.field_idx_); + dst->klass_ = klass; + dst->name_ = raw->dexStringById(field_id.name_idx_); + dst->signature_ = raw->dexStringByTypeIdx(field_id.type_idx_); + dst->access_flags_ = src.access_flags_; +} + +void ClassLinker::LoadMethod(Class* klass, const RawDexFile::Method& src, + Method* dst) { + const RawDexFile* raw = klass->GetDexFile()->GetRaw(); + const RawDexFile::MethodId& method_id = raw->GetMethodId(src.method_idx_); + dst->klass_ = klass; + dst->name_.set(raw->dexStringById(method_id.name_idx_)); + dst->proto_idx_ = method_id.proto_idx_; + dst->shorty_.set(raw->GetShorty(method_id.proto_idx_)); + dst->access_flags_ = src.access_flags_; + + // TODO: check for finalize method + + const RawDexFile::CodeItem* code_item = raw->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->insns_ = code_item->insns_; + } else { + uint16_t num_args = dst->NumArgRegisters(); + if (!dst->IsStatic()) { + ++num_args; + } + dst->num_registers_ = dst->num_ins_ + num_args; + // TODO: native methods + } +} + DexFile* ClassLinker::FindInClassPath(const char* descriptor) { for (size_t i = 0; i != class_path_.size(); ++i) { DexFile* dex_file = class_path_[i]; @@ -131,7 +283,7 @@ void ClassLinker::AppendToClassPath(DexFile* dex_file) { } Class* ClassLinker::CreatePrimitiveClass(JType type, const char* descriptor) { - Class* klass = Heap::AllocClass(); + Class* klass = Heap::AllocClass(NULL); CHECK(klass != NULL); klass->super_class_ = java_lang_Class_; klass->access_flags_ = kAccPublic | kAccFinal | kAccAbstract; @@ -348,8 +500,8 @@ bool ClassLinker::ValidateSuperClassDescriptors(const Class* klass) { } bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method, - const Class* klass1, - const Class* klass2) { + const Class* klass1, + const Class* klass2) { const RawDexFile* raw = method->GetClass()->GetDexFile()->GetRaw(); const RawDexFile::ProtoId& proto_id = raw->GetProtoId(method->proto_idx_); RawDexFile::ParameterIterator *it; @@ -378,8 +530,8 @@ bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method, // Returns true if classes referenced by the descriptor are the // same classes in klass1 as they are in klass2. bool ClassLinker::HasSameDescriptorClasses(const char* descriptor, - const Class* klass1, - const Class* klass2) { + const Class* klass1, + const Class* klass2) { CHECK(descriptor != NULL); CHECK(klass1 != NULL); CHECK(klass2 != NULL); @@ -432,7 +584,7 @@ void ClassLinker::InitializeStaticFields(Class* klass) { return; } const char* descriptor = klass->GetDescriptor().data(); - RawDexFile* raw = dex_file->GetRaw(); + const RawDexFile* raw = dex_file->GetRaw(); const RawDexFile::ClassDef* class_def = raw->FindClassDef(descriptor); CHECK(class_def != NULL); const byte* addr = raw->GetEncodedArray(*class_def); diff --git a/src/class_linker.h b/src/class_linker.h index 89fd8f7..3796dc2 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -30,6 +30,10 @@ class ClassLinker { return FindClass(descriptor, NULL, NULL); } + bool LoadClass(const char* descriptor, Class* klass); + + bool LoadClass(const RawDexFile::ClassDef& class_def, Class* klass); + Class* FindPrimitiveClass(JType type); bool InitializeClass(Class* klass); @@ -47,6 +51,12 @@ class ClassLinker { private: Class* CreatePrimitiveClass(JType type, const char* descriptor); + void LoadInterfaces(const RawDexFile::ClassDef& class_def, Class *klass); + + void LoadField(Class* klass, const RawDexFile::Field& src, Field* dst); + + void LoadMethod(Class* klass, const RawDexFile::Method& src, Method* dst); + // Inserts a class into the class table. Returns true if the class // was inserted. bool InsertClass(Class* klass); @@ -104,6 +114,7 @@ class ClassLinker { Class* primitive_long_; Class* primitive_void_; + Class* java_lang_Object_; Class* java_lang_Class_; DISALLOW_COPY_AND_ASSIGN(ClassLinker); diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc index 7bb9ecb..5cd8a6f 100644 --- a/src/class_linker_test.cc +++ b/src/class_linker_test.cc @@ -1,31 +1,95 @@ // Copyright 2011 Google Inc. All Rights Reserved. +#include "src/common_test.h" #include "src/class_linker.h" #include "src/dex_file.h" +#include "src/heap.h" #include "gtest/gtest.h" namespace art { -static const char kMyClassDex[] = -"ZGV4CjAzNQDyNgSqujckc8oAvOKGLvz3+wrLfW9ED5AIAgAAcAAAAHhWNBIAAAAAAAAAAIABAAAG" -"AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAIAAACgAAAAAgAAALAAAAAYAQAA8AAAABwB" -"AAAkAQAALwEAAEMBAABRAQAAXgEAAAEAAAACAAAABQAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAQAA" -"AAAAAAABAAAAAQAAAP////8AAAAABAAAAAAAAABrAQAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAA" -"AAAAAHUBAAAAAAAAAQABAAAAAABhAQAAAQAAAA4AAAABAAEAAQAAAGYBAAAEAAAAcBABAAAADgAG" -"PGluaXQ+AAlMTXlDbGFzczsAEkxqYXZhL2xhbmcvT2JqZWN0OwAMTXlDbGFzcy5qYXZhAAtPYmpl" -"Y3QuamF2YQABVgADAAcOAAEABw4AAAABAAGBgATwAQAAAQAAgIAEhAIACwAAAAAAAAABAAAAAAAA" -"AAEAAAAGAAAAcAAAAAIAAAADAAAAiAAAAAMAAAABAAAAlAAAAAUAAAACAAAAoAAAAAYAAAACAAAA" -"sAAAAAEgAAACAAAA8AAAAAIgAAAGAAAAHAEAAAMgAAACAAAAYQEAAAAgAAACAAAAawEAAAAQAAAB" -"AAAAgAEAAA=="; +TEST(ClassLinker, LoadNonexistent) { + scoped_ptr<DexFile> dex(DexFile::OpenBase64(kMyClassDex)); + ASSERT_TRUE(dex != NULL); + + ClassLinker linker; + linker.Init(); + linker.AppendToClassPath(dex.get()); + + scoped_ptr<Class> klass(Heap::AllocClass(dex.get())); + bool result1 = linker.LoadClass("NoSuchClass", klass.get()); + EXPECT_FALSE(result1); + bool result2 = linker.LoadClass("LNoSuchClass;", klass.get()); + EXPECT_FALSE(result2); +} + +TEST(ClassLinker, Load) { + scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex)); + ASSERT_TRUE(dex != NULL); + + ClassLinker linker; + linker.Init(); + linker.AppendToClassPath(dex.get()); + + scoped_ptr<Class> klass(Heap::AllocClass(dex.get())); + bool result = linker.LoadClass("LNested;", klass.get()); + ASSERT_TRUE(result); + + uint32_t vmeth = klass->NumVirtualMethods(); + EXPECT_EQ(vmeth, 0U); + + uint32_t dmeth = klass->NumDirectMethods(); + EXPECT_EQ(dmeth, 1U); +} TEST(ClassLinker, FindClass) { scoped_ptr<DexFile> dex(DexFile::OpenBase64(kMyClassDex)); ASSERT_TRUE(dex != NULL); ClassLinker linker; + linker.Init(); linker.AppendToClassPath(dex.get()); - Class* klass = linker.FindClass("LMyClass;", NULL, dex.get()); - EXPECT_TRUE(klass != NULL); + + Class* JavaLangObject = linker.FindClass("Ljava/lang/Object;", NULL, dex.get()); + ASSERT_TRUE(JavaLangObject != NULL); + EXPECT_TRUE(JavaLangObject->GetClass() != NULL); + ASSERT_TRUE(JavaLangObject->GetDescriptor() == "Ljava/lang/Object;"); + EXPECT_TRUE(JavaLangObject->GetSuperClass() == NULL); + EXPECT_FALSE(JavaLangObject->HasSuperClass()); + EXPECT_TRUE(JavaLangObject->GetComponentType() == NULL); + EXPECT_FALSE(JavaLangObject->IsErroneous()); + EXPECT_FALSE(JavaLangObject->IsVerified()); + EXPECT_TRUE(JavaLangObject->IsLinked()); + EXPECT_FALSE(JavaLangObject->IsArray()); + EXPECT_FALSE(JavaLangObject->IsInterface()); + EXPECT_TRUE(JavaLangObject->IsPublic()); + EXPECT_FALSE(JavaLangObject->IsFinal()); + EXPECT_FALSE(JavaLangObject->IsPrimitive()); + EXPECT_EQ((size_t) 1, JavaLangObject->NumDirectMethods()); + EXPECT_EQ((size_t) 0, JavaLangObject->NumVirtualMethods()); + EXPECT_EQ((size_t) 0, JavaLangObject->NumInstanceFields()); + EXPECT_EQ((size_t) 0, JavaLangObject->NumStaticFields()); + + Class* MyClass = linker.FindClass("LMyClass;", NULL, dex.get()); + ASSERT_TRUE(MyClass != NULL); + EXPECT_TRUE(MyClass->GetClass() != NULL); + ASSERT_TRUE(MyClass->GetDescriptor() == "LMyClass;"); + EXPECT_TRUE(MyClass->GetSuperClass() == JavaLangObject); + EXPECT_TRUE(MyClass->HasSuperClass()); + 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->IsArray()); + EXPECT_FALSE(MyClass->IsInterface()); + EXPECT_FALSE(MyClass->IsPublic()); + EXPECT_FALSE(MyClass->IsFinal()); + EXPECT_FALSE(MyClass->IsPrimitive()); + EXPECT_EQ((size_t) 1, MyClass->NumDirectMethods()); + EXPECT_EQ((size_t) 0, MyClass->NumVirtualMethods()); + EXPECT_EQ((size_t) 0, MyClass->NumInstanceFields()); + EXPECT_EQ((size_t) 0, MyClass->NumStaticFields()); } } // namespace art diff --git a/src/common_test.h b/src/common_test.h new file mode 100644 index 0000000..9747261 --- /dev/null +++ b/src/common_test.h @@ -0,0 +1,89 @@ +// Copyright 2011 Google Inc. All Rights Reserved. + +namespace art { + +// package java.lang; +// public class Object {} +// +// class MyClass {} +static const char kMyClassDex[] = + "ZGV4CjAzNQA5Nm9IrCVm91COwepff7LhIE23GZIxGjgIAgAAcAAAAHhWNBIAAAAAAAAAAIABAAAG" + "AAAAcAAAAAMAAACIAAAAAQAAAJQAAAAAAAAAAAAAAAIAAACgAAAAAgAAALAAAAAYAQAA8AAAABwB" + "AAAkAQAALwEAAEMBAABRAQAAXgEAAAEAAAACAAAABQAAAAUAAAACAAAAAAAAAAAAAAAAAAAAAQAA" + "AAAAAAABAAAAAQAAAP////8AAAAABAAAAAAAAABrAQAAAAAAAAAAAAAAAAAAAQAAAAAAAAADAAAA" + "AAAAAHUBAAAAAAAAAQABAAAAAABhAQAAAQAAAA4AAAABAAEAAQAAAGYBAAAEAAAAcBABAAAADgAG" + "PGluaXQ+AAlMTXlDbGFzczsAEkxqYXZhL2xhbmcvT2JqZWN0OwAMTXlDbGFzcy5qYXZhAAtPYmpl" + "Y3QuamF2YQABVgACAAcOAAUABw4AAAABAAGBgATwAQAAAQAAgIAEhAIACwAAAAAAAAABAAAAAAAA" + "AAEAAAAGAAAAcAAAAAIAAAADAAAAiAAAAAMAAAABAAAAlAAAAAUAAAACAAAAoAAAAAYAAAACAAAA" + "sAAAAAEgAAACAAAA8AAAAAIgAAAGAAAAHAEAAAMgAAACAAAAYQEAAAAgAAACAAAAawEAAAAQAAAB" + "AAAAgAEAAA=="; + +// class Nested { +// class Inner { +// } +// } +static const char kNestedDex[] = + "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP" + "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B" + "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA" + "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA" + "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA" + "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA" + "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA" + "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu" + "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2" + "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz" + "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA" + "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA" + "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH" + "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ" + "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA" + "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA=="; + +// class ProtoCompare { +// int m1(short x, int y, long z) { return x + y + (int)z; } +// int m2(short x, int y, long z) { return x + y + (int)z; } +// int m3(long x, int y, short z) { return (int)x + y + z; } +// long m4(long x, int y, short z) { return x + y + z; } +// } +static const char kProtoCompareDex[] = + "ZGV4CjAzNQBLUetu+TVZ8gsYsCOFoij7ecsHaGSEGA8gAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP" + "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B" + "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAOAgAAIgIAADUCAAA4AgAAOwIAAD8CAABDAgAARwIA" + "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA" + "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD" + "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHACAAAAAAAAAQABAAEAAABLAgAABAAAAHAQ" + "BQAAAA4ABwAFAAAAAABQAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWAIAAAUAAACQAAMEhFGw" + "EA8AAAAGAAUAAAAAAGACAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGgCAAAFAAAAgXC7UIGCuyAQAAAA" + "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMADkxQ" + "cm90b0NvbXBhcmU7ABJMamF2YS9sYW5nL09iamVjdDsAEVByb3RvQ29tcGFyZS5qYXZhAAFTAAFW" + "AAJtMQACbTIAAm0zAAJtNAABAAcOAAIDAAAABw4AAwMAAAAHDgAEAwAAAAcOAAUDAAAABw4AAAAB" + "BACAgATEAgEA3AIBAPgCAQCUAwEArAMAAAwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA" + "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB" + "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAEsCAAAAIAAAAQAAAHACAAAAEAAAAQAAAIwC" + "AAA="; + +// class ProtoCompare2 { +// int m1(short x, int y, long z) { return x + y + (int)z; } +// int m2(short x, int y, long z) { return x + y + (int)z; } +// int m3(long x, int y, short z) { return (int)x + y + z; } +// long m4(long x, int y, short z) { return x + y + z; } +// } +static const char kProtoCompare2Dex[] = + "ZGV4CjAzNQDVUXj687EpyTTDJZEZPA8dEYnDlm0Ir6YgAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP" + "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B" + "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAPAgAAIwIAADcCAAA6AgAAPQIAAEECAABFAgAASQIA" + "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA" + "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD" + "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHICAAAAAAAAAQABAAEAAABNAgAABAAAAHAQ" + "BQAAAA4ABwAFAAAAAABSAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWgIAAAUAAACQAAMEhFGw" + "EA8AAAAGAAUAAAAAAGICAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGoCAAAFAAAAgXC7UIGCuyAQAAAA" + "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMAD0xQ" + "cm90b0NvbXBhcmUyOwASTGphdmEvbGFuZy9PYmplY3Q7ABJQcm90b0NvbXBhcmUyLmphdmEAAVMA" + "AVYAAm0xAAJtMgACbTMAAm00AAEABw4AAgMAAAAHDgADAwAAAAcOAAQDAAAABw4ABQMAAAAHDgAA" + "AAEEAICABMQCAQDcAgEA+AIBAJQDAQCsAwwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA" + "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB" + "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAE0CAAAAIAAAAQAAAHICAAAAEAAAAQAAAIwC" + "AAA="; + +} // namespace art diff --git a/src/dex_file.cc b/src/dex_file.cc index c9604a1..5b39bfc 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -49,147 +49,4 @@ void DexFile::Init() { fields_ = new Field*[num_fields_](); } -bool DexFile::LoadClass(const char* descriptor, Class* klass) { - const RawDexFile::ClassDef* class_def = raw_->FindClassDef(descriptor); - if (class_def == NULL) { - return false; - } else { - return LoadClass(*class_def, klass); - } -} - -bool DexFile::LoadClass(const RawDexFile::ClassDef& class_def, Class* klass) { - CHECK(klass != NULL); - const byte* class_data = raw_->GetClassData(class_def); - RawDexFile::ClassDataHeader header = raw_->ReadClassDataHeader(&class_data); - - const char* descriptor = raw_->GetClassDescriptor(class_def); - CHECK(descriptor != NULL); - - klass->klass_ = NULL; // TODO - klass->descriptor_.set(descriptor); - klass->descriptor_alloc_ = NULL; - klass->access_flags_ = class_def.access_flags_; - klass->class_loader_ = NULL; // TODO - klass->dex_file_ = this; - klass->primitive_type_ = Class::kPrimNot; - klass->status_ = Class::kStatusIdx; - - klass->super_class_ = NULL; - klass->super_class_idx_ = class_def.superclass_idx_; - - klass->num_sfields_ = header.static_fields_size_; - klass->num_ifields_ = header.instance_fields_size_; - klass->num_direct_methods_ = header.direct_methods_size_; - klass->num_virtual_methods_ = header.virtual_methods_size_; - - klass->source_file_ = raw_->dexGetSourceFile(class_def); - - // Load class interfaces. - LoadInterfaces(class_def, klass); - - // Load static fields. - if (klass->num_sfields_ != 0) { - // TODO: allocate on the object heap. - klass->sfields_ = new StaticField[klass->NumStaticFields()](); - uint32_t last_idx = 0; - for (size_t i = 0; i < klass->num_sfields_; ++i) { - RawDexFile::Field raw_field; - raw_->dexReadClassDataField(&class_data, &raw_field, &last_idx); - LoadField(klass, raw_field, &klass->sfields_[i]); - } - } - - // Load instance fields. - if (klass->NumInstanceFields() != 0) { - // TODO: allocate on the object heap. - klass->ifields_ = new InstanceField[klass->NumInstanceFields()](); - uint32_t last_idx = 0; - for (size_t i = 0; i < klass->NumInstanceFields(); ++i) { - RawDexFile::Field raw_field; - raw_->dexReadClassDataField(&class_data, &raw_field, &last_idx); - LoadField(klass, raw_field, klass->GetInstanceField(i)); - } - } - - // Load direct methods. - if (klass->NumDirectMethods() != 0) { - // TODO: append direct methods to class object - klass->direct_methods_ = new Method[klass->NumDirectMethods()](); - uint32_t last_idx = 0; - for (size_t i = 0; i < klass->NumDirectMethods(); ++i) { - RawDexFile::Method raw_method; - raw_->dexReadClassDataMethod(&class_data, &raw_method, &last_idx); - LoadMethod(klass, raw_method, klass->GetDirectMethod(i)); - // TODO: register maps - } - } - - // Load virtual methods. - if (klass->NumVirtualMethods() != 0) { - // TODO: append virtual methods to class object - klass->virtual_methods_ = new Method[klass->NumVirtualMethods()](); - uint32_t last_idx = 0; - for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) { - RawDexFile::Method raw_method; - raw_->dexReadClassDataMethod(&class_data, &raw_method, &last_idx); - LoadMethod(klass, raw_method, klass->GetVirtualMethod(i)); - // TODO: register maps - } - } - - return klass; -} - -void DexFile::LoadInterfaces(const RawDexFile::ClassDef& class_def, - Class* klass) { - const RawDexFile::TypeList* list = raw_->GetInterfacesList(class_def); - if (list != NULL) { - klass->interface_count_ = list->Size(); - // TODO: allocate the interfaces array on the object heap. - klass->interfaces_ = new Class*[list->Size()](); - for (size_t i = 0; i < list->Size(); ++i) { - const RawDexFile::TypeItem& type_item = list->GetTypeItem(i); - klass->interfaces_[i] = reinterpret_cast<Class*>(type_item.type_idx_); - } - } -} - -void DexFile::LoadField(Class* klass, const RawDexFile::Field& src, - Field* dst) { - const RawDexFile::FieldId& field_id = raw_->GetFieldId(src.field_idx_); - dst->klass_ = klass; - dst->name_ = raw_->dexStringById(field_id.name_idx_); - dst->signature_ = raw_->dexStringByTypeIdx(field_id.type_idx_); - dst->access_flags_ = src.access_flags_; -} - -void DexFile::LoadMethod(Class* klass, const RawDexFile::Method& src, - Method* dst) { - const RawDexFile::MethodId& method_id = raw_->GetMethodId(src.method_idx_); - dst->klass_ = klass; - dst->name_.set(raw_->dexStringById(method_id.name_idx_)); - dst->dex_file_ = this; - dst->proto_idx_ = method_id.proto_idx_; - dst->shorty_.set(raw_->GetShorty(method_id.proto_idx_)); - dst->access_flags_ = src.access_flags_; - - // TODO: check for finalize method - - const RawDexFile::CodeItem* code_item = raw_->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->insns_ = code_item->insns_; - } else { - uint16_t num_args = dst->NumArgRegisters(); - if (!dst->IsStatic()) { - ++num_args; - } - dst->num_registers_ = dst->num_ins_ + num_args; - // TODO: native methods - } -} - } // namespace art diff --git a/src/dex_file.h b/src/dex_file.h index 8463672..d11b3b5 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -40,10 +40,6 @@ class DexFile { return num_methods_; } - bool LoadClass(const char* descriptor, Class* klass); - - bool LoadClass(const RawDexFile::ClassDef& class_def, Class* klass); - bool HasClass(const char* descriptor) { return raw_->FindClassDef(descriptor) != NULL; } @@ -77,12 +73,6 @@ class DexFile { void Init(); - void LoadInterfaces(const RawDexFile::ClassDef& class_def, Class *klass); - - void LoadField(Class* klass, const RawDexFile::Field& src, Field* dst); - - void LoadMethod(Class* klass, const RawDexFile::Method& src, Method* dst); - // Table of contents for interned String objects. String** strings_; size_t num_strings_; diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc index ccac396..e12f8e2 100644 --- a/src/dex_file_test.cc +++ b/src/dex_file_test.cc @@ -1,5 +1,6 @@ // Copyright 2011 Google Inc. All Rights Reserved. +#include "src/common_test.h" #include "src/dex_file.h" #include "src/object.h" #include "src/scoped_ptr.h" @@ -9,55 +10,9 @@ namespace art { -// class Nested { -// class Inner { -// } -// } -static const char kNestedDex[] = - "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP" - "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B" - "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA" - "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA" - "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA" - "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA" - "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA" - "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu" - "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2" - "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz" - "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA" - "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA" - "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH" - "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ" - "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA" - "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA=="; - TEST(DexFile, Open) { scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex)); ASSERT_TRUE(dex != NULL); } -TEST(DexFile, LoadNonexistent) { - scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex)); - ASSERT_TRUE(dex != NULL); - - scoped_ptr<Class> klass(reinterpret_cast<Class*>(new byte[sizeof(Class)])); - bool result = dex->LoadClass("NoSuchClass", klass.get()); - ASSERT_FALSE(result); -} - -TEST(DexFile, Load) { - scoped_ptr<DexFile> dex(DexFile::OpenBase64(kNestedDex)); - ASSERT_TRUE(dex != NULL); - - scoped_ptr<Class> klass(reinterpret_cast<Class*>(new byte[sizeof(Class)])); - bool result = dex->LoadClass("LNested;", klass.get()); - ASSERT_TRUE(result); - - uint32_t vmeth = klass->NumVirtualMethods(); - EXPECT_EQ(vmeth, 0U); - - uint32_t dmeth = klass->NumDirectMethods(); - EXPECT_EQ(dmeth, 1U); -} - } // namespace art @@ -11,9 +11,11 @@ namespace art { class Heap { public: - static Class* AllocClass() { + static Class* AllocClass(DexFile* dex_file) { byte* raw = new byte[sizeof(Class)](); - return reinterpret_cast<Class*>(raw); + Class* klass = reinterpret_cast<Class*>(raw); + klass->dex_file_ = dex_file; + return klass; } static CharArray* AllocCharArray(size_t length) { diff --git a/src/object.cc b/src/object.cc index 7c28d76..d897c52 100644 --- a/src/object.cc +++ b/src/object.cc @@ -69,9 +69,9 @@ uint32_t Method::NumArgRegisters() { } bool Method::HasSameArgumentTypes(const Method* that) const { - const RawDexFile* raw1 = this->dex_file_->GetRaw(); + const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw(); const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_); - const RawDexFile* raw2 = that->dex_file_->GetRaw(); + const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw(); const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_); // TODO: compare ProtoId objects for equality and exit early @@ -101,11 +101,11 @@ bool Method::HasSameArgumentTypes(const Method* that) const { } bool Method::HasSameReturnType(const Method* that) const { - const RawDexFile* raw1 = this->dex_file_->GetRaw(); + const RawDexFile* raw1 = this->GetClass()->GetDexFile()->GetRaw(); const RawDexFile::ProtoId& proto1 = raw1->GetProtoId(this->proto_idx_); const char* type1 = raw1->dexStringByTypeIdx(proto1.return_type_idx_); - const RawDexFile* raw2 = that->dex_file_->GetRaw(); + const RawDexFile* raw2 = that->GetClass()->GetDexFile()->GetRaw(); const RawDexFile::ProtoId& proto2 = raw2->GetProtoId(that->proto_idx_); const char* type2 = raw2->dexStringByTypeIdx(proto2.return_type_idx_); diff --git a/src/object.h b/src/object.h index 2b75ff7..3bad627 100644 --- a/src/object.h +++ b/src/object.h @@ -311,7 +311,7 @@ class Method { } // const char* GetReturnTypeDescriptor() const { - // return dex_file_->GetRaw()->dexStringByTypeIdx(proto_id_.return_type_id_); + // return klass_->GetDexFile_->GetRaw()->dexStringByTypeIdx(proto_id_.return_type_id_); // } // Returns true if the method is declared public. @@ -398,10 +398,6 @@ class Method { // method name, e.g. "<init>" or "eatLunch" StringPiece name_; - // A pointer to the DEX file this class was loaded from or NULL for - // proxy objects. - DexFile* dex_file_; - // Method prototype descriptor string (return and argument types). uint32_t proto_idx_; diff --git a/src/object_test.cc b/src/object_test.cc index 6ce3570..49dda32 100644 --- a/src/object_test.cc +++ b/src/object_test.cc @@ -1,7 +1,10 @@ // Copyright 2011 Google Inc. All Rights Reserved. // Author: cshapiro@google.com (Carl Shapiro) +#include "src/class_linker.h" +#include "src/common_test.h" #include "src/dex_file.h" +#include "src/heap.h" #include "src/object.h" #include "src/scoped_ptr.h" @@ -24,37 +27,18 @@ TEST(Object, IsInSamePackage) { "Ljava/lang/reflect/Method;")); } -// class ProtoCompare { -// int m1(short x, int y, long z) { return x + y + (int)z; } -// int m2(short x, int y, long z) { return x + y + (int)z; } -// int m3(long x, int y, short z) { return (int)x + y + z; } -// long m4(long x, int y, short z) { return x + y + z; } -// } -static const char kProtoCompareDex[] = - "ZGV4CjAzNQBLUetu+TVZ8gsYsCOFoij7ecsHaGSEGA8gAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP" - "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B" - "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAOAgAAIgIAADUCAAA4AgAAOwIAAD8CAABDAgAARwIA" - "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA" - "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD" - "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHACAAAAAAAAAQABAAEAAABLAgAABAAAAHAQ" - "BQAAAA4ABwAFAAAAAABQAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWAIAAAUAAACQAAMEhFGw" - "EA8AAAAGAAUAAAAAAGACAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGgCAAAFAAAAgXC7UIGCuyAQAAAA" - "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMADkxQ" - "cm90b0NvbXBhcmU7ABJMamF2YS9sYW5nL09iamVjdDsAEVByb3RvQ29tcGFyZS5qYXZhAAFTAAFW" - "AAJtMQACbTIAAm0zAAJtNAABAAcOAAIDAAAABw4AAwMAAAAHDgAEAwAAAAcOAAUDAAAABw4AAAAB" - "BACAgATEAgEA3AIBAPgCAQCUAwEArAMAAAwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA" - "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB" - "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAEsCAAAAIAAAAQAAAHACAAAAEAAAAQAAAIwC" - "AAA="; - // TODO: test 0 argument methods // TODO: make this test simpler and shorter TEST(Method, ProtoCompare) { scoped_ptr<DexFile> dex_file(DexFile::OpenBase64(kProtoCompareDex)); ASSERT_TRUE(dex_file != NULL); - scoped_ptr<Class> klass(reinterpret_cast<Class*>(new byte[sizeof(Class)])); - bool result = dex_file->LoadClass("LProtoCompare;", klass.get()); + ClassLinker linker; + linker.Init(); + linker.AppendToClassPath(dex_file.get()); + + scoped_ptr<Class> klass(Heap::AllocClass(dex_file.get())); + bool result = linker.LoadClass("LProtoCompare;", klass.get()); ASSERT_TRUE(result); ASSERT_EQ(4U, klass->NumVirtualMethods()); @@ -102,40 +86,23 @@ TEST(Method, ProtoCompare) { EXPECT_FALSE(m1->HasSameNameAndPrototype(m2)); } -// class ProtoCompare2 { -// int m1(short x, int y, long z) { return x + y + (int)z; } -// int m2(short x, int y, long z) { return x + y + (int)z; } -// int m3(long x, int y, short z) { return (int)x + y + z; } -// long m4(long x, int y, short z) { return x + y + z; } -// } -static const char kProtoCompare2Dex[] = - "ZGV4CjAzNQDVUXj687EpyTTDJZEZPA8dEYnDlm0Ir6YgAwAAcAAAAHhWNBIAAAAAAAAAAIwCAAAP" - "AAAAcAAAAAYAAACsAAAABAAAAMQAAAAAAAAAAAAAAAYAAAD0AAAAAQAAACQBAADcAQAARAEAAN4B" - "AADmAQAA6QEAAO8BAAD1AQAA+AEAAP4BAAAPAgAAIwIAADcCAAA6AgAAPQIAAEECAABFAgAASQIA" - "AAEAAAAEAAAABgAAAAcAAAAJAAAACgAAAAIAAAAAAAAAyAEAAAMAAAAAAAAA1AEAAAUAAAABAAAA" - "yAEAAAoAAAAFAAAAAAAAAAIAAwAAAAAAAgABAAsAAAACAAEADAAAAAIAAAANAAAAAgACAA4AAAAD" - "AAMAAAAAAAIAAAAAAAAAAwAAAAAAAAAIAAAAAAAAAHICAAAAAAAAAQABAAEAAABNAgAABAAAAHAQ" - "BQAAAA4ABwAFAAAAAABSAgAABQAAAJAAAwSEUbAQDwAAAAcABQAAAAAAWgIAAAUAAACQAAMEhFGw" - "EA8AAAAGAAUAAAAAAGICAAAEAAAAhCCwQLBQDwAJAAUAAAAAAGoCAAAFAAAAgXC7UIGCuyAQAAAA" - "AwAAAAEAAAAEAAAAAwAAAAQAAAABAAY8aW5pdD4AAUkABElKSVMABElTSUoAAUoABEpKSVMAD0xQ" - "cm90b0NvbXBhcmUyOwASTGphdmEvbGFuZy9PYmplY3Q7ABJQcm90b0NvbXBhcmUyLmphdmEAAVMA" - "AVYAAm0xAAJtMgACbTMAAm00AAEABw4AAgMAAAAHDgADAwAAAAcOAAQDAAAABw4ABQMAAAAHDgAA" - "AAEEAICABMQCAQDcAgEA+AIBAJQDAQCsAwwAAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAA" - "BgAAAKwAAAADAAAABAAAAMQAAAAFAAAABgAAAPQAAAAGAAAAAQAAACQBAAABIAAABQAAAEQBAAAB" - "EAAAAgAAAMgBAAACIAAADwAAAN4BAAADIAAABQAAAE0CAAAAIAAAAQAAAHICAAAAEAAAAQAAAIwC" - "AAA="; - TEST(Method, ProtoCompare2) { scoped_ptr<DexFile> dex_file1(DexFile::OpenBase64(kProtoCompareDex)); ASSERT_TRUE(dex_file1 != NULL); scoped_ptr<DexFile> dex_file2(DexFile::OpenBase64(kProtoCompare2Dex)); ASSERT_TRUE(dex_file2 != NULL); - - scoped_ptr<Class> klass1(reinterpret_cast<Class*>(new byte[sizeof(Class)])); - bool result1 = dex_file1->LoadClass("LProtoCompare;", klass1.get()); + ClassLinker linker1; + linker1.Init(); + linker1.AppendToClassPath(dex_file1.get()); + ClassLinker linker2; + linker2.Init(); + linker2.AppendToClassPath(dex_file2.get()); + + scoped_ptr<Class> klass1(Heap::AllocClass(dex_file1.get())); + bool result1 = linker1.LoadClass("LProtoCompare;", klass1.get()); ASSERT_TRUE(result1); - scoped_ptr<Class> klass2(reinterpret_cast<Class*>(new byte[sizeof(Class)])); - bool result2 = dex_file2->LoadClass("LProtoCompare2;", klass2.get()); + scoped_ptr<Class> klass2(Heap::AllocClass(dex_file2.get())); + bool result2 = linker2.LoadClass("LProtoCompare2;", klass2.get()); ASSERT_TRUE(result2); Method* m1_1 = klass1->GetVirtualMethod(0); diff --git a/src/raw_dex_file.cc b/src/raw_dex_file.cc index 145509a..2d97a9a 100644 --- a/src/raw_dex_file.cc +++ b/src/raw_dex_file.cc @@ -155,9 +155,9 @@ void RawDexFile::InitIndex() { } } -const RawDexFile::ClassDef* RawDexFile::FindClassDef(const char* descriptor) { +const RawDexFile::ClassDef* RawDexFile::FindClassDef(const char* descriptor) const { CHECK(descriptor != NULL); - Index::iterator it = index_.find(descriptor); + Index::const_iterator it = index_.find(descriptor); if (it == index_.end()) { return NULL; } else { @@ -223,7 +223,7 @@ static uint64_t ReadUnsignedLong(const byte* ptr, int zwidth, } RawDexFile::ValueType RawDexFile::ReadEncodedValue(const byte** stream, - JValue* value) { + JValue* value) const { const byte* ptr = *stream; byte value_type = *ptr++; byte value_arg = value_type >> kEncodedValueArgShift; diff --git a/src/raw_dex_file.h b/src/raw_dex_file.h index db3d8a2..6f8a581 100644 --- a/src/raw_dex_file.h +++ b/src/raw_dex_file.h @@ -227,7 +227,7 @@ class RawDexFile { } // Looks up a class definition by its class descriptor. - const ClassDef* FindClassDef(const char* descriptor); + const ClassDef* FindClassDef(const char* descriptor) const; // Returns the number of string identifiers in the .dex file. size_t NumStringIds() const { @@ -276,7 +276,7 @@ class RawDexFile { } // Decodes the header section from the raw class data bytes. - ClassDataHeader ReadClassDataHeader(const byte** class_data) { + ClassDataHeader ReadClassDataHeader(const byte** class_data) const { CHECK(class_data != NULL); ClassDataHeader header; memset(&header, 0, sizeof(ClassDataHeader)); @@ -349,7 +349,7 @@ class RawDexFile { } // Returns the short form method descriptor for the given prototype. - const char* GetShorty(uint32_t proto_idx) { + const char* GetShorty(uint32_t proto_idx) const { const ProtoId& proto_id = GetProtoId(proto_idx); return dexStringById(proto_id.shorty_idx_); } @@ -376,7 +376,7 @@ class RawDexFile { return DecodeUnsignedLeb128(&ptr); } - ValueType ReadEncodedValue(const byte** encoded_value, JValue* value); + ValueType ReadEncodedValue(const byte** encoded_value, JValue* value) const; // From libdex... diff --git a/src/raw_dex_file_test.cc b/src/raw_dex_file_test.cc index 1dd1485..8b0c130 100644 --- a/src/raw_dex_file_test.cc +++ b/src/raw_dex_file_test.cc @@ -1,5 +1,6 @@ // Copyright 2011 Google Inc. All Rights Reserved. +#include "src/common_test.h" #include "src/dex_file.h" #include "src/raw_dex_file.h" #include "src/scoped_ptr.h" @@ -9,29 +10,6 @@ namespace art { -// class Nested { -// class Inner { -// } -// } -static const char kNestedDex[] = - "ZGV4CjAzNQAQedgAe7gM1B/WHsWJ6L7lGAISGC7yjD2IAwAAcAAAAHhWNBIAAAAAAAAAAMQCAAAP" - "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAABAAAA4AAAAAMAAADoAAAAAgAAAAABAABIAgAAQAEAAK4B" - "AAC2AQAAvQEAAM0BAADXAQAA+wEAABsCAAA+AgAAUgIAAF8CAABiAgAAZgIAAHMCAAB5AgAAgQIA" - "AAIAAAADAAAABAAAAAUAAAAGAAAABwAAAAkAAAAJAAAABgAAAAAAAAAKAAAABgAAAKgBAAAAAAEA" - "DQAAAAAAAQAAAAAAAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAIAAAAiAEAAKsCAAAA" - "AAAAAQAAAAAAAAAFAAAAAAAAAAgAAACYAQAAuAIAAAAAAAACAAAAlAIAAJoCAAABAAAAowIAAAIA" - "AgABAAAAiAIAAAYAAABbAQAAcBACAAAADgABAAEAAQAAAI4CAAAEAAAAcBACAAAADgBAAQAAAAAA" - "AAAAAAAAAAAATAEAAAAAAAAAAAAAAAAAAAEAAAABAAY8aW5pdD4ABUlubmVyAA5MTmVzdGVkJElu" - "bmVyOwAITE5lc3RlZDsAIkxkYWx2aWsvYW5ub3RhdGlvbi9FbmNsb3NpbmdDbGFzczsAHkxkYWx2" - "aWsvYW5ub3RhdGlvbi9Jbm5lckNsYXNzOwAhTGRhbHZpay9hbm5vdGF0aW9uL01lbWJlckNsYXNz" - "ZXM7ABJMamF2YS9sYW5nL09iamVjdDsAC05lc3RlZC5qYXZhAAFWAAJWTAALYWNjZXNzRmxhZ3MA" - "BG5hbWUABnRoaXMkMAAFdmFsdWUAAgEABw4AAQAHDjwAAgIBDhgBAgMCCwQADBcBAgQBDhwBGAAA" - "AQEAAJAgAICABNQCAAABAAGAgATwAgAAEAAAAAAAAAABAAAAAAAAAAEAAAAPAAAAcAAAAAIAAAAH" - "AAAArAAAAAMAAAACAAAAyAAAAAQAAAABAAAA4AAAAAUAAAADAAAA6AAAAAYAAAACAAAAAAEAAAMQ" - "AAACAAAAQAEAAAEgAAACAAAAVAEAAAYgAAACAAAAiAEAAAEQAAABAAAAqAEAAAIgAAAPAAAArgEA" - "AAMgAAACAAAAiAIAAAQgAAADAAAAlAIAAAAgAAACAAAAqwIAAAAQAAABAAAAxAIAAA=="; - - TEST(RawDexFile, Open) { scoped_ptr<RawDexFile> raw(RawDexFile::OpenBase64(kNestedDex)); ASSERT_TRUE(raw != NULL); |