summaryrefslogtreecommitdiff
path: root/runtime/jit/jit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/jit/jit.cc')
-rw-r--r--runtime/jit/jit.cc153
1 files changed, 84 insertions, 69 deletions
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 31c278e748..188deb07a5 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -36,7 +36,7 @@
namespace art {
namespace jit {
-static constexpr bool kEnableOnStackReplacement = false;
+static constexpr bool kEnableOnStackReplacement = true;
JitOptions* JitOptions::CreateFromRuntimeArguments(const RuntimeArgumentMap& options) {
auto* jit_options = new JitOptions;
@@ -290,7 +290,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
}
if (kRuntimeISA == kMips || kRuntimeISA == kMips64) {
- VLOG(jit) << "OSR not supported on this platform";
+ VLOG(jit) << "OSR not supported on this platform: " << kRuntimeISA;
return false;
}
@@ -304,79 +304,93 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
return false;
}
- const OatQuickMethodHeader* osr_method = jit->GetCodeCache()->LookupOsrMethodHeader(method);
- if (osr_method == nullptr) {
- // No osr method yet, just return to the interpreter.
- return false;
- }
-
+ // Fetch some data before looking up for an OSR method. We don't want thread
+ // suspension once we hold an OSR method, as the JIT code cache could delete the OSR
+ // method while we are being suspended.
const size_t number_of_vregs = method->GetCodeItem()->registers_size_;
- CodeInfo code_info = osr_method->GetOptimizedCodeInfo();
- StackMapEncoding encoding = code_info.ExtractEncoding();
-
- // Find stack map starting at the target dex_pc.
- StackMap stack_map = code_info.GetOsrStackMapForDexPc(dex_pc + dex_pc_offset, encoding);
- if (!stack_map.IsValid()) {
- // There is no OSR stack map for this dex pc offset. Just return to the interpreter in the
- // hope that the next branch has one.
- return false;
- }
+ const char* shorty = method->GetShorty();
+ std::string method_name(VLOG_IS_ON(jit) ? PrettyMethod(method) : "");
+ void** memory = nullptr;
+ size_t frame_size = 0;
+ ShadowFrame* shadow_frame = nullptr;
+ const uint8_t* native_pc = nullptr;
- // We found a stack map, now fill the frame with dex register values from the interpreter's
- // shadow frame.
- DexRegisterMap vreg_map =
- code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs);
-
- 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.
- memory[0] = method;
-
- if (!vreg_map.IsValid()) {
- // If we don't have a dex register map, then there are no live dex registers at
- // this dex pc.
- } else {
- for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
- DexRegisterLocation::Kind location =
- vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
- if (location == DexRegisterLocation::Kind::kNone) {
- // Dex register is dead or unitialized.
- continue;
- }
+ {
+ ScopedAssertNoThreadSuspension sts(thread, "Holding OSR method");
+ const OatQuickMethodHeader* osr_method = jit->GetCodeCache()->LookupOsrMethodHeader(method);
+ if (osr_method == nullptr) {
+ // No osr method yet, just return to the interpreter.
+ return false;
+ }
- if (location == DexRegisterLocation::Kind::kConstant) {
- // We skip constants because the compiled code knows how to handle them.
- continue;
- }
+ CodeInfo code_info = osr_method->GetOptimizedCodeInfo();
+ StackMapEncoding encoding = code_info.ExtractEncoding();
- DCHECK(location == DexRegisterLocation::Kind::kInStack);
+ // Find stack map starting at the target dex_pc.
+ StackMap stack_map = code_info.GetOsrStackMapForDexPc(dex_pc + dex_pc_offset, encoding);
+ if (!stack_map.IsValid()) {
+ // There is no OSR stack map for this dex pc offset. Just return to the interpreter in the
+ // hope that the next branch has one.
+ return false;
+ }
- int32_t vreg_value = shadow_frame->GetVReg(vreg);
- int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg,
- number_of_vregs,
- code_info,
- encoding);
- DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size));
- DCHECK_GT(slot_offset, 0);
- (reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value;
+ // We found a stack map, now fill the frame with dex register values from the interpreter's
+ // shadow frame.
+ DexRegisterMap vreg_map =
+ code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_vregs);
+
+ 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.
+ 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.
+ memory[0] = method;
+
+ shadow_frame = thread->PopShadowFrame();
+ if (!vreg_map.IsValid()) {
+ // If we don't have a dex register map, then there are no live dex registers at
+ // this dex pc.
+ } else {
+ for (uint16_t vreg = 0; vreg < number_of_vregs; ++vreg) {
+ DexRegisterLocation::Kind location =
+ vreg_map.GetLocationKind(vreg, number_of_vregs, code_info, encoding);
+ if (location == DexRegisterLocation::Kind::kNone) {
+ // Dex register is dead or uninitialized.
+ continue;
+ }
+
+ if (location == DexRegisterLocation::Kind::kConstant) {
+ // We skip constants because the compiled code knows how to handle them.
+ continue;
+ }
+
+ DCHECK(location == DexRegisterLocation::Kind::kInStack)
+ << DexRegisterLocation::PrettyDescriptor(location);
+
+ int32_t vreg_value = shadow_frame->GetVReg(vreg);
+ int32_t slot_offset = vreg_map.GetStackOffsetInBytes(vreg,
+ number_of_vregs,
+ code_info,
+ encoding);
+ DCHECK_LT(slot_offset, static_cast<int32_t>(frame_size));
+ DCHECK_GT(slot_offset, 0);
+ (reinterpret_cast<int32_t*>(memory))[slot_offset / sizeof(int32_t)] = vreg_value;
+ }
}
+
+ native_pc = stack_map.GetNativePcOffset(encoding) + osr_method->GetEntryPoint();
+ VLOG(jit) << "Jumping to "
+ << method_name
+ << "@"
+ << std::hex << reinterpret_cast<uintptr_t>(native_pc);
}
- const uint8_t* native_pc = stack_map.GetNativePcOffset(encoding) + osr_method->GetEntryPoint();
- VLOG(jit) << "Jumping to "
- << PrettyMethod(method)
- << "@"
- << std::hex << reinterpret_cast<uintptr_t>(native_pc);
{
ManagedStack fragment;
thread->PushManagedStackFragment(&fragment);
@@ -384,8 +398,9 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
frame_size,
native_pc,
result,
- method->GetInterfaceMethodIfProxy(sizeof(void*))->GetShorty(),
+ shorty,
thread);
+
if (UNLIKELY(thread->GetException() == Thread::GetDeoptimizationException())) {
thread->DeoptimizeWithDeoptimizationException(result);
}
@@ -393,7 +408,7 @@ bool Jit::MaybeDoOnStackReplacement(Thread* thread,
}
free(memory);
thread->PushShadowFrame(shadow_frame);
- VLOG(jit) << "Done running OSR code for " << PrettyMethod(method);
+ VLOG(jit) << "Done running OSR code for " << method_name;
return true;
}