Fix bug in HasSameMethodDescriptorClass on return types
Also included:
- Make oatdump tolerant of missing code
- Include class status in oatdump output
- Additional oat_process support for testing
Change-Id: Id1b8d5662ca061f2dc22b2b087b5a5945e54b91c
diff --git a/Android.mk b/Android.mk
index 6c2fd7e..a27d526 100644
--- a/Android.mk
+++ b/Android.mk
@@ -156,18 +156,24 @@
# oatdump targets
.PHONY: dump-oat
-dump-oat: dump-core-oat dump-boot-oat
+dump-oat: dump-oat-core dump-oat-boot
-.PHONY: dump-core-oat
-dump-core-oat: $(TARGET_CORE_OAT) $(OATDUMP)
- $(OATDUMP) $(addprefix --dex-file=,$(TARGET_CORE_DEX)) --image=$(TARGET_CORE_OAT) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt
+.PHONY: dump-oat-core
+dump-oat-core: $(TARGET_CORE_OAT) $(OATDUMP)
+ $(OATDUMP) $(addprefix --dex-file=,$(TARGET_CORE_DEX)) --image=$< --strip-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt
@echo Output in /tmp/core.oatdump.txt
-.PHONY: dump-boot-oat
-dump-boot-oat: $(TARGET_BOOT_OAT) $(OATDUMP)
- $(OATDUMP) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --image=$(TARGET_BOOT_OAT) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
+.PHONY: dump-oat-boot
+dump-oat-boot: $(TARGET_BOOT_OAT) $(OATDUMP)
+ $(OATDUMP) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --image=$< --strip-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
@echo Output in /tmp/boot.oatdump.txt
+.PHONY: dump-oat-Calculator
+dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.oat $(TARGET_BOOT_OAT) $(OATDUMP)
+ $(OATDUMP) --dex-file=$(TARGET_OUT_APPS)/Calculator.apk --image=$< $(addprefix --boot-dex-file=,$(TARGET_BOOT_DEX)) --boot=$(TARGET_BOOT_OAT) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt
+ @echo Output in /tmp/Calculator.oatdump.txt
+
+
########################################################################
# cpplint target
diff --git a/oat_process/Android.mk b/oat_process/Android.mk
index 9fb9401..0ebb052 100644
--- a/oat_process/Android.mk
+++ b/oat_process/Android.mk
@@ -6,18 +6,25 @@
local_shared_libraries := \
libcutils \
libutils \
- libbinder
+ libbinder \
+ libstlport
include $(CLEAR_VARS)
+include external/stlport/libstlport.mk
LOCAL_MODULE:= oat_process
LOCAL_MODULE_TAGS:= optional
LOCAL_SRC_FILES:= $(local_src_files)
-LOCAL_SHARED_LIBRARIES := liboat_runtimed $(local_shared_libraries)
+LOCAL_SHARED_LIBRARIES := liboat_runtime libart $(local_shared_libraries)
+LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
+LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
include $(BUILD_EXECUTABLE)
include $(CLEAR_VARS)
+include external/stlport/libstlport.mk
LOCAL_MODULE_TAGS:= optional
LOCAL_MODULE:= oat_processd
LOCAL_SRC_FILES:= $(local_src_files)
-LOCAL_SHARED_LIBRARIES := liboat_runtimed $(local_shared_libraries)
+LOCAL_SHARED_LIBRARIES := liboat_runtimed libartd $(local_shared_libraries)
+LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
+LOCAL_CFLAGS := $(ART_TARGET_CFLAGS)
include $(BUILD_EXECUTABLE)
diff --git a/oat_process/app_main.cpp b/oat_process/app_main.cpp
index ca80fc2..45950cd 100644
--- a/oat_process/app_main.cpp
+++ b/oat_process/app_main.cpp
@@ -7,6 +7,11 @@
#define LOG_TAG "appproc"
+#include "class_loader.h"
+#include "jni_internal.h"
+#include "stringprintf.h"
+#include "thread.h"
+
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <utils/Log.h>
@@ -72,11 +77,37 @@
char* slashClassName = toSlashClassName(mClassName);
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
- LOGE("ERROR: could not find class '%s'\n", mClassName);
+ LOG(ERROR) << StringPrintf("ERROR: could not find class '%s'\n", mClassName);
}
free(slashClassName);
mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
+
+ // TODO: remove this ClassLoader code
+ jclass ApplicationLoaders = env->FindClass("android/app/ApplicationLoaders");
+ jmethodID getDefault = env->GetStaticMethodID(ApplicationLoaders,
+ "getDefault",
+ "()Landroid/app/ApplicationLoaders;");
+ jfieldID mLoaders = env->GetFieldID(ApplicationLoaders, "mLoaders", "Ljava/util/Map;");
+ jclass BootClassLoader = env->FindClass("java/lang/BootClassLoader");
+ jmethodID getInstance = env->GetStaticMethodID(BootClassLoader,
+ "getInstance",
+ "()Ljava/lang/BootClassLoader;");
+ jclass ClassLoader = env->FindClass("java/lang/ClassLoader");
+ jfieldID parent = env->GetFieldID(ClassLoader, "parent", "Ljava/lang/ClassLoader;");
+ jclass Map = env->FindClass("java/util/Map");
+ jmethodID put = env->GetMethodID(Map,
+ "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
+
+ jobject application_loaders = env->CallStaticObjectMethod(ApplicationLoaders, getDefault);
+ jobject loaders = env->GetObjectField(application_loaders, mLoaders);
+ jobject boot_class_loader = env->CallStaticObjectMethod(BootClassLoader, getInstance);
+ const art::ClassLoader* class_loader_object = art::Thread::Current()->GetClassLoaderOverride();
+ jobject class_loader = art::AddLocalReference<jobject>(env, class_loader_object);
+ env->SetObjectField(class_loader, parent, boot_class_loader);
+ jstring apk = env->NewStringUTF("/system/app/Calculator.apk");
+ env->CallObjectMethod(loaders, put, apk, class_loader);
}
virtual void onStarted()
@@ -150,11 +181,11 @@
// ignore /system/bin/app_process when invoked via WrapperInit
if (strcmp(argv[0], "/system/bin/app_process") == 0) {
- LOGI("Removing /system/bin/app_process argument");
+ LOG(INFO) << "Removing /system/bin/app_process argument";
argc--;
argv++;
for (int i = 0; i < argc; i++) {
- LOGI("argv[%d]=%s", i, argv[i]);
+ LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
}
}
@@ -162,7 +193,7 @@
int oatArgc = argc + 2;
const char* oatArgv[oatArgc];
if (strcmp(argv[0], "-Xbootimage:/system/framework/boot.oat") != 0) {
- LOGI("Adding oat arguments");
+ LOG(INFO) << "Adding oat arguments";
oatArgv[0] = "-Xbootimage:/system/framework/boot.oat";
oatArgv[1] = "-Ximage:/system/app/Calculator.oat";
setenv("CLASSPATH", "/system/app/Calculator.apk", 1);
@@ -170,12 +201,12 @@
argv = oatArgv;
argc = oatArgc;
for (int i = 0; i < argc; i++) {
- LOGI("argv[%d]=%s", i, argv[i]);
+ LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
}
}
// TODO: remove the heap arguments when implicit garbage collection enabled
- LOGI("Adding heap arguments");
+ LOG(INFO) << "Adding heap arguments";
int heapArgc = argc + 2;
const char* heapArgv[heapArgc];
heapArgv[0] = "-Xms64m";
@@ -184,11 +215,11 @@
argv = heapArgv;
argc = heapArgc;
for (int i = 0; i < argc; i++) {
- LOGI("argv[%d]=%s", i, argv[i]);
+ LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
}
// TODO: change the system default to not perform preloading
- LOGI("Disabling preloading");
+ LOG(INFO) << "Disabling preloading";
for (int i = 0; i < argc; i++) {
if (strcmp(argv[i], "preload") == 0) {
argv[i] = "nopreload";
@@ -196,7 +227,7 @@
}
}
for (int i = 0; i < argc; i++) {
- LOGI("argv[%d]=%s", i, argv[i]);
+ LOG(INFO) << StringPrintf("argv[%d]=%s", i, argv[i]);
}
// Everything up to '--' or first non '-' arg goes to the vm
@@ -249,7 +280,7 @@
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
- LOG_ALWAYS_FATAL("oat_process: no class name or --zygote supplied.");
+ LOG(FATAL) << "oat_process: no class name or --zygote supplied.";
return 10;
}
}
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 9c00d72..becd6d5 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1444,7 +1444,9 @@
bool ClassLinker::HasSameMethodDescriptorClasses(const Method* method,
const Class* klass1,
const Class* klass2) {
- if (method->IsMiranda()) { return true; }
+ if (method->IsMiranda()) {
+ return true;
+ }
const DexFile& dex_file = FindDexFile(method->GetDeclaringClass()->GetDexCache());
const DexFile::ProtoId& proto_id = dex_file.GetProtoId(method->GetProtoIdx());
DexFile::ParameterIterator *it;
@@ -1463,7 +1465,7 @@
// Check the return type
const char* descriptor = dex_file.GetReturnTypeDescriptor(proto_id);
if (descriptor[0] == 'L' || descriptor[0] == '[') {
- if (HasSameDescriptorClasses(descriptor, klass1, klass2)) {
+ if (!HasSameDescriptorClasses(descriptor, klass1, klass2)) {
return false;
}
}
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 4cb9cf0..e5911c0 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -126,6 +126,9 @@
if (obj->IsClass()) {
Class* klass = obj->AsClass();
StringAppendF(&summary, "CLASS %s", klass->GetDescriptor()->ToModifiedUtf8().c_str());
+ std::stringstream ss;
+ ss << " (" << klass->GetStatus() << ")";
+ summary += ss.str();
} else if (obj->IsMethod()) {
Method* method = obj->AsMethod();
StringAppendF(&summary, "METHOD %s", PrettyMethod(method).c_str());
@@ -151,21 +154,32 @@
// object_bytes, RoundUp(object_bytes, kObjectAlignment) - object_bytes);
if (obj->IsMethod()) {
Method* method = obj->AsMethod();
- const ByteArray* code = method->GetCodeArray();
if (!method->IsPhony()) {
- size_t code_bytes = code->GetLength();
- if (method->IsNative()) {
- state->stats_.managed_to_native_code_bytes += code_bytes;
- } else {
- state->stats_.managed_code_bytes += code_bytes;
+ const ByteArray* code = method->GetCodeArray();
+ const int8_t* code_base = NULL;
+ const int8_t* code_limit = NULL;
+ if (code != NULL) {
+ size_t code_bytes = code->GetLength();
+ code_base = code->GetData();
+ code_limit = code_base + code_bytes;
+ if (method->IsNative()) {
+ state->stats_.managed_to_native_code_bytes += code_bytes;
+ } else {
+ state->stats_.managed_code_bytes += code_bytes;
+ }
}
- StringAppendF(&summary, "\tCODE %p-%p\n", code->GetData(), code->GetData() + code_bytes);
+ StringAppendF(&summary, "\tCODE %p-%p\n", code_base, code_limit);
const ByteArray* invoke = method->GetInvokeStubArray();
- size_t native_to_managed_code_bytes = invoke->GetLength();
- state->stats_.native_to_managed_code_bytes += native_to_managed_code_bytes;
- StringAppendF(&summary, "\tJNI STUB %p-%p\n",
- invoke->GetData(), invoke->GetData() + native_to_managed_code_bytes);
+ const int8_t* invoke_base = NULL;
+ const int8_t* invoke_limit = NULL;
+ if (invoke != NULL) {
+ size_t native_to_managed_code_bytes = invoke->GetLength();
+ invoke_base = invoke->GetData();
+ invoke_limit = invoke_base + native_to_managed_code_bytes;
+ state->stats_.native_to_managed_code_bytes += native_to_managed_code_bytes;
+ StringAppendF(&summary, "\tJNI STUB %p-%p\n", invoke_base, invoke_limit);
+ }
}
if (method->IsNative()) {
if (method->IsRegistered()) {
@@ -191,8 +205,10 @@
method->GetRegisterMapData()->GetLength());
state->stats_.register_map_bytes += register_map_bytes;
- size_t pc_mapping_table_bytes = method->GetMappingTable()->GetLength();
- state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
+ if (method->GetMappingTable() != NULL) {
+ size_t pc_mapping_table_bytes = method->GetMappingTable()->GetLength();
+ state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
+ }
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
class DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();