Reduce meta-data object sizes, introduce meta-data helper classes.
Change-Id: Id14ad218f1c74c659701352fdf1a45bf6444daa3
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index e6011da..1d05527 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -19,6 +19,8 @@
#include "dex_cache.h"
#include "dex_verifier.h"
#include "macros.h"
+#include "object.h"
+#include "object_utils.h"
#include "reflection.h"
#include "ScopedLocalRef.h"
@@ -172,7 +174,7 @@
result += "tried to access class ";
result += class_name;
result += " from class ";
- result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
+ result += PrettyDescriptor(method->GetDeclaringClass());
return result;
}
@@ -194,7 +196,7 @@
result += "tried to access field ";
result += class_name + "." + field_name;
result += " from class ";
- result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
+ result += PrettyDescriptor(method->GetDeclaringClass());
return result;
}
@@ -217,7 +219,7 @@
result += class_name + "." + method_name + ":" +
dex_file.CreateMethodSignature(id.proto_idx_, NULL);
result += " from class ";
- result += PrettyDescriptor(method->GetDeclaringClass()->GetDescriptor());
+ result += PrettyDescriptor(method->GetDeclaringClass());
return result;
}
@@ -352,9 +354,7 @@
Method* caller = *caller_sp;
// less two as return address may span into next dex instruction
uint32_t dex_pc = caller->ToDexPC(caller_pc - 2);
- const DexFile& dex_file = Runtime::Current()->GetClassLinker()
- ->FindDexFile(caller->GetDeclaringClass()->GetDexCache());
- const DexFile::CodeItem* code = dex_file.GetCodeItem(caller->GetCodeItemOffset());
+ const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
CHECK_LT(dex_pc, code->insns_size_in_code_units_);
const Instruction* instr = Instruction::At(&code->insns_[dex_pc]);
Instruction::Code instr_code = instr->Opcode();
@@ -473,14 +473,16 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int32_t))) {
return field->Get32(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
+ FieldHelper fh(field);
+ if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int32_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of 32-bit primitive on field '%s'",
PrettyField(field, true).c_str());
@@ -495,14 +497,16 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int64_t))) {
return field->Get64(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t)) {
+ FieldHelper fh(field);
+ if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int64_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of 64-bit primitive on field '%s'",
PrettyField(field, true).c_str());
@@ -517,14 +521,16 @@
Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(!field->IsPrimitiveType())) {
+ FieldHelper fh(field);
+ if (LIKELY(!fh.IsPrimitiveType())) {
return field->GetObj(NULL);
}
}
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (field->IsPrimitiveType()) {
+ FieldHelper fh(field);
+ if (fh.IsPrimitiveType()) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted read of reference on primitive field '%s'",
PrettyField(field, true).c_str());
@@ -539,7 +545,8 @@
uint32_t new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int32_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int32_t))) {
field->Set32(NULL, new_value);
return 0; // success
}
@@ -547,7 +554,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int32_t)) {
+ FieldHelper fh(field);
+ if (!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int32_t)) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of 32-bit primitive to field '%s'",
PrettyField(field, true).c_str());
@@ -563,7 +571,8 @@
uint64_t new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(field->IsPrimitiveType() && field->PrimitiveSize() == sizeof(int64_t))) {
+ FieldHelper fh(field);
+ if (LIKELY(fh.IsPrimitiveType() && fh.FieldSize() == sizeof(int64_t))) {
field->Set64(NULL, new_value);
return 0; // success
}
@@ -571,7 +580,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (LIKELY(field != NULL)) {
- if (UNLIKELY(!field->IsPrimitiveType() || field->PrimitiveSize() != sizeof(int64_t))) {
+ FieldHelper fh(field);
+ if (UNLIKELY(!fh.IsPrimitiveType() || fh.FieldSize() != sizeof(int64_t))) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of 64-bit primitive to field '%s'",
PrettyField(field, true).c_str());
@@ -587,7 +597,7 @@
Object* new_value, Thread* self, Method** sp) {
Field* field = FindFieldFast(field_idx, referrer);
if (LIKELY(field != NULL)) {
- if (LIKELY(!field->IsPrimitiveType())) {
+ if (LIKELY(!FieldHelper(field).IsPrimitiveType())) {
field->SetObj(NULL, new_value);
return 0; // success
}
@@ -595,7 +605,7 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
field = FindFieldFromCode(field_idx, referrer, true);
if (field != NULL) {
- if (field->IsPrimitiveType()) {
+ if (FieldHelper(field).IsPrimitiveType()) {
self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
"Attempted write of reference to primitive field '%s'",
PrettyField(field, true).c_str());
@@ -643,8 +653,8 @@
Class* referrer = method->GetDeclaringClass();
if (UNLIKELY(!referrer->CanAccess(klass))) {
self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;", "illegal class access: '%s' -> '%s'",
- PrettyDescriptor(referrer->GetDescriptor()).c_str(),
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(referrer).c_str(),
+ PrettyDescriptor(klass).c_str());
return NULL; // Failure
}
if (!runtime->GetClassLinker()->EnsureInitialized(klass, true)) {
@@ -672,11 +682,11 @@
if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
"Bad filled array request for type %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
} else {
Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
"Found type %s; filled-new-array not implemented for anything but \'int\'",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ PrettyDescriptor(klass).c_str());
}
return NULL; // Failure
} else {
@@ -731,8 +741,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
"%s cannot be cast to %s",
- PrettyDescriptor(a->GetDescriptor()).c_str(),
- PrettyDescriptor(b->GetDescriptor()).c_str());
+ PrettyDescriptor(a).c_str(),
+ PrettyDescriptor(b).c_str());
return -1; // Failure
}
}
@@ -751,8 +761,8 @@
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
"Cannot store an object of type %s in to an array of type %s",
- PrettyDescriptor(element_class->GetDescriptor()).c_str(),
- PrettyDescriptor(array_class->GetDescriptor()).c_str());
+ PrettyDescriptor(element_class).c_str(),
+ PrettyDescriptor(array_class).c_str());
return -1; // Failure
}
}
@@ -769,7 +779,7 @@
//
// Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
// running.
- if (klass == referrer->GetDeclaringClass() && referrer->IsClassInitializer()) {
+ if (klass == referrer->GetDeclaringClass() && MethodHelper(referrer).IsClassInitializer()) {
return klass;
}
if (!class_linker->EnsureInitialized(klass, true)) {
@@ -792,14 +802,14 @@
if (UNLIKELY(!referrer->GetDeclaringClass()->CanAccess(klass))) {
self->ThrowNewExceptionF("Ljava/lang/IllegalAccessError;",
"Class %s is inaccessible to method %s",
- PrettyDescriptor(klass->GetDescriptor()).c_str(),
+ PrettyDescriptor(klass).c_str(),
PrettyMethod(referrer, true).c_str());
}
// If we are the <clinit> of this class, just return our storage.
//
// Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
// running.
- if (klass == referrer->GetDeclaringClass() && referrer->IsClassInitializer()) {
+ if (klass == referrer->GetDeclaringClass() && MethodHelper(referrer).IsClassInitializer()) {
return klass;
}
if (!class_linker->EnsureInitialized(klass, true)) {
@@ -1000,10 +1010,11 @@
// Placing into local references incoming arguments from the caller's register arguments,
// replacing original Object* with jobject
- const size_t num_params = proxy_method->NumArgs();
+ MethodHelper proxy_mh(proxy_method);
+ const size_t num_params = proxy_mh.NumArgs();
size_t args_in_regs = 0;
for (size_t i = 1; i < num_params; i++) { // skip receiver
- args_in_regs = args_in_regs + (proxy_method->IsParamALongOrDouble(i) ? 2 : 1);
+ args_in_regs = args_in_regs + (proxy_mh.IsParamALongOrDouble(i) ? 2 : 1);
if (args_in_regs > 2) {
args_in_regs = 2;
break;
@@ -1012,23 +1023,23 @@
size_t cur_arg = 0; // current stack location to read
size_t param_index = 1; // skip receiver
while (cur_arg < args_in_regs && param_index < num_params) {
- if (proxy_method->IsParamAReference(param_index)) {
+ if (proxy_mh.IsParamAReference(param_index)) {
Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
jobject jobj = AddLocalReference<jobject>(env, obj);
*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
}
- cur_arg = cur_arg + (proxy_method->IsParamALongOrDouble(param_index) ? 2 : 1);
+ cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
param_index++;
}
// Placing into local references incoming arguments from the caller's stack arguments
cur_arg += 11; // skip callee saves, LR, Method* and out arg spills for R1 to R3
while (param_index < num_params) {
- if (proxy_method->IsParamAReference(param_index)) {
+ if (proxy_mh.IsParamAReference(param_index)) {
Object* obj = *reinterpret_cast<Object**>(stack_args + (cur_arg * kPointerSize));
jobject jobj = AddLocalReference<jobject>(env, obj);
*reinterpret_cast<jobject*>(stack_args + (cur_arg * kPointerSize)) = jobj;
}
- cur_arg = cur_arg + (proxy_method->IsParamALongOrDouble(param_index) ? 2 : 1);
+ cur_arg = cur_arg + (proxy_mh.IsParamALongOrDouble(param_index) ? 2 : 1);
param_index++;
}
// Set up arguments array and place in local IRT during boxing (which may allocate/GC)
@@ -1049,13 +1060,14 @@
// Convert proxy method into expected interface method
Method* interface_method = proxy_method->FindOverriddenMethod();
CHECK(interface_method != NULL);
+ CHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
args_jobj[1].l = AddLocalReference<jobject>(env, interface_method);
LOG(INFO) << "Interface method is " << PrettyMethod(interface_method, true);
// Box arguments
cur_arg = 0; // reset stack location to read to start
// reset index, will index into param type array which doesn't include the receiver
param_index = 0;
- ObjectArray<Class>* param_types = interface_method->GetJavaParameterTypes();
+ ObjectArray<Class>* param_types = proxy_mh.GetParameterTypes();
CHECK(param_types != NULL);
// Check number of parameter types agrees with number from the Method - less 1 for the receiver.
CHECK_EQ(static_cast<size_t>(param_types->GetLength()), num_params - 1);
@@ -1119,7 +1131,7 @@
Object* result_ref = self->DecodeJObject(result);
if (result_ref != NULL) {
JValue result_unboxed;
- UnboxPrimitive(env, result_ref, interface_method->GetReturnType(), result_unboxed);
+ UnboxPrimitive(env, result_ref, proxy_mh.GetReturnType(), result_unboxed);
*reinterpret_cast<JValue*>(stack_args) = result_unboxed;
} else {
*reinterpret_cast<jobject*>(stack_args) = NULL;
@@ -1132,7 +1144,10 @@
if (!exception->IsCheckedException()) {
self->SetException(exception);
} else {
- ObjectArray<Class>* declared_exceptions = proxy_method->GetExceptionTypes();
+ // TODO: get the correct intersection of exceptions as passed to the class linker's create
+ // proxy code.
+ UNIMPLEMENTED(FATAL);
+ ObjectArray<Class>* declared_exceptions = NULL; // proxy_mh.GetExceptionTypes();
Class* exception_class = exception->GetClass();
bool declares_exception = false;
for (int i = 0; i < declared_exceptions->GetLength() && !declares_exception; i++) {