Re-enable OSR.
Fixes two bugs:
- Dealing with proxy methods, which the compiler and code cache
does not handle.
- Dealing with phi types, that may have been speculatively optimized
but do not hold once jumping to the compiled code.
Change-Id: I7dcd9976ef7b12128fff95d2b7ed3e69cc42e90a
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 949ad99..c4e314b 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -444,11 +444,12 @@
mov r10, r1 @ Save size of stack
ldr r9, [r11, #40] @ Move managed thread pointer into r9
mov r8, r2 @ Save the pc to call
- sub r7, sp, #12 @ Reserve space for stack pointer, JValue result, and ArtMethod* slot
+ sub r7, sp, #12 @ Reserve space for stack pointer,
+ @ JValue* result, and ArtMethod* slot.
and r7, #0xFFFFFFF0 @ Align stack pointer
mov sp, r7 @ Update stack pointer
str r11, [sp, #4] @ Save old stack pointer
- str r3, [sp, #8] @ Save JValue result
+ str r3, [sp, #8] @ Save JValue* result
mov ip, #0
str ip, [sp] @ Store null for ArtMethod* at bottom of frame
sub sp, sp, r1 @ Reserve space for callee stack
@@ -457,9 +458,8 @@
mov r0, sp
bl memcpy @ memcpy (dest r0, src r1, bytes r2)
bl .Losr_entry @ Call the method
- ldr r11, [sp, #4] @ Restore saved stack pointer
- ldr r10, [sp, #8] @ Restore JValue result
- mov sp, r11 @ Restore stack pointer.
+ ldr r10, [sp, #8] @ Restore JValue* result
+ ldr sp, [sp, #4] @ Restore saved stack pointer
ldr r4, [sp, #36] @ load shorty
ldrb r4, [r4, #0] @ load return type
cmp r4, #68 @ Test if result type char == 'D'.
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index d6e0f1c..69caec8 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -1755,6 +1755,8 @@
* rcx = JValue* result
* r8 = shorty
* r9 = thread
+ *
+ * Note that the native C ABI already aligned the stack to 16-byte.
*/
DEFINE_FUNCTION art_quick_osr_stub
// Save the non-volatiles.
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index e38a684..fcfa457 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -36,8 +36,6 @@
namespace art {
namespace jit {
-static constexpr bool kEnableOnStackReplacement = false;
-
JitOptions* JitOptions::CreateFromRuntimeArguments(const RuntimeArgumentMap& options) {
auto* jit_options = new JitOptions;
jit_options->use_jit_ = options.GetOrDefault(RuntimeArgumentMap::UseJIT);
@@ -164,6 +162,7 @@
bool Jit::CompileMethod(ArtMethod* method, Thread* self, bool osr) {
DCHECK(!method->IsRuntimeMethod());
+
// Don't compile the method if it has breakpoints.
if (Dbg::IsDebuggerActive() && Dbg::MethodHasAnyBreakpoints(method)) {
VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to breakpoint";
@@ -177,12 +176,15 @@
return false;
}
- if (!code_cache_->NotifyCompilationOf(method, self, osr)) {
+ // If we get a request to compile a proxy method, we pass the actual Java method
+ // of that proxy method, as the compiler does not expect a proxy method.
+ ArtMethod* method_to_compile = method->GetInterfaceMethodIfProxy(sizeof(void*));
+ if (!code_cache_->NotifyCompilationOf(method_to_compile, self, osr)) {
VLOG(jit) << "JIT not compiling " << PrettyMethod(method) << " due to code cache";
return false;
}
- bool success = jit_compile_method_(jit_compiler_handle_, method, self, osr);
- code_cache_->DoneCompiling(method, self);
+ bool success = jit_compile_method_(jit_compiler_handle_, method_to_compile, self, osr);
+ code_cache_->DoneCompiling(method_to_compile, self);
return success;
}
@@ -276,10 +278,6 @@
uint32_t dex_pc,
int32_t dex_pc_offset,
JValue* result) {
- if (!kEnableOnStackReplacement) {
- return false;
- }
-
Jit* jit = Runtime::Current()->GetJit();
if (jit == nullptr) {
return false;
@@ -326,7 +324,13 @@
ShadowFrame* shadow_frame = thread->PopShadowFrame();
size_t frame_size = osr_method->GetFrameSizeInBytes();
+
+ // Allocate memory to put shadow frame values. The osr stub will copy that memory to
+ // stack.
+ // Note that we could pass the shadow frame to the stub, and let it copy the values there,
+ // but that is engineering complexity not worth the effort for something like OSR.
void** memory = reinterpret_cast<void**>(malloc(frame_size));
+ CHECK(memory != nullptr);
memset(memory, 0, frame_size);
// Art ABI: ArtMethod is at the bottom of the stack.
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 464c441..9111ddf 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -578,7 +578,7 @@
}
}
- // Empty osr method map, as osr compile code will be deleted (except the ones
+ // Empty osr method map, as osr compiled code will be deleted (except the ones
// on thread stacks).
osr_code_map_.clear();
}