summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorMingyao Yang <mingyao@google.com>2015-03-07 06:37:59 -0800
committerMingyao Yang <mingyao@google.com>2015-03-23 16:39:37 -0700
commite295e6ec5beaea31be5d7d3c996cd8cfa2053129 (patch)
tree4d8a657d23d511743ce35bee596544d7f652efdb /runtime
parentd24ba2c44c76a2b2dd13aafe8f7981c15be31a98 (diff)
downloadart-e295e6ec5beaea31be5d7d3c996cd8cfa2053129.zip
art-e295e6ec5beaea31be5d7d3c996cd8cfa2053129.tar.gz
art-e295e6ec5beaea31be5d7d3c996cd8cfa2053129.tar.bz2
Deoptimization-based bce.
A mechanism is introduced that a runtime method can be called from code compiled with optimizing compiler to deoptimize into interpreter. This can be used to establish invariants in the managed code If the invariant does not hold at runtime, we will deoptimize and continue execution in the interpreter. This allows to optimize the managed code as if the invariant was proven during compile time. However, the exception will be thrown according to the semantics demanded by the spec. The invariant and optimization included in this patch are based on the length of an array. Given a set of array accesses with constant indices {c1, ..., cn}, we can optimize away all bounds checks iff all 0 <= min(ci) and max(ci) < array-length. The first can be proven statically. The second can be established with a deoptimization-based invariant. This replaces n bounds checks with one invariant check (plus slow-path code). Change-Id: I8c6e34b56c85d25b91074832d13dba1db0a81569
Diffstat (limited to 'runtime')
-rw-r--r--runtime/arch/arm/entrypoints_init_arm.cc2
-rw-r--r--runtime/arch/arm64/entrypoints_init_arm64.cc3
-rw-r--r--runtime/arch/x86/entrypoints_init_x86.cc3
-rw-r--r--runtime/arch/x86/quick_entrypoints_x86.S5
-rw-r--r--runtime/arch/x86_64/entrypoints_init_x86_64.cc3
-rw-r--r--runtime/arch/x86_64/quick_entrypoints_x86_64.S7
-rw-r--r--runtime/asm_support.h2
-rw-r--r--runtime/entrypoints/quick/quick_entrypoints_list.h1
-rw-r--r--runtime/entrypoints/runtime_asm_entrypoints.h2
-rw-r--r--runtime/entrypoints_order_test.cc3
-rw-r--r--runtime/interpreter/interpreter.cc4
-rw-r--r--runtime/thread.cc1
12 files changed, 30 insertions, 6 deletions
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index ce0e614..055b5ab 100644
--- a/runtime/arch/arm/entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -159,6 +159,8 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
+
+ qpoints->pDeoptimize = art_quick_deoptimize;
}
} // namespace art
diff --git a/runtime/arch/arm64/entrypoints_init_arm64.cc b/runtime/arch/arm64/entrypoints_init_arm64.cc
index e68d41d..6c787e3 100644
--- a/runtime/arch/arm64/entrypoints_init_arm64.cc
+++ b/runtime/arch/arm64/entrypoints_init_arm64.cc
@@ -151,6 +151,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
+
+ // Deoptimize
+ qpoints->pDeoptimize = art_quick_deoptimize;
};
} // namespace art
diff --git a/runtime/arch/x86/entrypoints_init_x86.cc b/runtime/arch/x86/entrypoints_init_x86.cc
index 7cdd2fc..c012173 100644
--- a/runtime/arch/x86/entrypoints_init_x86.cc
+++ b/runtime/arch/x86/entrypoints_init_x86.cc
@@ -141,6 +141,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
+
+ // Deoptimize
+ qpoints->pDeoptimize = art_quick_deoptimize_from_compiled_slow_path;
};
} // namespace art
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index e59c881..c5a020a 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -1542,7 +1542,10 @@ END_FUNCTION art_quick_instrumentation_exit
* will long jump to the upcall with a special exception of -1.
*/
DEFINE_FUNCTION art_quick_deoptimize
- pushl %ebx // Fake that we were called.
+ pushl %ebx // Entry point for a jump. Fake that we were called.
+.globl SYMBOL(art_quick_deoptimize_from_compiled_slow_path) // Entry point for real calls
+ // from compiled slow paths.
+SYMBOL(art_quick_deoptimize_from_compiled_slow_path):
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME ebx, ebx
subl LITERAL(12), %esp // Align stack.
CFI_ADJUST_CFA_OFFSET(12)
diff --git a/runtime/arch/x86_64/entrypoints_init_x86_64.cc b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
index b25d7a7..3bc0dc4 100644
--- a/runtime/arch/x86_64/entrypoints_init_x86_64.cc
+++ b/runtime/arch/x86_64/entrypoints_init_x86_64.cc
@@ -146,6 +146,9 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
qpoints->pThrowNoSuchMethod = art_quick_throw_no_such_method;
qpoints->pThrowNullPointer = art_quick_throw_null_pointer_exception;
qpoints->pThrowStackOverflow = art_quick_throw_stack_overflow;
+
+ // Deoptimize
+ qpoints->pDeoptimize = art_quick_deoptimize_from_compiled_slow_path;
#endif // __APPLE__
};
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index 5edcd96..3a448a5 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -1600,7 +1600,11 @@ END_FUNCTION art_quick_instrumentation_exit
* will long jump to the upcall with a special exception of -1.
*/
DEFINE_FUNCTION art_quick_deoptimize
- pushq %rsi // Fake that we were called. Use hidden arg.
+ pushq %rsi // Entry point for a jump. Fake that we were called.
+ // Use hidden arg.
+.globl SYMBOL(art_quick_deoptimize_from_compiled_slow_path) // Entry point for real calls
+ // from compiled slow paths.
+SYMBOL(art_quick_deoptimize_from_compiled_slow_path):
SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
// Stack should be aligned now.
movq %gs:THREAD_SELF_OFFSET, %rdi // Pass Thread.
@@ -1608,7 +1612,6 @@ DEFINE_FUNCTION art_quick_deoptimize
int3 // Unreachable.
END_FUNCTION art_quick_deoptimize
-
/*
* String's compareTo.
*
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index b1dbf6f..0d0017d 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -103,7 +103,7 @@ ADD_TEST_EQ(THREAD_TOP_QUICK_FRAME_OFFSET,
ADD_TEST_EQ(THREAD_SELF_OFFSET,
art::Thread::SelfOffset<__SIZEOF_POINTER__>().Int32Value())
-#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 125 * __SIZEOF_POINTER__)
+#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 126 * __SIZEOF_POINTER__)
ADD_TEST_EQ(THREAD_LOCAL_POS_OFFSET,
art::Thread::ThreadLocalPosOffset<__SIZEOF_POINTER__>().Int32Value())
#define THREAD_LOCAL_END_OFFSET (THREAD_LOCAL_POS_OFFSET + __SIZEOF_POINTER__)
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index da454f3..eaf874e 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -120,6 +120,7 @@
V(ThrowNoSuchMethod, void, int32_t) \
V(ThrowNullPointer, void, void) \
V(ThrowStackOverflow, void, void*) \
+ V(Deoptimize, void, void) \
\
V(A64Load, int64_t, volatile const int64_t *) \
V(A64Store, void, volatile int64_t *, int64_t)
diff --git a/runtime/entrypoints/runtime_asm_entrypoints.h b/runtime/entrypoints/runtime_asm_entrypoints.h
index 420e8db..bfe7ee8 100644
--- a/runtime/entrypoints/runtime_asm_entrypoints.h
+++ b/runtime/entrypoints/runtime_asm_entrypoints.h
@@ -70,6 +70,8 @@ static inline const void* GetQuickInstrumentationEntryPoint() {
return reinterpret_cast<const void*>(art_quick_instrumentation_entry);
}
+extern "C" void art_quick_deoptimize_from_compiled_slow_path();
+
// The return_pc of instrumentation exit stub.
extern "C" void art_quick_instrumentation_exit();
static inline const void* GetQuickInstrumentationExitPc() {
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index 88209a3..0664fa0 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -265,7 +265,8 @@ class EntrypointsOrderTest : public CommonRuntimeTest {
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowDivZero, pThrowNoSuchMethod, sizeof(void*));
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowNoSuchMethod, pThrowNullPointer, sizeof(void*));
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowNullPointer, pThrowStackOverflow, sizeof(void*));
- EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowStackOverflow, pA64Load, sizeof(void*));
+ EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pThrowStackOverflow, pDeoptimize, sizeof(void*));
+ EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pDeoptimize, pA64Load, sizeof(void*));
EXPECT_OFFSET_DIFFNP(QuickEntryPoints, pA64Load, pA64Store, sizeof(void*));
CHECKED(OFFSETOF_MEMBER(QuickEntryPoints, pA64Store)
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 686b518..4801124 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -401,7 +401,9 @@ void EnterInterpreterFromDeoptimize(Thread* self, ShadowFrame* shadow_frame, JVa
// or DexFile::kDexNoIndex if there is none.
} else {
const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
- new_dex_pc = dex_pc + instr->SizeInCodeUnits(); // the dex pc of the next instruction.
+ // For an invoke, use the dex pc of the next instruction.
+ // TODO: should be tested more once b/17586779 is fixed.
+ new_dex_pc = dex_pc + (instr->IsInvoke() ? instr->SizeInCodeUnits() : 0);
}
if (new_dex_pc != DexFile::kDexNoIndex) {
shadow_frame->SetDexPC(new_dex_pc);
diff --git a/runtime/thread.cc b/runtime/thread.cc
index e1a07e9..9fee779 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -1996,6 +1996,7 @@ void Thread::DumpThreadOffset(std::ostream& os, uint32_t offset) {
QUICK_ENTRY_POINT_INFO(pThrowNoSuchMethod)
QUICK_ENTRY_POINT_INFO(pThrowNullPointer)
QUICK_ENTRY_POINT_INFO(pThrowStackOverflow)
+ QUICK_ENTRY_POINT_INFO(pDeoptimize)
QUICK_ENTRY_POINT_INFO(pA64Load)
QUICK_ENTRY_POINT_INFO(pA64Store)
#undef QUICK_ENTRY_POINT_INFO