Removed compiled resolution trampoline.
Created assembly versions of resolution trampoline for portable and
quick. Removed compiled version from the image.
Change-Id: I183e110c4e102fb45ce6e7f4e855f8bed7986251
diff --git a/src/check_jni.cc b/src/check_jni.cc
index f97e0b3..19f8abf 100644
--- a/src/check_jni.cc
+++ b/src/check_jni.cc
@@ -31,9 +31,9 @@
#include "mirror/object_array-inl.h"
#include "mirror/throwable.h"
#include "object_utils.h"
+#include "runtime.h"
#include "scoped_thread_state_change.h"
#include "thread.h"
-#include "runtime.h"
#define LIBCORE_CPP_JNI_HELPERS
#include <JNIHelp.h> // from libcore
diff --git a/src/class_linker.cc b/src/class_linker.cc
index cee1881..9dee36a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1034,12 +1034,11 @@
return;
}
- // Check if object is an uncompiled method and point the to the interpreter entry point.
+ // Check if object is a method without its code set and point it to the resolution trampoline.
if (obj->IsMethod()) {
mirror::AbstractMethod* method = obj->AsMethod();
if (method->GetCode() == NULL) {
- const void* interpreter_entry = GetInterpreterEntryPoint();
- method->SetCode(interpreter_entry);
+ method->SetCode(GetResolutionTrampoline());
}
}
}
@@ -1607,7 +1606,7 @@
if (method->IsStatic() && !method->IsConstructor()) {
// For static methods excluding the class initializer, install the trampoline.
- method->SetCode(runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData());
+ method->SetCode(GetResolutionTrampoline());
}
if (method->IsNative()) {
diff --git a/src/common_test.h b/src/common_test.h
index 68b0cf6..05b0e05 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -36,6 +36,7 @@
#include "object_utils.h"
#include "os.h"
#include "runtime.h"
+#include "runtime_support.h"
#include "scoped_thread_state_change.h"
#include "ScopedLocalRef.h"
#include "thread.h"
@@ -354,13 +355,6 @@
runtime_->SetJniDlsymLookupStub(CompilerDriver::CreateJniDlsymLookupStub(instruction_set));
runtime_->SetAbstractMethodErrorStubArray(CompilerDriver::CreateAbstractMethodErrorStub(instruction_set));
- for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
- Runtime::TrampolineType type = Runtime::TrampolineType(i);
- if (!runtime_->HasResolutionStubArray(type)) {
- runtime_->SetResolutionStubArray(
- CompilerDriver::CreateResolutionStub(instruction_set, type), type);
- }
- }
if (!runtime_->HasResolutionMethod()) {
runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod());
}
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index d464b42..e6f4b67 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -409,22 +409,6 @@
return res;
}
-mirror::ByteArray* CompilerDriver::CreateResolutionStub(InstructionSet instruction_set,
- Runtime::TrampolineType type) {
- switch (instruction_set) {
- case kArm:
- case kThumb2:
- return arm::ArmCreateResolutionTrampoline(type);
- case kMips:
- return mips::MipsCreateResolutionTrampoline(type);
- case kX86:
- return x86::X86CreateResolutionTrampoline(type);
- default:
- LOG(FATAL) << "Unknown InstructionSet: " << instruction_set;
- return NULL;
- }
-}
-
mirror::ByteArray* CompilerDriver::CreateJniDlsymLookupStub(InstructionSet instruction_set) {
switch (instruction_set) {
case kArm:
diff --git a/src/compiler/driver/compiler_driver.h b/src/compiler/driver/compiler_driver.h
index fae6902..3581f5f 100644
--- a/src/compiler/driver/compiler_driver.h
+++ b/src/compiler/driver/compiler_driver.h
@@ -106,12 +106,6 @@
static mirror::ByteArray* CreateAbstractMethodErrorStub(InstructionSet instruction_set)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- // Generate the trampoline that's invoked by unresolved direct methods
- static mirror::ByteArray* CreateResolutionStub(InstructionSet instruction_set,
- Runtime::TrampolineType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
static mirror::ByteArray* CreateJniDlsymLookupStub(InstructionSet instruction_set)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 97212ce..36b8d26 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -378,12 +378,6 @@
if (!runtime->HasAbstractMethodErrorStubArray()) {
runtime->SetAbstractMethodErrorStubArray(CompilerDriver::CreateAbstractMethodErrorStub(instruction_set));
}
- for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
- Runtime::TrampolineType type = Runtime::TrampolineType(i);
- if (!runtime->HasResolutionStubArray(type)) {
- runtime->SetResolutionStubArray(CompilerDriver::CreateResolutionStub(instruction_set, type), type);
- }
- }
if (!runtime->HasResolutionMethod()) {
runtime->SetResolutionMethod(runtime->CreateResolutionMethod());
}
diff --git a/src/gc/space.cc b/src/gc/space.cc
index e618f07..d7378c3 100644
--- a/src/gc/space.cc
+++ b/src/gc/space.cc
@@ -518,14 +518,6 @@
mirror::Object* ame_stub_array = image_header.GetImageRoot(ImageHeader::kAbstractMethodErrorStubArray);
runtime->SetAbstractMethodErrorStubArray(down_cast<mirror::ByteArray*>(ame_stub_array));
- mirror::Object* resolution_stub_array =
- image_header.GetImageRoot(ImageHeader::kStaticResolutionStubArray);
- runtime->SetResolutionStubArray(
- down_cast<mirror::ByteArray*>(resolution_stub_array), Runtime::kStaticMethod);
- resolution_stub_array = image_header.GetImageRoot(ImageHeader::kUnknownMethodResolutionStubArray);
- runtime->SetResolutionStubArray(
- down_cast<mirror::ByteArray*>(resolution_stub_array), Runtime::kUnknownMethod);
-
mirror::Object* resolution_method = image_header.GetImageRoot(ImageHeader::kResolutionMethod);
runtime->SetResolutionMethod(down_cast<mirror::AbstractMethod*>(resolution_method));
diff --git a/src/image.cc b/src/image.cc
index d6bf635..c746c8e 100644
--- a/src/image.cc
+++ b/src/image.cc
@@ -24,7 +24,7 @@
namespace art {
const byte ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' };
-const byte ImageHeader::kImageVersion[] = { '0', '0', '2', '\0' };
+const byte ImageHeader::kImageVersion[] = { '0', '0', '3', '\0' };
ImageHeader::ImageHeader(uint32_t image_begin,
uint32_t image_roots,
diff --git a/src/image.h b/src/image.h
index 6501328..040e3fe 100644
--- a/src/image.h
+++ b/src/image.h
@@ -83,8 +83,6 @@
enum ImageRoot {
kJniStubArray,
kAbstractMethodErrorStubArray,
- kStaticResolutionStubArray,
- kUnknownMethodResolutionStubArray,
kResolutionMethod,
kCalleeSaveMethod,
kRefsOnlySaveMethod,
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 5638b5b..16ac385 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -354,10 +354,6 @@
image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub());
image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray,
runtime->GetAbstractMethodErrorStubArray());
- image_roots->Set(ImageHeader::kStaticResolutionStubArray,
- runtime->GetResolutionStubArray(Runtime::kStaticMethod));
- image_roots->Set(ImageHeader::kUnknownMethodResolutionStubArray,
- runtime->GetResolutionStubArray(Runtime::kUnknownMethod));
image_roots->Set(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod());
image_roots->Set(ImageHeader::kCalleeSaveMethod,
runtime->GetCalleeSaveMethod(Runtime::kSaveAll));
@@ -490,31 +486,13 @@
}
if (orig == Runtime::Current()->GetResolutionMethod()) {
- // The resolution stub's code points at the unknown resolution trampoline
- ByteArray* orig_res_stub_array_ =
- Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod);
- CHECK(orig->GetCode() == orig_res_stub_array_->GetData());
- ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_));
- copy->SetCode(copy_res_stub_array_->GetData());
+ // The resolution method's code is set to the resolution trampoline when we load the image.
+ copy->SetCode(NULL);
return;
}
- // Non-abstract methods typically have code
- uint32_t code_offset = orig->GetOatCodeOffset();
- const byte* code = NULL;
- if (orig->IsStatic()) {
- // Static methods may point at the resolution trampoline stub
- ByteArray* orig_res_stub_array_ =
- Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod);
- if (reinterpret_cast<int8_t*>(code_offset) == orig_res_stub_array_->GetData()) {
- ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_));
- code = reinterpret_cast<const byte*>(copy_res_stub_array_->GetData());
- }
- }
- if (code == NULL) {
- code = GetOatAddress(code_offset);
- }
- copy->SetCode(code);
+ // Non-abstract methods have code
+ copy->SetCode(GetOatAddress(orig->GetOatCodeOffset()));
if (orig->IsNative()) {
// The native method's pointer is directed to a stub to lookup via dlsym.
diff --git a/src/instrumentation.cc b/src/instrumentation.cc
index a8c2c73..43bab53 100644
--- a/src/instrumentation.cc
+++ b/src/instrumentation.cc
@@ -62,7 +62,7 @@
if (is_initialized || !method->IsStatic() || method->IsConstructor()) {
new_code = class_linker->GetOatCodeFor(method);
} else {
- new_code = Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData();
+ new_code = GetResolutionTrampoline();
}
} else { // !uninstall
if (!interpreter_stubs_installed_ || method->IsNative()) {
@@ -380,7 +380,7 @@
if (LIKELY(!instrumentation_stubs_installed_)) {
const void* code = method->GetCode();
DCHECK(code != NULL);
- if (LIKELY(code != runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData())) {
+ if (LIKELY(code != GetResolutionTrampoline())) {
return code;
}
}
diff --git a/src/mirror/abstract_method-inl.h b/src/mirror/abstract_method-inl.h
index fd02474..a420714 100644
--- a/src/mirror/abstract_method-inl.h
+++ b/src/mirror/abstract_method-inl.h
@@ -20,9 +20,9 @@
#include "abstract_method.h"
#include "dex_file.h"
-#include "oat/runtime/oat_support_entrypoints.h"
#include "object_array.h"
#include "runtime.h"
+#include "runtime_support.h"
namespace art {
namespace mirror {
@@ -117,8 +117,7 @@
if (GetCode() == GetInterpreterEntryPoint()) {
return;
}
- Runtime* runtime = Runtime::Current();
- if (GetCode() == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
+ if (GetCode() == GetResolutionTrampoline()) {
return;
}
DCHECK(IsWithinCode(pc))
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
index 1276f78..dcf6bb8 100644
--- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "runtime_support.h"
#include "oat/runtime/oat_support_entrypoints.h"
+#include "runtime_support.h"
namespace art {
@@ -97,9 +97,6 @@
extern "C" int32_t art_quick_string_compareto(void*, void*);
// Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*,
- mirror::AbstractMethod**, Thread*,
- Runtime::TrampolineType);
extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -121,12 +118,6 @@
extern "C" void art_quick_throw_null_pointer_exception_from_code();
extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-// Instrumentation entrypoints.
-extern "C" void art_quick_instrumentation_entry_from_code(void*);
-extern "C" void art_quick_instrumentation_exit_from_code();
-extern "C" void art_quick_interpreter_entry(void*);
-extern "C" void art_quick_deoptimize();
-
void InitEntryPoints(EntryPoints* points) {
// Alloc
points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
@@ -206,7 +197,6 @@
points->pMemcpy = memcpy;
// Invocation
- points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -228,20 +218,4 @@
points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
};
-uintptr_t GetInstrumentationExitPc() {
- return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
-}
-
-uintptr_t GetDeoptimizationEntryPoint() {
- return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
-}
-
-void* GetInstrumentationEntryPoint() {
- return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
-}
-
-void* GetInterpreterEntryPoint() {
- return reinterpret_cast<void*>(art_quick_interpreter_entry);
-}
-
} // namespace art
diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S
index 0e34d40..2aa380b 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -246,6 +246,47 @@
INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
+ /*
+ * Portable resolution trampoline.
+ */
+ .extern artPortableResolutionTrampoline
+ENTRY art_portable_resolution_trampoline
+ push {r0, r1, r2, r3, lr} @ spill regs
+ .save {r0, r1, r2, r3, lr}
+ .pad #20
+ .cfi_adjust_cfa_offset 20
+ sub sp, #12 @ pad stack pointer to align frame
+ .pad #12
+ mov r2, r9 @ pass Thread::Current
+ mov r1, sp @ pass stack pointer
+ blx artPortableResolutionTrampoline @ (method_idx, sp, Thread*)
+ mov r12, r0 @ save method code pointer result
+ add sp, #12 @ remove padding from stack pointer
+ .cfi_adjust_cfa_offset -12
+ pop {r0, r1, r2, r3, lr} @ restore regs
+ .cfi_adjust_cfa_offset -20
+ cmp r12, #0 @ is method code null?
+ bxne r12 @ if non-null, tail call to method's code
+ bx lr @ otherwise, return to caller to handle exception
+END art_portable_resolution_trampoline
+
+ /*
+ * Quick resolution trampoline.
+ */
+ .extern artQuickResolutionTrampoline
+ENTRY art_quick_resolution_trampoline
+ SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME @ save callee saves in case allocation triggers GC
+ mov r2, r9 @ pass Thread::Current
+ mov r1, sp @ pass stack pointer
+ blx artQuickResolutionTrampoline @ (method_idx, sp, Thread*)
+ mov r12, r0 @ save method code pointer result
+ add sp, #4 @ set up stack pointer
+ .cfi_adjust_cfa_offset -4
+ pop {r0-r3, r5-r8, r10-r11, lr} @ 11 words, r0 will hold method*
+ .cfi_adjust_cfa_offset -44
+ bx r12 @ leaf call to method code
+END art_quick_resolution_trampoline
+
/*
* Portable invocation stub.
* On entry:
diff --git a/src/oat/runtime/arm/stub_arm.cc b/src/oat/runtime/arm/stub_arm.cc
index 33354bd..7c97f4c 100644
--- a/src/oat/runtime/arm/stub_arm.cc
+++ b/src/oat/runtime/arm/stub_arm.cc
@@ -28,70 +28,6 @@
namespace art {
namespace arm {
-mirror::ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type) {
- UniquePtr<ArmAssembler> assembler(static_cast<ArmAssembler*>(Assembler::Create(kArm)));
-#if !defined(ART_USE_PORTABLE_COMPILER)
- // | Out args |
- // | Method* | <- SP on entry
- // | LR | return address into caller
- // | ... | callee saves
- // | R3 | possible argument
- // | R2 | possible argument
- // | R1 | possible argument
- // | R0 | junk on call to UnresolvedDirectMethodTrampolineFromCode, holds result Method*
- // | Method* | Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
- // Save callee saves and ready frame for exception delivery
- RegList save = (1 << R1) | (1 << R2) | (1 << R3) | (1 << R5) | (1 << R6) | (1 << R7) | (1 << R8) |
- (1 << R10) | (1 << R11) | (1 << LR);
- // TODO: enable when GetCalleeSaveMethod is available at stub generation time
- // DCHECK_EQ(save, Runtime::Current()->GetCalleeSaveMethod(Runtime::kRefsAndArgs)->GetCoreSpillMask());
- __ PushList(save);
- __ LoadFromOffset(kLoadWord, R12, TR,
- ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
- __ mov(R2, ShifterOperand(TR)); // Pass Thread::Current() in R2
- __ LoadImmediate(R3, type);
- __ IncreaseFrameSize(8); // 2 words of space for alignment
- __ mov(R1, ShifterOperand(SP)); // Pass SP
- // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
- __ blx(R12);
- __ mov(R12, ShifterOperand(R0)); // Save code address returned into R12
- // Restore registers which may have been modified by GC, "R0" will hold the Method*
- __ DecreaseFrameSize(4);
- __ PopList((1 << R0) | save);
- __ bx(R12); // Leaf call to method's code
-
- __ bkpt(0);
-#else // ART_USE_PORTABLE_COMPILER
- RegList save = (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3) | (1 << LR);
- __ PushList(save);
- __ LoadFromOffset(kLoadWord, R12, TR,
- ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
- __ mov(R2, ShifterOperand(TR)); // Pass Thread::Current() in R2
- __ LoadImmediate(R3, type); // Pass is_static
- __ mov(R1, ShifterOperand(SP)); // Pass sp for Method** callee_addr
- __ IncreaseFrameSize(12); // 3 words of space for alignment
- // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
- __ blx(R12);
- __ mov(R12, ShifterOperand(R0)); // Save code address returned into R12
- __ DecreaseFrameSize(12);
- __ PopList(save);
- __ cmp(R12, ShifterOperand(0));
- __ bx(R12, NE); // If R12 != 0 tail call method's code
-
- __ bx(LR); // Return to caller to handle exception
-#endif // ART_USE_PORTABLE_COMPILER
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- Thread* self = Thread::Current();
- SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
- CHECK(resolution_trampoline.get() != NULL);
- MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.get();
-}
-
typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);
mirror::ByteArray* CreateAbstractMethodErrorStub() {
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 599b14c..b201b07 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -99,9 +99,6 @@
extern "C" int32_t art_quick_string_compareto(void*, void*);
// Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*,
- mirror::AbstractMethod**, Thread*,
- Runtime::TrampolineType);
extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -123,12 +120,6 @@
extern "C" void art_quick_throw_null_pointer_exception_from_code();
extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-// Instrumentation entrypoints.
-extern "C" void art_quick_instrumentation_entry_from_code(void*);
-extern "C" void art_quick_instrumentation_exit_from_code();
-extern "C" void art_quick_interpreter_entry(void*);
-extern "C" void art_quick_deoptimize();
-
void InitEntryPoints(EntryPoints* points) {
// Alloc
points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
@@ -207,7 +198,6 @@
points->pMemcpy = memcpy;
// Invocation
- points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -229,21 +219,4 @@
points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
};
-uintptr_t GetInstrumentationExitPc() {
- return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
-}
-
-uintptr_t GetDeoptimizationEntryPoint() {
- UNIMPLEMENTED(FATAL);
- return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
-}
-
-void* GetInstrumentationEntryPoint() {
- return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
-}
-
-void* GetInterpreterEntryPoint() {
- return reinterpret_cast<void*>(art_quick_interpreter_entry);
-}
-
} // namespace art
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index 31b1846..f5f8d9b 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -378,16 +378,16 @@
SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME # save callee saves in case allocation triggers GC
lw $a2, 48($sp) # pass caller Method*
move $t0, $sp # save $sp
- addiu $sp, $sp, -16 # make space for extra args
- .cfi_adjust_cfa_offset 16
+ addiu $sp, $sp, -32 # make space for extra args
+ .cfi_adjust_cfa_offset 32
move $a3, rSELF # pass Thread::Current
- sw $gp, 12($sp) # save $gp
+ sw $gp, 20($sp) # save $gp
.cfi_rel_offset 28, 12
jal \cxx_name # (method_idx, this, caller, Thread*, $sp)
sw $t0, 16($sp) # pass $sp
- lw $gp, 12($sp) # restore $gp
- addiu $sp, $sp, 16 # release out args
- .cfi_adjust_cfa_offset -16
+ lw $gp, 20($sp) # restore $gp
+ addiu $sp, $sp, 32 # release out args
+ .cfi_adjust_cfa_offset -32
move $a0, $v0 # save target Method*
move $t9, $v1 # save $v0->code_
RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
@@ -408,6 +408,70 @@
INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
+ /*
+ * Portable resolution trampoline.
+ */
+ .extern artPortableResolutionTrampoline
+ENTRY art_portable_resolution_trampoline
+ GENERATE_GLOBAL_POINTER
+ addiu $sp, $sp, -32 # leave room for $a0, $a1, $a2, $a3, and $ra
+ .cfi_adjust_cfa_offset 32
+ sw $ra, 16($sp)
+ .cfi_rel_offset 31, 16
+ sw $a3, 12($sp)
+ .cfi_rel_offset 7, 12
+ sw $a2, 8($sp)
+ .cfi_rel_offset 6, 8
+ sw $a1, 4($sp)
+ .cfi_rel_offset 5, 4
+ sw $a0, 0($sp)
+ .cfi_rel_offset 4, 0
+ move $a2, $s1 # pass Thread::Current()
+ jal artPortableResolutionTrampoline # (method_idx, sp, Thread*)
+ move $a1, $sp # pass stack pointer
+ lw $a0, 0($sp) # restore registers from stack
+ lw $a1, 4($sp)
+ lw $a2, 8($sp)
+ lw $a3, 12($sp)
+ lw $ra, 16($sp)
+ beq $v0, $zero, resolve_fail
+ addiu $sp, $sp, 32 # restore the stack
+ .cfi_adjust_cfa_offset -32
+ jr $t9 # leaf call to method's code
+ move $t9, $v0 # put method code result in $t9
+resolve_fail:
+ jr $ra
+ nop
+END art_portable_resolution_trampoline
+
+ /*
+ * Quick resolution trampoline.
+ */
+ .extern artQuickResolutionTrampoline
+ENTRY art_quick_resolution_trampoline
+ GENERATE_GLOBAL_POINTER
+ SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+ move $a2, $s1 # pass Thread::Current()
+ jal artQuickResolutionTrampoline # (method_idx, sp, Thread*)
+ move $a1, $sp # pass stack pointer
+ move $t9, $v0 # put method code result in $t9
+ lw $a0, 0($sp) # restore registers from stack
+ lw $a1, 4($sp)
+ lw $a2, 8($sp)
+ lw $a3, 12($sp)
+ lw $s2, 16($sp)
+ lw $s3, 20($sp)
+ lw $s4, 24($sp)
+ lw $s5, 28($sp)
+ lw $s6, 32($sp)
+ lw $s7, 36($sp)
+ lw $fp, 40($sp)
+ lw $ra, 44($sp)
+ jr $t9 # leaf call to method's code
+ addiu $sp, $sp, 48 # restore the stack
+ .cfi_adjust_cfa_offset -48
+END art_quick_resolution_trampoline
+
/*
* Common invocation stub for portable and quick.
* On entry:
diff --git a/src/oat/runtime/mips/stub_mips.cc b/src/oat/runtime/mips/stub_mips.cc
index 60ec9de..a1adf66 100644
--- a/src/oat/runtime/mips/stub_mips.cc
+++ b/src/oat/runtime/mips/stub_mips.cc
@@ -28,100 +28,6 @@
namespace art {
namespace mips {
-mirror::ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type) {
- UniquePtr<MipsAssembler> assembler(static_cast<MipsAssembler*>(Assembler::Create(kMips)));
-#if !defined(ART_USE_PORTABLE_COMPILER)
- // | Out args |
- // | Method* | <- SP on entry
- // | RA | return address into caller
- // | ... | callee saves
- // | A3 | possible argument
- // | A2 | possible argument
- // | A1 | possible argument
- // | A0/Method* | Callee save Method* set up by UnresolvedDirectMethodTrampolineFromCode
- // Save callee saves and ready frame for exception delivery
- __ AddConstant(SP, SP, -48);
- __ StoreToOffset(kStoreWord, RA, SP, 44);
- __ StoreToOffset(kStoreWord, FP, SP, 40);
- __ StoreToOffset(kStoreWord, S7, SP, 36);
- __ StoreToOffset(kStoreWord, S6, SP, 32);
- __ StoreToOffset(kStoreWord, S5, SP, 28);
- __ StoreToOffset(kStoreWord, S4, SP, 24);
- __ StoreToOffset(kStoreWord, S3, SP, 20);
- __ StoreToOffset(kStoreWord, S2, SP, 16);
- __ StoreToOffset(kStoreWord, A3, SP, 12);
- __ StoreToOffset(kStoreWord, A2, SP, 8);
- __ StoreToOffset(kStoreWord, A1, SP, 4);
-
- __ LoadFromOffset(kLoadWord, T9, S1,
- ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
- __ Move(A2, S1); // Pass Thread::Current() in A2
- __ LoadImmediate(A3, type); // Pass is_static
- __ Move(A1, SP); // Pass SP for Method** callee_addr
- __ Jalr(T9); // Call to unresolved direct method trampoline (method_idx, sp, Thread*, is_static)
-
- // Restore registers which may have been modified by GC
- __ LoadFromOffset(kLoadWord, A0, SP, 0);
- __ LoadFromOffset(kLoadWord, A1, SP, 4);
- __ LoadFromOffset(kLoadWord, A2, SP, 8);
- __ LoadFromOffset(kLoadWord, A3, SP, 12);
- __ LoadFromOffset(kLoadWord, S2, SP, 16);
- __ LoadFromOffset(kLoadWord, S3, SP, 20);
- __ LoadFromOffset(kLoadWord, S4, SP, 24);
- __ LoadFromOffset(kLoadWord, S5, SP, 28);
- __ LoadFromOffset(kLoadWord, S6, SP, 32);
- __ LoadFromOffset(kLoadWord, S7, SP, 36);
- __ LoadFromOffset(kLoadWord, FP, SP, 40);
- __ LoadFromOffset(kLoadWord, RA, SP, 44);
- __ AddConstant(SP, SP, 48);
-
- __ Move(T9, V0); // Put method's code in T9
- __ Jr(T9); // Leaf call to method's code
-
- __ Break();
-#else // ART_USE_PORTABLE_COMPILER
- // Build frame and save argument registers and RA.
- __ AddConstant(SP, SP, -32);
- __ StoreToOffset(kStoreWord, RA, SP, 28);
- __ StoreToOffset(kStoreWord, A3, SP, 24);
- __ StoreToOffset(kStoreWord, A2, SP, 20);
- __ StoreToOffset(kStoreWord, A1, SP, 16);
- __ StoreToOffset(kStoreWord, A0, SP, 12);
-
- __ LoadFromOffset(kLoadWord, T9, S1,
- ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode));
- __ Move(A2, S1); // Pass Thread::Current() in A2
- __ LoadImmediate(A3, type); // Pass is_static
- __ Move(A1, SP); // Pass SP for Method** callee_addr
- __ Jalr(T9); // Call to unresolved direct method trampoline (callee, callee_addr, Thread*, is_static)
-
- // Restore frame, argument registers, and RA.
- __ LoadFromOffset(kLoadWord, A0, SP, 12);
- __ LoadFromOffset(kLoadWord, A1, SP, 16);
- __ LoadFromOffset(kLoadWord, A2, SP, 20);
- __ LoadFromOffset(kLoadWord, A3, SP, 24);
- __ LoadFromOffset(kLoadWord, RA, SP, 28);
- __ AddConstant(SP, SP, 32);
-
- Label resolve_fail;
- __ EmitBranch(V0, ZERO, &resolve_fail, true);
- __ Jr(V0); // If V0 != 0 tail call method's code
- __ Bind(&resolve_fail, false);
- __ Jr(RA); // Return to caller to handle exception
-#endif // ART_USE_PORTABLE_COMPILER
-
- assembler->EmitSlowPaths();
-
- size_t cs = assembler->CodeSize();
- Thread* self = Thread::Current();
- SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
- CHECK(resolution_trampoline.get() != NULL);
- MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.get();
-}
-
typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);
mirror::ByteArray* CreateAbstractMethodErrorStub() {
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
index 9cd9cc7..5be1e49 100644
--- a/src/oat/runtime/oat_support_entrypoints.h
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -112,9 +112,6 @@
void* (*pMemcpy)(void*, const void*, size_t);
// Invocation
- const void* (*pUnresolvedDirectMethodTrampolineFromCode)(mirror::AbstractMethod*,
- mirror::AbstractMethod**, Thread*,
- Runtime::TrampolineType);
void (*pInvokeDirectTrampolineWithAccessCheck)(uint32_t, void*);
void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
void (*pInvokeInterfaceTrampolineWithAccessCheck)(uint32_t, void*);
@@ -163,18 +160,6 @@
// Change the debugger entry point in the data structure.
void ChangeDebuggerEntryPoint(EntryPoints* points, bool enabled);
-// The return_pc of instrumentation exit stub.
-uintptr_t GetInstrumentationExitPc();
-
-// Entry point for deoptimization.
-uintptr_t GetDeoptimizationEntryPoint();
-
-// Return address of instrumentation stub.
-void* GetInstrumentationEntryPoint();
-
-// Return address of interpreter stub.
-void* GetInterpreterEntryPoint();
-
} // namespace art
#endif // ART_SRC_OAT_RUNTIME_OAT_SUPPORT_ENTRYPOINTS_H_
diff --git a/src/oat/runtime/stub.h b/src/oat/runtime/stub.h
index 2679793..ee39273 100644
--- a/src/oat/runtime/stub.h
+++ b/src/oat/runtime/stub.h
@@ -28,8 +28,6 @@
namespace arm {
mirror::ByteArray* CreateAbstractMethodErrorStub()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ByteArray* ArmCreateResolutionTrampoline(Runtime::TrampolineType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::ByteArray* CreateJniDlsymLookupStub()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
}
@@ -37,8 +35,6 @@
namespace mips {
mirror::ByteArray* CreateAbstractMethodErrorStub()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ByteArray* MipsCreateResolutionTrampoline(Runtime::TrampolineType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::ByteArray* CreateJniDlsymLookupStub()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
}
@@ -46,8 +42,6 @@
namespace x86 {
mirror::ByteArray* CreateAbstractMethodErrorStub()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- mirror::ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
mirror::ByteArray* CreateJniDlsymLookupStub()
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
}
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index 56fc07f..230421a 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -35,11 +35,94 @@
namespace art {
-#if !defined(ART_USE_PORTABLE_COMPILER)
-// Lazily resolve a method. Called by stub code.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod* called,
- mirror::AbstractMethod** sp, Thread* thread,
- Runtime::TrampolineType type)
+// Lazily resolve a method for portable. Called by stub code.
+extern "C" const void* artPortableResolutionTrampoline(mirror::AbstractMethod* called,
+ mirror::AbstractMethod** called_addr,
+ Thread* thread)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ uint32_t dex_pc;
+ mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
+
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ InvokeType invoke_type;
+ uint32_t dex_method_idx;
+ DCHECK(called->IsRuntimeMethod());
+ const DexFile::CodeItem* code_item = MethodHelper(caller).GetCodeItem();
+ CHECK_LT(dex_pc, code_item->insns_size_in_code_units_);
+ const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
+ Instruction::Code instr_code = instr->Opcode();
+ switch (instr_code) {
+ case Instruction::INVOKE_DIRECT: // Fall-through.
+ case Instruction::INVOKE_DIRECT_RANGE:
+ invoke_type = kDirect;
+ break;
+ case Instruction::INVOKE_STATIC: // Fall-through.
+ case Instruction::INVOKE_STATIC_RANGE:
+ invoke_type = kStatic;
+ break;
+ case Instruction::INVOKE_SUPER: // Fall-through.
+ case Instruction::INVOKE_SUPER_RANGE:
+ invoke_type = kSuper;
+ break;
+ case Instruction::INVOKE_VIRTUAL: // Fall-through.
+ case Instruction::INVOKE_VIRTUAL_RANGE:
+ invoke_type = kVirtual;
+ break;
+ default:
+ LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
+ invoke_type = kDirect; // Avoid used uninitialized warnings.
+ }
+ DecodedInstruction dec_insn(instr);
+ dex_method_idx = dec_insn.vB;
+ called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
+ const void* code = NULL;
+ if (LIKELY(!thread->IsExceptionPending())) {
+ // Incompatible class change should have been handled in resolve method.
+ CHECK(!called->CheckIncompatibleClassChange(invoke_type));
+ // Ensure that the called method's class is initialized.
+ mirror::Class* called_class = called->GetDeclaringClass();
+ linker->EnsureInitialized(called_class, true, true);
+ if (LIKELY(called_class->IsInitialized())) {
+ code = called->GetCode();
+ // TODO: remove this after we solve the link issue.
+ { // for lazy link.
+ if (code == NULL) {
+ code = linker->GetOatCodeFor(called);
+ }
+ }
+ } else if (called_class->IsInitializing()) {
+ if (invoke_type == kStatic) {
+ // Class is still initializing, go to oat and grab code (trampoline must be left in place
+ // until class is initialized to stop races between threads).
+ code = linker->GetOatCodeFor(called);
+ } else {
+ // No trampoline for non-static methods.
+ code = called->GetCode();
+ // TODO: remove this after we solve the link issue.
+ { // for lazy link.
+ if (code == NULL) {
+ code = linker->GetOatCodeFor(called);
+ }
+ }
+ }
+ } else {
+ DCHECK(called_class->IsErroneous());
+ }
+ }
+ if (LIKELY(code != NULL)) {
+ // Expect class to at least be initializing.
+ DCHECK(called->GetDeclaringClass()->IsInitializing());
+ // Don't want infinite recursion.
+ DCHECK(code != GetResolutionTrampoline());
+ // Set up entry into main method
+ *called_addr = called;
+ }
+ return code;
+}
+
+// Lazily resolve a method for quick. Called by stub code.
+extern "C" const void* artQuickResolutionTrampoline(mirror::AbstractMethod* called,
+ mirror::AbstractMethod** sp, Thread* thread)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
#if defined(__arm__)
// On entry the stack pointed by sp is:
@@ -122,8 +205,7 @@
const char* shorty;
uint32_t shorty_len;
#endif
- if (type == Runtime::kUnknownMethod) {
- DCHECK(called->IsRuntimeMethod());
+ if (called->IsRuntimeMethod()) {
uint32_t dex_pc = caller->ToDexPc(caller_pc);
const DexFile::CodeItem* code = MethodHelper(caller).GetCodeItem();
CHECK_LT(dex_pc, code->insns_size_in_code_units_);
@@ -156,8 +238,7 @@
shorty = linker->MethodShorty(dex_method_idx, caller, &shorty_len);
#endif
} else {
- DCHECK(!called->IsRuntimeMethod());
- invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
+ invoke_type = kStatic;
dex_method_idx = called->GetDexMethodIndex();
#if !defined(__i386__)
MethodHelper mh(called);
@@ -212,7 +293,7 @@
}
#endif
// Resolve method filling in dex cache
- if (type == Runtime::kUnknownMethod) {
+ if (called->IsRuntimeMethod()) {
called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
}
const void* code = NULL;
@@ -248,105 +329,12 @@
// Expect class to at least be initializing.
DCHECK(called->GetDeclaringClass()->IsInitializing());
// Don't want infinite recursion.
- DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
+ DCHECK(code != GetResolutionTrampoline());
// Set up entry into main method
regs[0] = reinterpret_cast<uintptr_t>(called);
}
return code;
}
-#else // ART_USE_PORTABLE_COMPILER
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod* called,
- mirror::AbstractMethod** called_addr,
- Thread* thread, Runtime::TrampolineType type)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- uint32_t dex_pc;
- mirror::AbstractMethod* caller = thread->GetCurrentMethod(&dex_pc);
-
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- InvokeType invoke_type;
- uint32_t dex_method_idx;
- if (type == Runtime::kUnknownMethod) {
- DCHECK(called->IsRuntimeMethod());
- 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();
- switch (instr_code) {
- case Instruction::INVOKE_DIRECT: // Fall-through.
- case Instruction::INVOKE_DIRECT_RANGE:
- invoke_type = kDirect;
- break;
- case Instruction::INVOKE_STATIC: // Fall-through.
- case Instruction::INVOKE_STATIC_RANGE:
- invoke_type = kStatic;
- break;
- case Instruction::INVOKE_SUPER: // Fall-through.
- case Instruction::INVOKE_SUPER_RANGE:
- invoke_type = kSuper;
- break;
- case Instruction::INVOKE_VIRTUAL: // Fall-through.
- case Instruction::INVOKE_VIRTUAL_RANGE:
- invoke_type = kVirtual;
- break;
- default:
- LOG(FATAL) << "Unexpected call into trampoline: " << instr->DumpString(NULL);
- invoke_type = kDirect; // Avoid used uninitialized warnings.
- }
- DecodedInstruction dec_insn(instr);
- dex_method_idx = dec_insn.vB;
- } else {
- DCHECK(!called->IsRuntimeMethod());
- invoke_type = (type == Runtime::kStaticMethod) ? kStatic : kDirect;
- dex_method_idx = called->GetDexMethodIndex();
- }
- if (type == Runtime::kUnknownMethod) {
- called = linker->ResolveMethod(dex_method_idx, caller, invoke_type);
- }
- const void* code = NULL;
- if (LIKELY(!thread->IsExceptionPending())) {
- // Incompatible class change should have been handled in resolve method.
- CHECK(!called->CheckIncompatibleClassChange(invoke_type));
- // Ensure that the called method's class is initialized.
- mirror::Class* called_class = called->GetDeclaringClass();
- linker->EnsureInitialized(called_class, true, true);
- if (LIKELY(called_class->IsInitialized())) {
- code = called->GetCode();
- // TODO: remove this after we solve the link issue.
- { // for lazy link.
- if (code == NULL) {
- code = linker->GetOatCodeFor(called);
- }
- }
- } else if (called_class->IsInitializing()) {
- if (invoke_type == kStatic) {
- // Class is still initializing, go to oat and grab code (trampoline must be left in place
- // until class is initialized to stop races between threads).
- code = linker->GetOatCodeFor(called);
- } else {
- // No trampoline for non-static methods.
- code = called->GetCode();
- // TODO: remove this after we solve the link issue.
- { // for lazy link.
- if (code == NULL) {
- code = linker->GetOatCodeFor(called);
- }
- }
- }
- } else {
- DCHECK(called_class->IsErroneous());
- }
- }
- if (LIKELY(code != NULL)) {
- // Expect class to at least be initializing.
- DCHECK(called->GetDeclaringClass()->IsInitializing());
- // Don't want infinite recursion.
- DCHECK(code != Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod)->GetData());
- // Set up entry into main method
- *called_addr = called;
- }
- return code;
-}
-#endif // ART_USE_PORTABLE_COMPILER
// Called by the AbstractMethodError. Called by stub code.
extern void ThrowAbstractMethodErrorFromCode(mirror::AbstractMethod* method, Thread* self,
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index 708e04e..2e35d78 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -82,9 +82,6 @@
extern "C" void* art_quick_memcpy(void*, const void*, size_t);
// Invoke entrypoints.
-const void* UnresolvedDirectMethodTrampolineFromCode(mirror::AbstractMethod*,
- mirror::AbstractMethod**, Thread*,
- Runtime::TrampolineType);
extern "C" void art_quick_invoke_direct_trampoline_with_access_check(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline(uint32_t, void*);
extern "C" void art_quick_invoke_interface_trampoline_with_access_check(uint32_t, void*);
@@ -106,12 +103,6 @@
extern "C" void art_quick_throw_null_pointer_exception_from_code();
extern "C" void art_quick_throw_stack_overflow_from_code(void*);
-// Instrumentation entrypoints.
-extern "C" void art_quick_instrumentation_entry_from_code(void*);
-extern "C" void art_quick_instrumentation_exit_from_code();
-extern "C" void art_quick_interpreter_entry(void*);
-extern "C" void art_quick_deoptimize();
-
void InitEntryPoints(EntryPoints* points) {
// Alloc
points->pAllocArrayFromCode = art_quick_alloc_array_from_code;
@@ -190,7 +181,6 @@
points->pMemcpy = art_quick_memcpy;
// Invocation
- points->pUnresolvedDirectMethodTrampolineFromCode = UnresolvedDirectMethodTrampolineFromCode;
points->pInvokeDirectTrampolineWithAccessCheck = art_quick_invoke_direct_trampoline_with_access_check;
points->pInvokeInterfaceTrampoline = art_quick_invoke_interface_trampoline;
points->pInvokeInterfaceTrampolineWithAccessCheck = art_quick_invoke_interface_trampoline_with_access_check;
@@ -212,20 +202,4 @@
points->pThrowStackOverflowFromCode = art_quick_throw_stack_overflow_from_code;
};
-uintptr_t GetInstrumentationExitPc() {
- return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
-}
-
-uintptr_t GetDeoptimizationEntryPoint() {
- return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
-}
-
-void* GetInstrumentationEntryPoint() {
- return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
-}
-
-void* GetInterpreterEntryPoint() {
- return reinterpret_cast<void*>(art_quick_interpreter_entry);
-}
-
} // namespace art
diff --git a/src/oat/runtime/x86/runtime_support_x86.S b/src/oat/runtime/x86/runtime_support_x86.S
index 3ca42d1..22330c9 100644
--- a/src/oat/runtime/x86/runtime_support_x86.S
+++ b/src/oat/runtime/x86/runtime_support_x86.S
@@ -301,6 +301,50 @@
INVOKE_TRAMPOLINE art_quick_invoke_super_trampoline_with_access_check, artInvokeSuperTrampolineWithAccessCheck
INVOKE_TRAMPOLINE art_quick_invoke_virtual_trampoline_with_access_check, artInvokeVirtualTrampolineWithAccessCheck
+ /*
+ * Portable resolution trampoline.
+ */
+DEFINE_FUNCTION art_portable_resolution_trampoline
+ PUSH ebp // stash %ebp
+ movl %esp, %ebp // save %esp
+ subl LITERAL(8), %esp // align stack
+ movl 8(%ebp), %eax // load the called method* into %eax
+ leal 8(%ebp), %edx // put the called method* address in %edx
+ pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
+ PUSH edx // pass called method* address
+ PUSH eax // pass method*
+ call SYMBOL(artPortableResolutionTrampoline) // (method_idx, sp, Thread*)
+ leave // restore the stack
+ cmpl LITERAL(0), %eax // check if returned method code is null
+ je resolve_fail // if null, jump to return to handle
+ jmp *%eax // otherwise, tail call to intended method
+resolve_fail:
+ ret
+END_FUNCTION art_portable_resolution_trampoline
+
+ /*
+ * Quick resolution trampoline.
+ */
+DEFINE_FUNCTION art_quick_resolution_trampoline
+ SETUP_REF_AND_ARGS_CALLEE_SAVE_FRAME
+ movl %esp, %ecx // save stack pointer
+ PUSH eax // align stack
+ pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
+ PUSH ecx // pass stack pointer
+ PUSH eax // pass method*
+ call SYMBOL(artQuickResolutionTrampoline) // (method_idx, sp, Thread*)
+ movl %eax, %edi // save returned code pointer in %edi
+ addl LITERAL(16), %esp // pop arguments
+ POP eax // restore registers
+ POP ecx
+ POP edx
+ POP ebx
+ POP ebp
+ POP esi
+ xchgl %edi, (%esp) // swap %edi and code pointer
+ ret // tail call to intended method
+END_FUNCTION art_quick_resolution_trampoline
+
/*
* Portable invocation stub.
* On entry:
diff --git a/src/oat/runtime/x86/stub_x86.cc b/src/oat/runtime/x86/stub_x86.cc
index 14c9ce4..3f85b28 100644
--- a/src/oat/runtime/x86/stub_x86.cc
+++ b/src/oat/runtime/x86/stub_x86.cc
@@ -28,80 +28,6 @@
namespace art {
namespace x86 {
-mirror::ByteArray* X86CreateResolutionTrampoline(Runtime::TrampolineType type) {
- UniquePtr<X86Assembler> assembler(static_cast<X86Assembler*>(Assembler::Create(kX86)));
-
-#if !defined(ART_USE_PORTABLE_COMPILER)
- // Set up the callee save frame to conform with Runtime::CreateCalleeSaveMethod(kRefsAndArgs)
- // return address
- __ pushl(EDI);
- __ pushl(ESI);
- __ pushl(EBP);
- __ pushl(EBX);
- __ pushl(EDX);
- __ pushl(ECX);
- __ pushl(EAX); // <-- callee save Method* to go here
- __ movl(ECX, ESP); // save ESP
- __ pushl(Immediate(type)); // pass is_static
- __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // Thread*
- __ pushl(ECX); // pass ESP for Method*
- __ pushl(EAX); // pass Method*
-
- // Call to resolve method.
- __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode)),
- X86ManagedRegister::FromCpuRegister(ECX));
-
- __ movl(EDI, EAX); // save code pointer in EDI
- __ addl(ESP, Immediate(16)); // Pop arguments
- __ popl(EAX); // Restore args.
- __ popl(ECX);
- __ popl(EDX);
- __ popl(EBX);
- __ popl(EBP); // Restore callee saves.
- __ popl(ESI);
- // Swap EDI callee save with code pointer
- __ xchgl(EDI, Address(ESP, 0));
- // Tail call to intended method.
- __ ret();
-#else // ART_USE_PORTABLE_COMPILER
- __ pushl(EBP);
- __ movl(EBP, ESP); // save ESP
- __ subl(ESP, Immediate(8)); // Align stack
- __ movl(EAX, Address(EBP, 8)); // Method* called
- __ leal(EDX, Address(EBP, 8)); // Method** called_addr
- __ pushl(Immediate(type)); // pass is_static
- __ fs()->pushl(Address::Absolute(Thread::SelfOffset())); // pass thread
- __ pushl(EDX); // pass called_addr
- __ pushl(EAX); // pass called
-
- // Call to resolve method.
- __ Call(ThreadOffset(ENTRYPOINT_OFFSET(pUnresolvedDirectMethodTrampolineFromCode)),
- X86ManagedRegister::FromCpuRegister(ECX));
-
- __ leave();
-
- Label resolve_fail; // forward declaration
- __ cmpl(EAX, Immediate(0));
- __ j(kEqual, &resolve_fail);
-
- __ jmp(EAX);
- // Tail call to intended method.
-
- __ Bind(&resolve_fail);
- __ ret();
-#endif // ART_USE_PORTABLE_COMPILER
-
- assembler->EmitSlowPaths();
- size_t cs = assembler->CodeSize();
- Thread* self = Thread::Current();
- SirtRef<mirror::ByteArray> resolution_trampoline(self, mirror::ByteArray::Alloc(self, cs));
- CHECK(resolution_trampoline.get() != NULL);
- MemoryRegion code(resolution_trampoline->GetData(), resolution_trampoline->GetLength());
- assembler->FinalizeInstructions(code);
-
- return resolution_trampoline.get();
-}
-
typedef void (*ThrowAme)(mirror::AbstractMethod*, Thread*);
mirror::ByteArray* CreateAbstractMethodErrorStub() {
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index e586f98..e529654 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -369,7 +369,7 @@
method->GetDeclaringClass()->IsInitialized()) {
method->SetOatCodeOffset(code_offset);
} else {
- method->SetCode(Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData());
+ method->SetCode(NULL);
}
method->SetOatVmapTableOffset(vmap_table_offset);
method->SetOatNativeGcMapOffset(gc_map_offset);
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 37a995d..62af7a9 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -84,8 +84,6 @@
const char* image_roots_descriptions_[] = {
"kJniStubArray",
"kAbstractMethodErrorStubArray",
- "kStaticResolutionStubArray",
- "kUnknownMethodResolutionStubArray",
"kResolutionMethod",
"kCalleeSaveMethod",
"kRefsOnlySaveMethod",
@@ -883,9 +881,8 @@
const void* GetOatCodeBegin(mirror::AbstractMethod* m)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- Runtime* runtime = Runtime::Current();
const void* code = m->GetCode();
- if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
+ if (code == GetResolutionTrampoline()) {
code = oat_dumper_->GetOatCode(m);
}
if (oat_dumper_->GetInstructionSet() == kThumb2) {
@@ -999,7 +996,7 @@
indent_os << StringPrintf("OAT CODE: %p\n", oat_code);
}
} else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
- method->IsResolutionMethod()) {
+ method->IsResolutionMethod() || MethodHelper(method).IsClassInitializer()) {
DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method);
DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
} else {
diff --git a/src/runtime.cc b/src/runtime.cc
index 9661f50..b336156 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -102,9 +102,6 @@
use_compile_time_class_path_(false),
main_thread_group_(NULL),
system_thread_group_(NULL) {
- for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
- resolution_stub_array_[i] = NULL;
- }
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
callee_save_methods_[i] = NULL;
}
@@ -1070,9 +1067,6 @@
}
visitor(jni_stub_array_, arg);
visitor(abstract_method_error_stub_array_, arg);
- for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
- visitor(resolution_stub_array_[i], arg);
- }
visitor(resolution_method_, arg);
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
visitor(callee_save_methods_[i], arg);
@@ -1109,12 +1103,6 @@
abstract_method_error_stub_array_ = abstract_method_error_stub_array;
}
-void Runtime::SetResolutionStubArray(mirror::ByteArray* resolution_stub_array, TrampolineType type) {
- CHECK(resolution_stub_array != NULL);
- CHECK(!HasResolutionStubArray(type) || resolution_stub_array_[type] == resolution_stub_array);
- resolution_stub_array_[type] = resolution_stub_array;
-}
-
mirror::AbstractMethod* Runtime::CreateResolutionMethod() {
mirror::Class* method_class = mirror::AbstractMethod::GetMethodClass();
Thread* self = Thread::Current();
@@ -1123,9 +1111,8 @@
method->SetDeclaringClass(method_class);
// TODO: use a special method for resolution method saves
method->SetDexMethodIndex(DexFile::kDexNoIndex16);
- mirror::ByteArray* unknown_resolution_stub = GetResolutionStubArray(kUnknownMethod);
- CHECK(unknown_resolution_stub != NULL);
- method->SetCode(unknown_resolution_stub->GetData());
+ // When compiling, the code pointer will get set later when the image is loaded.
+ method->SetCode(Runtime::Current()->IsCompiler() ? NULL : GetResolutionTrampoline());
return method.get();
}
diff --git a/src/runtime.h b/src/runtime.h
index 67c8e36..93cffbe 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -264,24 +264,6 @@
void SetAbstractMethodErrorStubArray(mirror::ByteArray* abstract_method_error_stub_array);
- enum TrampolineType {
- kStaticMethod,
- kUnknownMethod,
- kLastTrampolineMethodType // Value used for iteration
- };
-
- bool HasResolutionStubArray(TrampolineType type) const {
- return resolution_stub_array_[type] != NULL;
- }
-
- mirror::ByteArray* GetResolutionStubArray(TrampolineType type) const {
- CHECK(HasResolutionStubArray(type));
- DCHECK_LT(static_cast<int>(type), static_cast<int>(kLastTrampolineMethodType));
- return resolution_stub_array_[type];
- }
-
- void SetResolutionStubArray(mirror::ByteArray* resolution_stub_array, TrampolineType type);
-
// Returns a special method that calls into a trampoline for runtime method resolution
mirror::AbstractMethod* GetResolutionMethod() const {
CHECK(HasResolutionMethod());
@@ -419,8 +401,6 @@
mirror::ByteArray* abstract_method_error_stub_array_;
- mirror::ByteArray* resolution_stub_array_[kLastTrampolineMethodType];
-
mirror::AbstractMethod* callee_save_methods_[kLastCalleeSaveType];
mirror::AbstractMethod* resolution_method_;
diff --git a/src/runtime_support.h b/src/runtime_support.h
index c7eb957..2bab323 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -32,7 +32,13 @@
extern "C" void art_interpreter_invoke_handler();
extern "C" void art_portable_proxy_invoke_handler();
+extern "C" void art_portable_resolution_trampoline();
+extern "C" void art_quick_deoptimize();
+extern "C" void art_quick_instrumentation_entry_from_code(void*);
+extern "C" void art_quick_instrumentation_exit_from_code();
+extern "C" void art_quick_interpreter_entry(void*);
extern "C" void art_quick_proxy_invoke_handler();
+extern "C" void art_quick_resolution_trampoline();
extern "C" void art_work_around_app_jni_bugs();
extern "C" double art_l2d(int64_t l);
@@ -313,6 +319,46 @@
std::vector<jvalue>& args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ;
+// Entry point for deoptimization.
+static inline uintptr_t GetDeoptimizationEntryPoint() {
+ return reinterpret_cast<uintptr_t>(art_quick_deoptimize);
+}
+
+// Return address of instrumentation stub.
+static inline void* GetInstrumentationEntryPoint() {
+ return reinterpret_cast<void*>(art_quick_instrumentation_entry_from_code);
+}
+
+// The return_pc of instrumentation exit stub.
+static inline uintptr_t GetInstrumentationExitPc() {
+ return reinterpret_cast<uintptr_t>(art_quick_instrumentation_exit_from_code);
+}
+
+// Return address of interpreter stub.
+static inline void* GetInterpreterEntryPoint() {
+ return reinterpret_cast<void*>(art_quick_interpreter_entry);
+}
+
+// Return address of portable resolution trampoline stub.
+static inline void* GetPortableResolutionTrampoline() {
+ return reinterpret_cast<void*>(art_portable_resolution_trampoline);
+}
+
+// Return address of quick resolution trampoline stub.
+static inline void* GetQuickResolutionTrampoline() {
+ return reinterpret_cast<void*>(art_quick_resolution_trampoline);
+}
+
+// Return address of resolution trampoline stub for defined compiler.
+static inline void* GetResolutionTrampoline() {
+#if defined(ART_USE_PORTABLE_COMPILER)
+ return GetPortableResolutionTrampoline();
+#else
+ return GetQuickResolutionTrampoline();
+#endif
+
} // namespace art
+}
+
#endif // ART_SRC_RUNTIME_SUPPORT_H_
diff --git a/src/thread.cc b/src/thread.cc
index 07a3a90..c878a86 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1646,7 +1646,6 @@
ENTRY_POINT_INFO(pMemcmp16),
ENTRY_POINT_INFO(pStringCompareTo),
ENTRY_POINT_INFO(pMemcpy),
- ENTRY_POINT_INFO(pUnresolvedDirectMethodTrampolineFromCode),
ENTRY_POINT_INFO(pInvokeDirectTrampolineWithAccessCheck),
ENTRY_POINT_INFO(pInvokeInterfaceTrampoline),
ENTRY_POINT_INFO(pInvokeInterfaceTrampolineWithAccessCheck),