summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/quick/x86/x86_lir.h67
-rw-r--r--runtime/arch/arm/quick_entrypoints_arm.S2
-rw-r--r--runtime/arch/mips/quick_entrypoints_mips.S5
-rw-r--r--runtime/arch/x86/quick_entrypoints_x86.S15
-rw-r--r--runtime/arch/x86_64/quick_entrypoints_x86_64.S8
-rw-r--r--runtime/class_linker.cc2
-rw-r--r--runtime/common_test.h26
-rw-r--r--runtime/debugger.cc2
-rw-r--r--runtime/entrypoints/interpreter/interpreter_entrypoints.cc4
-rw-r--r--runtime/gc/heap.cc8
-rw-r--r--runtime/jni_internal.cc16
-rw-r--r--runtime/jni_internal.h2
-rw-r--r--runtime/jni_internal_test.cc127
-rw-r--r--runtime/mirror/art_method.cc10
-rw-r--r--runtime/mirror/art_method.h4
-rw-r--r--runtime/reflection.cc16
-rw-r--r--runtime/runtime.cc11
-rw-r--r--runtime/thread.cc11
18 files changed, 204 insertions, 132 deletions
diff --git a/compiler/dex/quick/x86/x86_lir.h b/compiler/dex/quick/x86/x86_lir.h
index c49f627..8c385a1 100644
--- a/compiler/dex/quick/x86/x86_lir.h
+++ b/compiler/dex/quick/x86/x86_lir.h
@@ -22,54 +22,53 @@
namespace art {
/*
- * Runtime register conventions. We consider both x86, x86-64 and x32 (32bit mode x86-64), although
- * we currently only target x86. The ABI has different conventions and we hope to have a single
- * convention to simplify code generation. Changing something that is callee save and making it
- * caller save places a burden on up-calls to save/restore the callee save register, however, there
- * are few registers that are callee save in the ABI. Changing something that is caller save and
- * making it callee save places a burden on down-calls to save/restore the callee save register.
- * For these reasons we aim to match native conventions for caller and callee save. The first 4
- * registers can be used for byte operations, for this reason they are preferred for temporary
- * scratch registers.
+ * Runtime register conventions. We consider both x86, x86-64 and x32 (32bit mode x86-64). The ABI
+ * has different conventions and we capture those here. Changing something that is callee save and
+ * making it caller save places a burden on up-calls to save/restore the callee save register,
+ * however, there are few registers that are callee save in the ABI. Changing something that is
+ * caller save and making it callee save places a burden on down-calls to save/restore the callee
+ * save register. For these reasons we aim to match native conventions for caller and callee save.
+ * On x86 only the first 4 registers can be used for byte operations, for this reason they are
+ * preferred for temporary scratch registers.
*
* General Purpose Register:
- * Native: x86 | x86-64 / x32 | ART
- * r0/eax: caller save | caller save | caller, Method*, scratch, return value
- * r1/ecx: caller save | caller save, arg4 | caller, arg1, scratch
- * r2/edx: caller save | caller save, arg3 | caller, arg2, scratch, high half of long return
- * r3/ebx: callEE save | callEE save | callER, arg3, scratch
+ * Native: x86 | x86-64 / x32 | ART x86 | ART x86-64
+ * r0/eax: caller | caller | caller, Method*, scratch, return value | caller, scratch, return value
+ * r1/ecx: caller | caller, arg4 | caller, arg1, scratch | caller, arg3, scratch
+ * r2/edx: caller | caller, arg3 | caller, arg2, scratch, high half of long return | caller, arg2, scratch
+ * r3/ebx: callEE | callEE | callER, arg3, scratch | callee, promotable
* r4/esp: stack pointer
- * r5/ebp: callee save | callee save | callee, available for dalvik register promotion
- * r6/esi: callEE save | callER save, arg2 | callee, available for dalvik register promotion
- * r7/edi: callEE save | callER save, arg1 | callee, available for dalvik register promotion
+ * r5/ebp: callee | callee | callee, promotable | callee, promotable
+ * r6/esi: callEE | callER, arg2 | callee, promotable | caller, arg1, scratch
+ * r7/edi: callEE | callER, arg1 | callee, promotable | caller, Method*, scratch
* --- x86-64/x32 registers
* Native: x86-64 / x32 | ART
- * r8: caller save, arg5 | caller, scratch
- * r9: caller save, arg6 | caller, scratch
+ * r8: caller save, arg5 | caller, arg4, scratch
+ * r9: caller save, arg6 | caller, arg5, scratch
* r10: caller save | caller, scratch
* r11: caller save | caller, scratch
- * r12: callee save | callee, available for dalvik register promotion
- * r13: callee save | callee, available for dalvik register promotion
- * r14: callee save | callee, available for dalvik register promotion
- * r15: callee save | callee, available for dalvik register promotion
+ * r12: callee save | callee, available for register promotion (promotable)
+ * r13: callee save | callee, available for register promotion (promotable)
+ * r14: callee save | callee, available for register promotion (promotable)
+ * r15: callee save | callee, available for register promotion (promotable)
*
* There is no rSELF, instead on x86 fs: has a base address of Thread::Current, whereas on
* x86-64/x32 gs: holds it.
*
* For floating point we don't support CPUs without SSE2 support (ie newer than PIII):
- * Native: x86 | x86-64 / x32 | ART
- * XMM0: caller save |caller save, arg1 | caller, float/double return value (except for native x86 code)
- * XMM1: caller save |caller save, arg2 | caller, scratch
- * XMM2: caller save |caller save, arg3 | caller, scratch
- * XMM3: caller save |caller save, arg4 | caller, scratch
- * XMM4: caller save |caller save, arg5 | caller, scratch
- * XMM5: caller save |caller save, arg6 | caller, scratch
- * XMM6: caller save |caller save, arg7 | caller, scratch
- * XMM7: caller save |caller save, arg8 | caller, scratch
+ * Native: x86 | x86-64 / x32 | ART x86 | ART x86-64
+ * XMM0: caller | caller, arg1 | caller, float return value | caller, arg1, float return value
+ * XMM1: caller | caller, arg2 | caller, scratch | caller, arg2, scratch
+ * XMM2: caller | caller, arg3 | caller, scratch | caller, arg3, scratch
+ * XMM3: caller | caller, arg4 | caller, scratch | caller, arg4, scratch
+ * XMM4: caller | caller, arg5 | caller, scratch | caller, arg5, scratch
+ * XMM5: caller | caller, arg6 | caller, scratch | caller, arg6, scratch
+ * XMM6: caller | caller, arg7 | caller, scratch | caller, arg7, scratch
+ * XMM7: caller | caller, arg8 | caller, scratch | caller, arg8, scratch
* --- x86-64/x32 registers
- * XMM8 .. 15: caller save
+ * XMM8 .. 15: caller save available as scratch registers for ART.
*
- * X87 is a necessary evil outside of ART code:
+ * X87 is a necessary evil outside of ART code for x86:
* ST0: x86 float/double native return value, caller save
* ST1 .. ST7: caller save
*
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 0e5c60a..cf3f72e 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -274,7 +274,7 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo
* r2 = size of argument array in bytes
* r3 = (managed) thread pointer
* [sp] = JValue* result
- * [sp + 4] = result type char
+ * [sp + 4] = shorty
*/
ENTRY art_quick_invoke_stub
push {r0, r4, r5, r9, r11, lr} @ spill regs
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index c60bca0..f9a200a 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -456,7 +456,7 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo
* a2 = size of argument array in bytes
* a3 = (managed) thread pointer
* [sp + 16] = JValue* result
- * [sp + 20] = result type char
+ * [sp + 20] = shorty
*/
ENTRY art_quick_invoke_stub
GENERATE_GLOBAL_POINTER
@@ -502,7 +502,8 @@ ENTRY art_quick_invoke_stub
addiu $sp, $sp, 16
.cfi_adjust_cfa_offset -16
lw $t0, 16($sp) # get result pointer
- lw $t1, 20($sp) # get result type char
+ lw $t1, 20($sp) # get shorty
+ lb $t1, 0($t1) # get result type char
li $t2, 68 # put char 'D' into t2
beq $t1, $t2, 1f # branch if result type char == 'D'
li $t3, 70 # put char 'F' into t3
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 9c3eb30..c76c6b2 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -251,7 +251,7 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo
* [sp + 12] = size of argument array in bytes
* [sp + 16] = (managed) thread pointer
* [sp + 20] = JValue* result
- * [sp + 24] = result type char
+ * [sp + 24] = shorty
*/
DEFINE_FUNCTION art_quick_invoke_stub
PUSH ebp // save ebp
@@ -281,17 +281,20 @@ DEFINE_FUNCTION art_quick_invoke_stub
POP ebx // pop ebx
POP ebp // pop ebp
mov 20(%esp), %ecx // get result pointer
- cmpl LITERAL(68), 24(%esp) // test if result type char == 'D'
+ mov %eax, (%ecx) // store the result assuming its a long, int or Object*
+ mov %edx, 4(%ecx) // store the other half of the result
+ mov 24(%esp), %edx // get the shorty
+ cmpb LITERAL(68), (%edx) // test if result type char == 'D'
je return_double_quick
- cmpl LITERAL(70), 24(%esp) // test if result type char == 'F'
+ cmpb LITERAL(70), (%edx) // test if result type char == 'F'
je return_float_quick
- mov %eax, (%ecx) // store the result
- mov %edx, 4(%ecx) // store the other half of the result
ret
return_double_quick:
-return_float_quick:
movsd %xmm0, (%ecx) // store the floating point result
ret
+return_float_quick:
+ movss %xmm0, (%ecx) // store the floating point result
+ ret
END_FUNCTION art_quick_invoke_stub
MACRO3(NO_ARG_DOWNCALL, c_name, cxx_name, return_macro)
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index e01a31b..44bc7a2 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -149,6 +149,14 @@ INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvo
/*
* Quick invocation stub.
+ * On entry:
+ * [sp] = return address
+ * rdi = method pointer
+ * rsi = argument array or NULL for no argument methods
+ * rdx = size of argument array in bytes
+ * rcx = (managed) thread pointer
+ * r8 = JValue* result
+ * r9 = char* shorty
*/
DEFINE_FUNCTION art_quick_invoke_stub
int3
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 978c99b..707082d 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3152,7 +3152,7 @@ bool ClassLinker::InitializeClass(const SirtRef<mirror::Class>& klass, bool can_
CHECK(can_init_statics);
if (LIKELY(Runtime::Current()->IsStarted())) {
JValue result;
- clinit->Invoke(self, NULL, 0, &result, 'V');
+ clinit->Invoke(self, NULL, 0, &result, "V");
} else {
art::interpreter::EnterInterpreterFromInvoke(self, clinit, NULL, NULL, NULL);
}
diff --git a/runtime/common_test.h b/runtime/common_test.h
index af7e8ae..f7859ea 100644
--- a/runtime/common_test.h
+++ b/runtime/common_test.h
@@ -268,7 +268,7 @@ class CommonTest : public testing::Test {
MakeExecutable(&code[0], code.size());
}
- // Create an OatMethod based on pointers (for unit tests)
+ // Create an OatMethod based on pointers (for unit tests).
OatFile::OatMethod CreateOatMethod(const void* code,
const size_t frame_size_in_bytes,
const uint32_t core_spill_mask,
@@ -276,11 +276,23 @@ class CommonTest : public testing::Test {
const uint8_t* mapping_table,
const uint8_t* vmap_table,
const uint8_t* gc_map) {
- const byte* base = nullptr; // Base of data in oat file, ie 0.
- uint32_t code_offset = PointerToLowMemUInt32(code);
- uint32_t mapping_table_offset = PointerToLowMemUInt32(mapping_table);
- uint32_t vmap_table_offset = PointerToLowMemUInt32(vmap_table);
- uint32_t gc_map_offset = PointerToLowMemUInt32(gc_map);
+ const byte* base;
+ uint32_t code_offset, mapping_table_offset, vmap_table_offset, gc_map_offset;
+ if (mapping_table == nullptr && vmap_table == nullptr && gc_map == nullptr) {
+ base = reinterpret_cast<const byte*>(code); // Base of data points at code.
+ base -= kPointerSize; // Move backward so that code_offset != 0.
+ code_offset = kPointerSize;
+ mapping_table_offset = 0;
+ vmap_table_offset = 0;
+ gc_map_offset = 0;
+ } else {
+ // TODO: 64bit support.
+ base = nullptr; // Base of data in oat file, ie 0.
+ code_offset = PointerToLowMemUInt32(code);
+ mapping_table_offset = PointerToLowMemUInt32(mapping_table);
+ vmap_table_offset = PointerToLowMemUInt32(vmap_table);
+ gc_map_offset = PointerToLowMemUInt32(gc_map);
+ }
return OatFile::OatMethod(base,
code_offset,
frame_size_in_bytes,
@@ -470,6 +482,8 @@ class CommonTest : public testing::Test {
instruction_set = kX86;
#elif defined(__x86_64__)
instruction_set = kX86_64;
+ // TODO: x86_64 compilation support.
+ runtime_->SetCompilerFilter(Runtime::kInterpretOnly);
#endif
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index 8280c7c..53ac5cc 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -3019,7 +3019,7 @@ void Dbg::ExecuteMethod(DebugInvokeReq* pReq) {
MethodHelper mh(m.get());
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, pReq->receiver, reinterpret_cast<jvalue*>(pReq->arg_values));
- InvokeWithArgArray(soa, m.get(), &arg_array, &pReq->result_value, mh.GetShorty()[0]);
+ InvokeWithArgArray(soa, m.get(), &arg_array, &pReq->result_value, mh.GetShorty());
mirror::Throwable* exception = soa.Self()->GetException(NULL);
soa.Self()->ClearException();
diff --git a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
index 8a2ce51..2067a45 100644
--- a/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
+++ b/runtime/entrypoints/interpreter/interpreter_entrypoints.cc
@@ -48,11 +48,11 @@ extern "C" void artInterpreterToCompiledCodeBridge(Thread* self, MethodHelper& m
if (kUsePortableCompiler) {
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArrayFromFrame(shadow_frame, arg_offset);
- method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty()[0]);
+ method->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), result, mh.GetShorty());
} else {
method->Invoke(self, shadow_frame->GetVRegArgs(arg_offset),
(shadow_frame->NumberOfVRegs() - arg_offset) * sizeof(uint32_t),
- result, mh.GetShorty()[0]);
+ result, mh.GetShorty());
}
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 62567d7..39521b3 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2316,10 +2316,10 @@ mirror::Object* Heap::GetReferenceReferent(mirror::Object* reference) {
void Heap::AddFinalizerReference(Thread* self, mirror::Object* object) {
ScopedObjectAccess soa(self);
JValue result;
- ArgArray arg_array(NULL, 0);
+ ArgArray arg_array("VL", 2);
arg_array.Append(object);
soa.DecodeMethod(WellKnownClasses::java_lang_ref_FinalizerReference_add)->Invoke(self,
- arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
+ arg_array.GetArray(), arg_array.GetNumBytes(), &result, "VL");
}
void Heap::EnqueueClearedReferences() {
@@ -2330,10 +2330,10 @@ void Heap::EnqueueClearedReferences() {
if (LIKELY(Runtime::Current()->IsStarted())) {
ScopedObjectAccess soa(self);
JValue result;
- ArgArray arg_array(NULL, 0);
+ ArgArray arg_array("VL", 2);
arg_array.Append(cleared_references_.GetList());
soa.DecodeMethod(WellKnownClasses::java_lang_ref_ReferenceQueue_add)->Invoke(soa.Self(),
- arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
+ arg_array.GetArray(), arg_array.GetNumBytes(), &result, "VL");
}
cleared_references_.Clear();
}
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index deea5f6..cb13f27 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -139,13 +139,13 @@ static void CheckMethodArguments(ArtMethod* m, uint32_t* args)
}
void InvokeWithArgArray(const ScopedObjectAccess& soa, ArtMethod* method,
- ArgArray* arg_array, JValue* result, char result_type)
+ ArgArray* arg_array, JValue* result, const char* shorty)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t* args = arg_array->GetArray();
if (UNLIKELY(soa.Env()->check_jni)) {
CheckMethodArguments(method, args);
}
- method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, result_type);
+ method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty);
}
static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj,
@@ -157,7 +157,7 @@ static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj,
JValue result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
+ InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
return result;
}
@@ -175,7 +175,7 @@ static JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccess& soa,
JValue result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
+ InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
return result;
}
@@ -188,7 +188,7 @@ static JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccess& soa,
JValue result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
+ InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
return result;
}
@@ -637,7 +637,7 @@ JValue InvokeWithJValues(const ScopedObjectAccess& soa, jobject obj, jmethodID m
JValue result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
arg_array.BuildArgArray(soa, receiver, args);
- InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()[0]);
+ InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty());
return result;
}
@@ -2437,8 +2437,10 @@ class JNI {
m = c->FindVirtualMethod(name, sig);
}
if (m == NULL) {
+ c->DumpClass(LOG(ERROR), mirror::Class::kDumpClassFullDetail);
LOG(return_errors ? ERROR : FATAL) << "Failed to register native method "
- << PrettyDescriptor(c) << "." << name << sig;
+ << PrettyDescriptor(c) << "." << name << sig << " in "
+ << c->GetDexCache()->GetLocation()->ToModifiedUtf8();
ThrowNoSuchMethodError(soa, c, name, sig, "static or non-static");
return JNI_ERR;
} else if (!m->IsNative()) {
diff --git a/runtime/jni_internal.h b/runtime/jni_internal.h
index cd3c5cb..6eb1aad 100644
--- a/runtime/jni_internal.h
+++ b/runtime/jni_internal.h
@@ -57,7 +57,7 @@ void RegisterNativeMethods(JNIEnv* env, const char* jni_class_name, const JNINat
JValue InvokeWithJValues(const ScopedObjectAccess&, jobject obj, jmethodID mid, jvalue* args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void InvokeWithArgArray(const ScopedObjectAccess& soa, mirror::ArtMethod* method,
- ArgArray *arg_array, JValue* result, char result_type)
+ ArgArray *arg_array, JValue* result, const char* shorty)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
int ThrowNewException(JNIEnv* env, jclass exception_class, const char* msg, jobject cause);
diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc
index fed734e..4c58c84 100644
--- a/runtime/jni_internal_test.cc
+++ b/runtime/jni_internal_test.cc
@@ -134,14 +134,14 @@ class JniInternalTest : public CommonTest {
arg_array.Append(receiver);
}
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "V");
}
void InvokeIdentityByteMethod(bool is_static)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::ArtMethod* method;
mirror::Object* receiver;
- JniInternalTestMakeExecutable(&method, &receiver, is_static, "identity", "(I)I");
+ JniInternalTestMakeExecutable(&method, &receiver, is_static, "identity", "(B)B");
ArgArray arg_array(NULL, 0);
uint32_t* args = arg_array.GetArray();
@@ -154,22 +154,22 @@ class JniInternalTest : public CommonTest {
arg_array.Append(0U);
result.SetB(-1);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "BB");
EXPECT_EQ(0, result.GetB());
args[0] = -1;
result.SetB(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "BB");
EXPECT_EQ(-1, result.GetB());
args[0] = SCHAR_MAX;
result.SetB(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "BB");
EXPECT_EQ(SCHAR_MAX, result.GetB());
args[0] = (SCHAR_MIN << 24) >> 24;
result.SetB(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "BB");
EXPECT_EQ(SCHAR_MIN, result.GetB());
}
@@ -190,22 +190,22 @@ class JniInternalTest : public CommonTest {
arg_array.Append(0U);
result.SetI(-1);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "II");
EXPECT_EQ(0, result.GetI());
args[0] = -1;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "II");
EXPECT_EQ(-1, result.GetI());
args[0] = INT_MAX;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "II");
EXPECT_EQ(INT_MAX, result.GetI());
args[0] = INT_MIN;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "II");
EXPECT_EQ(INT_MIN, result.GetI());
}
@@ -228,28 +228,28 @@ class JniInternalTest : public CommonTest {
value.SetD(0.0);
arg_array.AppendWide(value.GetJ());
result.SetD(-1.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "DD");
EXPECT_EQ(0.0, result.GetD());
value.SetD(-1.0);
args[0] = value.GetJ();
args[1] = value.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "DD");
EXPECT_EQ(-1.0, result.GetD());
value.SetD(DBL_MAX);
args[0] = value.GetJ();
args[1] = value.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "DD");
EXPECT_EQ(DBL_MAX, result.GetD());
value.SetD(DBL_MIN);
args[0] = value.GetJ();
args[1] = value.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "DD");
EXPECT_EQ(DBL_MIN, result.GetD());
}
@@ -271,31 +271,31 @@ class JniInternalTest : public CommonTest {
arg_array.Append(0U);
arg_array.Append(0U);
result.SetI(-1);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "III");
EXPECT_EQ(0, result.GetI());
args[0] = 1;
args[1] = 2;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "III");
EXPECT_EQ(3, result.GetI());
args[0] = -2;
args[1] = 5;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "III");
EXPECT_EQ(3, result.GetI());
args[0] = INT_MAX;
args[1] = INT_MIN;
result.SetI(1234);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "III");
EXPECT_EQ(-1, result.GetI());
args[0] = INT_MAX;
args[1] = INT_MAX;
result.SetI(INT_MIN);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "III");
EXPECT_EQ(-2, result.GetI());
}
@@ -318,35 +318,40 @@ class JniInternalTest : public CommonTest {
arg_array.Append(0U);
arg_array.Append(0U);
result.SetI(-1);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIII");
EXPECT_EQ(0, result.GetI());
args[0] = 1;
args[1] = 2;
args[2] = 3;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIII");
EXPECT_EQ(6, result.GetI());
args[0] = -1;
args[1] = 2;
args[2] = -3;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIII");
EXPECT_EQ(-2, result.GetI());
args[0] = INT_MAX;
args[1] = INT_MIN;
args[2] = INT_MAX;
result.SetI(1234);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIII");
EXPECT_EQ(2147483646, result.GetI());
args[0] = INT_MAX;
args[1] = INT_MAX;
args[2] = INT_MAX;
result.SetI(INT_MIN);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIII");
EXPECT_EQ(2147483645, result.GetI());
}
@@ -370,7 +375,8 @@ class JniInternalTest : public CommonTest {
arg_array.Append(0U);
arg_array.Append(0U);
result.SetI(-1);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIII");
EXPECT_EQ(0, result.GetI());
args[0] = 1;
@@ -378,7 +384,8 @@ class JniInternalTest : public CommonTest {
args[2] = 3;
args[3] = 4;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIII");
EXPECT_EQ(10, result.GetI());
args[0] = -1;
@@ -386,7 +393,8 @@ class JniInternalTest : public CommonTest {
args[2] = -3;
args[3] = 4;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIII");
EXPECT_EQ(2, result.GetI());
args[0] = INT_MAX;
@@ -394,7 +402,8 @@ class JniInternalTest : public CommonTest {
args[2] = INT_MAX;
args[3] = INT_MIN;
result.SetI(1234);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIII");
EXPECT_EQ(-2, result.GetI());
args[0] = INT_MAX;
@@ -402,7 +411,8 @@ class JniInternalTest : public CommonTest {
args[2] = INT_MAX;
args[3] = INT_MAX;
result.SetI(INT_MIN);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIII");
EXPECT_EQ(-4, result.GetI());
}
@@ -427,7 +437,8 @@ class JniInternalTest : public CommonTest {
arg_array.Append(0U);
arg_array.Append(0U);
result.SetI(-1.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIIII");
EXPECT_EQ(0, result.GetI());
args[0] = 1;
@@ -436,7 +447,8 @@ class JniInternalTest : public CommonTest {
args[3] = 4;
args[4] = 5;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIIII");
EXPECT_EQ(15, result.GetI());
args[0] = -1;
@@ -445,7 +457,8 @@ class JniInternalTest : public CommonTest {
args[3] = 4;
args[4] = -5;
result.SetI(0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIIII");
EXPECT_EQ(-3, result.GetI());
args[0] = INT_MAX;
@@ -454,7 +467,8 @@ class JniInternalTest : public CommonTest {
args[3] = INT_MIN;
args[4] = INT_MAX;
result.SetI(1234);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIIII");
EXPECT_EQ(2147483645, result.GetI());
args[0] = INT_MAX;
@@ -463,7 +477,8 @@ class JniInternalTest : public CommonTest {
args[3] = INT_MAX;
args[4] = INT_MAX;
result.SetI(INT_MIN);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "IIIIII");
EXPECT_EQ(2147483643, result.GetI());
}
@@ -489,7 +504,8 @@ class JniInternalTest : public CommonTest {
arg_array.AppendWide(value.GetJ());
arg_array.AppendWide(value2.GetJ());
result.SetD(-1.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDD");
EXPECT_EQ(0.0, result.GetD());
value.SetD(1.0);
@@ -499,7 +515,8 @@ class JniInternalTest : public CommonTest {
args[2] = value2.GetJ();
args[3] = value2.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDD");
EXPECT_EQ(3.0, result.GetD());
value.SetD(1.0);
@@ -509,7 +526,8 @@ class JniInternalTest : public CommonTest {
args[2] = value2.GetJ();
args[3] = value2.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDD");
EXPECT_EQ(-1.0, result.GetD());
value.SetD(DBL_MAX);
@@ -519,7 +537,8 @@ class JniInternalTest : public CommonTest {
args[2] = value2.GetJ();
args[3] = value2.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDD");
EXPECT_EQ(1.7976931348623157e308, result.GetD());
value.SetD(DBL_MAX);
@@ -529,7 +548,8 @@ class JniInternalTest : public CommonTest {
args[2] = value2.GetJ();
args[3] = value2.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDD");
EXPECT_EQ(INFINITY, result.GetD());
}
@@ -558,7 +578,8 @@ class JniInternalTest : public CommonTest {
arg_array.AppendWide(value2.GetJ());
arg_array.AppendWide(value3.GetJ());
result.SetD(-1.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDD");
EXPECT_EQ(0.0, result.GetD());
value.SetD(1.0);
@@ -571,7 +592,8 @@ class JniInternalTest : public CommonTest {
args[4] = value3.GetJ();
args[5] = value3.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDD");
EXPECT_EQ(6.0, result.GetD());
value.SetD(1.0);
@@ -584,7 +606,8 @@ class JniInternalTest : public CommonTest {
args[4] = value3.GetJ();
args[5] = value3.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDD");
EXPECT_EQ(2.0, result.GetD());
}
@@ -616,7 +639,8 @@ class JniInternalTest : public CommonTest {
arg_array.AppendWide(value3.GetJ());
arg_array.AppendWide(value4.GetJ());
result.SetD(-1.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDDD");
EXPECT_EQ(0.0, result.GetD());
value.SetD(1.0);
@@ -632,7 +656,8 @@ class JniInternalTest : public CommonTest {
args[6] = value4.GetJ();
args[7] = value4.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDDD");
EXPECT_EQ(10.0, result.GetD());
value.SetD(1.0);
@@ -648,7 +673,8 @@ class JniInternalTest : public CommonTest {
args[6] = value4.GetJ();
args[7] = value4.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDDD");
EXPECT_EQ(-2.0, result.GetD());
}
@@ -683,7 +709,8 @@ class JniInternalTest : public CommonTest {
arg_array.AppendWide(value4.GetJ());
arg_array.AppendWide(value5.GetJ());
result.SetD(-1.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDDDD");
EXPECT_EQ(0.0, result.GetD());
value.SetD(1.0);
@@ -702,7 +729,8 @@ class JniInternalTest : public CommonTest {
args[8] = value5.GetJ();
args[9] = value5.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDDDD");
EXPECT_EQ(15.0, result.GetD());
value.SetD(1.0);
@@ -721,7 +749,8 @@ class JniInternalTest : public CommonTest {
args[8] = value5.GetJ();
args[9] = value5.GetJ() >> 32;
result.SetD(0.0);
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result,
+ "DDDDDD");
EXPECT_EQ(3.0, result.GetD());
}
@@ -1764,7 +1793,7 @@ TEST_F(JniInternalTest, StaticMainMethod) {
CHECK(started);
Thread::Current()->TransitionFromSuspendedToRunnable();
- method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
+ method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, "VL");
}
TEST_F(JniInternalTest, StaticNopMethod) {
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 575ea03..8fba66a 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -35,7 +35,8 @@ namespace art {
namespace mirror {
extern "C" void art_portable_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*, char);
-extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*, char);
+extern "C" void art_quick_invoke_stub(ArtMethod*, uint32_t*, uint32_t, Thread*, JValue*,
+ const char*);
// TODO: get global references for these
Class* ArtMethod::java_lang_reflect_ArtMethod_ = NULL;
@@ -245,10 +246,11 @@ uint32_t ArtMethod::FindCatchBlock(Class* exception_type, uint32_t dex_pc,
}
void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
- char result_type) {
+ const char* shorty) {
if (kIsDebugBuild) {
self->AssertThreadSuspensionIsAllowable();
CHECK_EQ(kRunnable, self->GetState());
+ CHECK_STREQ(MethodHelper(this).GetShorty(), shorty);
}
// Push a transition back into managed code onto the linked list in thread.
@@ -274,9 +276,9 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
: GetEntryPointFromPortableCompiledCode());
}
if (!IsPortableCompiled()) {
- (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
+ (*art_quick_invoke_stub)(this, args, args_size, self, result, shorty);
} else {
- (*art_portable_invoke_stub)(this, args, args_size, self, result, result_type);
+ (*art_portable_invoke_stub)(this, args, args_size, self, result, shorty[0]);
}
if (UNLIKELY(reinterpret_cast<intptr_t>(self->GetException(NULL)) == -1)) {
// Unusual case where we were running LLVM generated code and an
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index bfa7cbe..bf0d416 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -207,8 +207,8 @@ class MANAGED ArtMethod : public Object {
// Find the method that this method overrides
ArtMethod* FindOverriddenMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, char result_type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
+ const char* shorty) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
EntryPointFromInterpreter* GetEntryPointFromInterpreter() {
return GetFieldPtr<EntryPointFromInterpreter*>(
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index ac8f5ef..0bfa70f 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -220,36 +220,46 @@ mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) {
}
jmethodID m = NULL;
+ const char* shorty;
switch (src_class) {
case Primitive::kPrimBoolean:
m = WellKnownClasses::java_lang_Boolean_valueOf;
+ shorty = "LZ";
break;
case Primitive::kPrimByte:
m = WellKnownClasses::java_lang_Byte_valueOf;
+ shorty = "LB";
break;
case Primitive::kPrimChar:
m = WellKnownClasses::java_lang_Character_valueOf;
+ shorty = "LC";
break;
case Primitive::kPrimDouble:
m = WellKnownClasses::java_lang_Double_valueOf;
+ shorty = "LD";
break;
case Primitive::kPrimFloat:
m = WellKnownClasses::java_lang_Float_valueOf;
+ shorty = "LF";
break;
case Primitive::kPrimInt:
m = WellKnownClasses::java_lang_Integer_valueOf;
+ shorty = "LI";
break;
case Primitive::kPrimLong:
m = WellKnownClasses::java_lang_Long_valueOf;
+ shorty = "LJ";
break;
case Primitive::kPrimShort:
m = WellKnownClasses::java_lang_Short_valueOf;
+ shorty = "LS";
break;
case Primitive::kPrimVoid:
// There's no such thing as a void field, and void methods invoked via reflection return null.
- return NULL;
+ return nullptr;
default:
LOG(FATAL) << static_cast<int>(src_class);
+ shorty = nullptr;
}
ScopedObjectAccessUnchecked soa(Thread::Current());
@@ -257,7 +267,7 @@ mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) {
CHECK_EQ(soa.Self()->GetState(), kRunnable);
}
- ArgArray arg_array(NULL, 0);
+ ArgArray arg_array(nullptr, 0);
JValue result;
if (src_class == Primitive::kPrimDouble || src_class == Primitive::kPrimLong) {
arg_array.AppendWide(value.GetJ());
@@ -266,7 +276,7 @@ mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) {
}
soa.DecodeMethod(m)->Invoke(soa.Self(), arg_array.GetArray(), arg_array.GetNumBytes(),
- &result, 'L');
+ &result, shorty);
return result.GetL();
}
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 09d05d1..4f3437f 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -807,7 +807,7 @@ jobject CreateSystemClassLoader() {
JValue result;
ArgArray arg_array(nullptr, 0);
- InvokeWithArgArray(soa, getSystemClassLoader, &arg_array, &result, 'L');
+ InvokeWithArgArray(soa, getSystemClassLoader, &arg_array, &result, "L");
SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
down_cast<mirror::ClassLoader*>(result.GetL()));
CHECK(class_loader.get() != nullptr);
@@ -1473,12 +1473,11 @@ mirror::ArtMethod* Runtime::CreateCalleeSaveMethod(InstructionSet instruction_se
method->SetFpSpillMask(0);
} else if (instruction_set == kX86_64) {
uint32_t ref_spills =
- (1 << art::x86_64::RBP) | (1 << art::x86_64::RSI) | (1 << art::x86_64::RDI) |
- (1 << art::x86_64::R8) | (1 << art::x86_64::R9) | (1 << art::x86_64::R10) |
- (1 << art::x86_64::R11) | (1 << art::x86_64::R12) | (1 << art::x86_64::R13) |
- (1 << art::x86_64::R14) | (1 << art::x86_64::R15);
+ (1 << art::x86_64::RBX) | (1 << art::x86_64::RBP) | (1 << art::x86_64::R12) |
+ (1 << art::x86_64::R13) | (1 << art::x86_64::R14) | (1 << art::x86_64::R15);
uint32_t arg_spills =
- (1 << art::x86_64::RCX) | (1 << art::x86_64::RDX) | (1 << art::x86_64::RBX);
+ (1 << art::x86_64::RSI) | (1 << art::x86_64::RDX) | (1 << art::x86_64::RCX) |
+ (1 << art::x86_64::R8) | (1 << art::x86_64::R9);
uint32_t core_spills = ref_spills | (type == kRefsAndArgs ? arg_spills : 0) |
(1 << art::x86::kNumberOfCpuRegisters); // fake return address callee save
size_t frame_size = RoundUp((__builtin_popcount(core_spills) /* gprs */ +
diff --git a/runtime/thread.cc b/runtime/thread.cc
index c649765..cb1a37e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -179,7 +179,7 @@ void* Thread::CreateCallback(void* arg) {
JValue result;
ArgArray arg_array(nullptr, 0);
arg_array.Append(receiver);
- m->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
+ m->Invoke(self, arg_array.GetArray(), arg_array.GetNumBytes(), &result, "V");
}
// Detach and delete self.
Runtime::Current()->GetThreadList()->Unregister(self);
@@ -1530,6 +1530,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
// Choose an appropriate constructor and set up the arguments.
const char* signature;
+ const char* shorty;
SirtRef<mirror::String> msg_string(this, nullptr);
if (msg != nullptr) {
// Ensure we remember this and the method over the String allocation.
@@ -1539,14 +1540,18 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
return;
}
if (cause.get() == nullptr) {
+ shorty = "VL";
signature = "(Ljava/lang/String;)V";
} else {
+ shorty = "VLL";
signature = "(Ljava/lang/String;Ljava/lang/Throwable;)V";
}
} else {
if (cause.get() == nullptr) {
+ shorty = "V";
signature = "()V";
} else {
+ shorty = "VL";
signature = "(Ljava/lang/Throwable;)V";
}
}
@@ -1570,7 +1575,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
throw_location.GetDexPc());
SetException(gc_safe_throw_location, exception.get());
} else {
- ArgArray args("VLL", 3);
+ ArgArray args(shorty, strlen(shorty));
args.Append(exception.get());
if (msg != nullptr) {
args.Append(msg_string.get());
@@ -1579,7 +1584,7 @@ void Thread::ThrowNewWrappedException(const ThrowLocation& throw_location,
args.Append(cause.get());
}
JValue result;
- exception_init_method->Invoke(this, args.GetArray(), args.GetNumBytes(), &result, 'V');
+ exception_init_method->Invoke(this, args.GetArray(), args.GetNumBytes(), &result, shorty);
if (LIKELY(!IsExceptionPending())) {
ThrowLocation gc_safe_throw_location(saved_throw_this.get(), saved_throw_method.get(),
throw_location.GetDexPc());