summaryrefslogtreecommitdiffstats
path: root/runtime/stack.cc
diff options
context:
space:
mode:
authorVladimir Marko <vmarko@google.com>2017-11-30 16:16:07 +0000
committerVladimir Marko <vmarko@google.com>2017-11-30 16:20:39 +0000
commit2196c651ecc77e49992c6c329dfce45f78ff46cb (patch)
tree4eb151632fc7b851101b4264286ce5e900fa06b5 /runtime/stack.cc
parentdc93cac66f1db225474cec5bf0350fd7a148085e (diff)
downloadart-2196c651ecc77e49992c6c329dfce45f78ff46cb.tar.gz
art-2196c651ecc77e49992c6c329dfce45f78ff46cb.tar.bz2
art-2196c651ecc77e49992c6c329dfce45f78ff46cb.zip
Revert^4 "JIT JNI stubs."
The original CL, https://android-review.googlesource.com/513417 , has a bug fixed in the Revert^2, https://android-review.googlesource.com/550579 , and this Revert^4 adds two more fixes: - fix obsolete native method getting interpreter entrypoint in 980-redefine-object, - fix random JIT GC flakiness in 667-jit-jni-stub. Test: testrunner.py --host --prebuild --no-relocate \ --no-image --jit -t 980-redefine-object Bug: 65574695 Bug: 69843562 This reverts commit 056d7756152bb3ced81dd57781be5028428ce2bd. Change-Id: Ic778686168b90e29816fd526e23141dcbe5ea880
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r--runtime/stack.cc59
1 files changed, 53 insertions, 6 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc
index ab9fb0d73f..5ad1f7c9c5 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -735,12 +735,19 @@ QuickMethodFrameInfo StackVisitor::GetCurrentQuickFrameInfo() const {
return runtime->GetCalleeSaveMethodFrameInfo(CalleeSaveType::kSaveRefsAndArgs);
}
- // The only remaining case is if the method is native and uses the generic JNI stub.
+ // The only remaining case is if the method is native and uses the generic JNI stub,
+ // called either directly or through some (resolution, instrumentation) trampoline.
DCHECK(method->IsNative());
- ClassLinker* class_linker = runtime->GetClassLinker();
- const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(method,
- kRuntimePointerSize);
- DCHECK(class_linker->IsQuickGenericJniStub(entry_point)) << method->PrettyMethod();
+ if (kIsDebugBuild) {
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(method,
+ kRuntimePointerSize);
+ CHECK(class_linker->IsQuickGenericJniStub(entry_point) ||
+ // The current entrypoint (after filtering out trampolines) may have changed
+ // from GenericJNI to JIT-compiled stub since we have entered this frame.
+ (runtime->GetJit() != nullptr &&
+ runtime->GetJit()->GetCodeCache()->ContainsPc(entry_point))) << method->PrettyMethod();
+ }
// Generic JNI frame.
uint32_t handle_refs = GetNumberOfReferenceArgsWithoutReceiver(method) + 1;
size_t scope_size = HandleScope::SizeOf(handle_refs);
@@ -776,8 +783,48 @@ void StackVisitor::WalkStack(bool include_transitions) {
// Can't be both a shadow and a quick fragment.
DCHECK(current_fragment->GetTopShadowFrame() == nullptr);
ArtMethod* method = *cur_quick_frame_;
+ DCHECK(method != nullptr);
+ bool header_retrieved = false;
+ if (method->IsNative()) {
+ // We do not have a PC for the first frame, so we cannot simply use
+ // ArtMethod::GetOatQuickMethodHeader() as we're unable to distinguish there
+ // between GenericJNI frame and JIT-compiled JNI stub; the entrypoint may have
+ // changed since the frame was entered. The top quick frame tag indicates
+ // GenericJNI here, otherwise it's either AOT-compiled or JNI-compiled JNI stub.
+ if (UNLIKELY(current_fragment->GetTopQuickFrameTag())) {
+ // The generic JNI does not have any method header.
+ cur_oat_quick_method_header_ = nullptr;
+ } else {
+ const void* existing_entry_point = method->GetEntryPointFromQuickCompiledCode();
+ CHECK(existing_entry_point != nullptr);
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
+ // Check whether we can quickly get the header from the current entrypoint.
+ if (!class_linker->IsQuickGenericJniStub(existing_entry_point) &&
+ !class_linker->IsQuickResolutionStub(existing_entry_point) &&
+ existing_entry_point != GetQuickInstrumentationEntryPoint()) {
+ cur_oat_quick_method_header_ =
+ OatQuickMethodHeader::FromEntryPoint(existing_entry_point);
+ } else {
+ const void* code = method->GetOatMethodQuickCode(class_linker->GetImagePointerSize());
+ if (code != nullptr) {
+ cur_oat_quick_method_header_ = OatQuickMethodHeader::FromEntryPoint(code);
+ } else {
+ // This must be a JITted JNI stub frame.
+ CHECK(runtime->GetJit() != nullptr);
+ code = runtime->GetJit()->GetCodeCache()->GetJniStubCode(method);
+ CHECK(code != nullptr) << method->PrettyMethod();
+ cur_oat_quick_method_header_ = OatQuickMethodHeader::FromCodePointer(code);
+ }
+ }
+ }
+ header_retrieved = true;
+ }
while (method != nullptr) {
- cur_oat_quick_method_header_ = method->GetOatQuickMethodHeader(cur_quick_frame_pc_);
+ if (!header_retrieved) {
+ cur_oat_quick_method_header_ = method->GetOatQuickMethodHeader(cur_quick_frame_pc_);
+ }
+ header_retrieved = false; // Force header retrieval in next iteration.
SanityCheckFrame();
if ((walk_kind_ == StackWalkKind::kIncludeInlinedFrames)