diff options
author | Vladimir Marko <vmarko@google.com> | 2017-11-30 16:16:07 +0000 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2017-11-30 16:20:39 +0000 |
commit | 2196c651ecc77e49992c6c329dfce45f78ff46cb (patch) | |
tree | 4eb151632fc7b851101b4264286ce5e900fa06b5 /runtime/stack.cc | |
parent | dc93cac66f1db225474cec5bf0350fd7a148085e (diff) | |
download | art-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.cc | 59 |
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) |