Revert^2 "Add support for calling entry / exit hooks directly from JIT code""
This reverts commit 72be14ed06b76cd0e83392145cec9025ff43d174.
Reason for revert: A reland of
commit 2d4feeb67912d64b9e980e6687794826a5c22f9d with a fix for no-image
tests
Change-Id: I79f719f0d4d9b903db301a1636fde5689da35a29
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 0b58c36..b29da65 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -60,6 +60,9 @@
namespace art {
+extern "C" NO_RETURN void artDeoptimizeFromCompiledCode(DeoptimizationKind kind, Thread* self);
+extern "C" NO_RETURN void artDeoptimize(Thread* self);
+
// Visits the arguments as saved to the stack by a CalleeSaveType::kRefAndArgs callee save frame.
class QuickArgumentVisitor {
// Number of bytes for each out register in the caller method's frame.
@@ -2586,4 +2589,71 @@
return result.GetJ();
}
+extern "C" void artMethodEntryHook(ArtMethod* method, Thread* self, ArtMethod** sp ATTRIBUTE_UNUSED)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
+ instr->MethodEnterEvent(self, method);
+ if (instr->IsDeoptimized(method)) {
+ // Instrumentation can request deoptimizing only a particular method (for
+ // ex: when there are break points on the method). In such cases deoptimize
+ // only this method. FullFrame deoptimizations are handled on method exits.
+ artDeoptimizeFromCompiledCode(DeoptimizationKind::kDebugging, self);
+ }
+}
+
+extern "C" int artMethodExitHook(Thread* self,
+ ArtMethod* method,
+ uint64_t* gpr_result,
+ uint64_t* fpr_result)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ DCHECK_EQ(reinterpret_cast<uintptr_t>(self), reinterpret_cast<uintptr_t>(Thread::Current()));
+ CHECK(gpr_result != nullptr);
+ CHECK(fpr_result != nullptr);
+ // Instrumentation exit stub must not be entered with a pending exception.
+ CHECK(!self->IsExceptionPending())
+ << "Enter instrumentation exit stub with pending exception " << self->GetException()->Dump();
+
+ instrumentation::Instrumentation* instr = Runtime::Current()->GetInstrumentation();
+ bool is_ref;
+ JValue return_value = instr->GetReturnValue(self, method, &is_ref, gpr_result, fpr_result);
+ bool deoptimize = false;
+ {
+ StackHandleScope<1> hs(self);
+ MutableHandle<mirror::Object> res(hs.NewHandle<mirror::Object>(nullptr));
+ if (is_ref) {
+ // Take a handle to the return value so we won't lose it if we suspend.
+ res.Assign(return_value.GetL());
+ }
+ DCHECK(!method->IsRuntimeMethod());
+ instr->MethodExitEvent(self,
+ method,
+ /* frame= */ {},
+ return_value);
+
+ // Deoptimize if the caller needs to continue execution in the interpreter. Do nothing if we get
+ // back to an upcall.
+ NthCallerVisitor visitor(self, 1, true);
+ visitor.WalkStack(true);
+ deoptimize = instr->ShouldDeoptimizeMethod(self, visitor);
+
+ if (is_ref) {
+ // Restore the return value if it's a reference since it might have moved.
+ *reinterpret_cast<mirror::Object**>(gpr_result) = res.Get();
+ }
+ }
+
+ if (self->IsExceptionPending() || self->ObserveAsyncException()) {
+ return 1;
+ }
+
+ if (deoptimize) {
+ DeoptimizationMethodType deopt_method_type = instr->GetDeoptimizationMethodType(method);
+ self->PushDeoptimizationContext(return_value, is_ref, nullptr, false, deopt_method_type);
+ artDeoptimize(self);
+ UNREACHABLE();
+ }
+
+ return 0;
+}
+
} // namespace art