diff options
author | Ian Rogers <irogers@google.com> | 2014-02-11 16:30:46 -0800 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2014-02-11 17:02:21 -0800 |
commit | 0177e53ea521ad58b70c305700dab32f1ac773b7 (patch) | |
tree | db15627a19a04634cf84cecd15b813319d80d225 | |
parent | abaf927f29f6feceb3df3e6ced7d01970ba0dbe9 (diff) | |
download | android_art-0177e53ea521ad58b70c305700dab32f1ac773b7.tar.gz android_art-0177e53ea521ad58b70c305700dab32f1ac773b7.tar.bz2 android_art-0177e53ea521ad58b70c305700dab32f1ac773b7.zip |
Work in the direction of hard float quick ABIs.
Pass a shorty to ArtMethod::Invoke so that register setup can use it.
Document x86-64 ABI.
Add extra debug output for one JNI native method registration fails, namely a
dump of the Class and its dex file's location.
Add hack to get testing of OatMethod's without GC maps working in 64bit.
Change-Id: Ic06b68e18eac33637df2caf5e7e775ff95ae70f3
-rw-r--r-- | compiler/dex/quick/x86/x86_lir.h | 67 | ||||
-rw-r--r-- | runtime/arch/arm/quick_entrypoints_arm.S | 2 | ||||
-rw-r--r-- | runtime/arch/mips/quick_entrypoints_mips.S | 5 | ||||
-rw-r--r-- | runtime/arch/x86/quick_entrypoints_x86.S | 15 | ||||
-rw-r--r-- | runtime/arch/x86_64/quick_entrypoints_x86_64.S | 8 | ||||
-rw-r--r-- | runtime/class_linker.cc | 2 | ||||
-rw-r--r-- | runtime/common_test.h | 26 | ||||
-rw-r--r-- | runtime/debugger.cc | 2 | ||||
-rw-r--r-- | runtime/entrypoints/interpreter/interpreter_entrypoints.cc | 4 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 8 | ||||
-rw-r--r-- | runtime/jni_internal.cc | 16 | ||||
-rw-r--r-- | runtime/jni_internal.h | 2 | ||||
-rw-r--r-- | runtime/jni_internal_test.cc | 127 | ||||
-rw-r--r-- | runtime/mirror/art_method.cc | 10 | ||||
-rw-r--r-- | runtime/mirror/art_method.h | 4 | ||||
-rw-r--r-- | runtime/reflection.cc | 16 | ||||
-rw-r--r-- | runtime/runtime.cc | 11 | ||||
-rw-r--r-- | runtime/thread.cc | 11 |
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 c49f627661..8c385a181f 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 0e5c60ae8d..cf3f72e4d0 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 c60bca0e5e..f9a200a770 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 9c3eb30736..c76c6b269b 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 e01a31b6b4..44bc7a20af 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 978c99bf1a..707082d9ee 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 af7e8aecf8..f7859ea0bc 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 8280c7c9a6..53ac5cc711 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 8a2ce510f5..2067a455af 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 62567d7951..39521b322b 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 deea5f6bc0..cb13f27383 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 cd3c5cbb7f..6eb1aad922 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 fed734ef5e..4c58c84eb4 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 575ea03519..8fba66a45b 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 bfa7cbe10f..bf0d4169ae 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 ac8f5ef6c4..0bfa70f279 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 09d05d1fec..4f3437f105 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 c649765e55..cb1a37efd3 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()); |