summaryrefslogtreecommitdiff
path: root/runtime/stack.cc
diff options
context:
space:
mode:
author hangl <quic_hangl@quicinc.com> 2024-02-21 18:28:06 +0800
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-03-07 12:40:19 +0000
commitc8b6e26aa56bb6761bb781d1095b36f84c4c65d4 (patch)
treeff692b41c6022bdb576bcf5090b89a452608db9b /runtime/stack.cc
parent9e6eca71dc3aeeb7f92c40fb7a51d582af0610f0 (diff)
Reuse boot JNI stub for native methods
Different native methods can share the same JNI stub as long as they have the same flag and shorty. Boot images loaded by zygote contain lots of JNI stubs that already compiled, so we can reuse them for native methods loaded later. For those methods having a matching JNI stub, we no longer need the GenericJNI and following JIT/AOT, which will bring an increase in program speed. Since there are many optimizations in JniCompile, we also optimize the "shorty equals" criteria for some archs to let more methods find their matching stubs. Test performance improvement: run a simple addOne(Object, int) native method for multiple times at startup (microsecond, lower is better): Number of runs before after 5000 398.70 124.94 10000 792.21 234.23 50000 3919.20 1065.30 Test feature coverage: start and run the app for 30 seconds (top 10 apps in Chinese market, higher percentage is better): (count of native methods that reuse boot JNI stub / total count of app native methods = percentage) app1: 1055/1206 = 87.48% app2: 765/884 = 86.54% app3: 1267/1414 = 89.60% app4: 1577/1759 = 89.65% app5: 1698/1860 = 91.29% app6: 2528/2787 = 90.71% app7: 1058/1218 = 86.86% app8: 952/1092 = 87.18% app9: 1343/1483 = 90.56% app10: 2990/3492 = 85.62% Test: m test-art-host-gtest Test: testrunner.py --host Test: run-gtest.sh Test: testrunner.py --target Bug: 288983053 Change-Id: I72f27bcfcd4d4a360bd5d9478b8f7687f087e431
Diffstat (limited to 'runtime/stack.cc')
-rw-r--r--runtime/stack.cc23
1 files changed, 16 insertions, 7 deletions
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 942b155261..81c8a8a9e0 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -840,7 +840,7 @@ void StackVisitor::WalkStack(bool include_transitions) {
cur_oat_quick_method_header_ = OatQuickMethodHeader::FromCodePointer(code);
} else {
// We are sure we are not running GenericJni here. Though the entry point could still be
- // GenericJnistub. The entry point is usually JITed or AOT code. It could be lso a
+ // GenericJnistub. The entry point is usually JITed or AOT code. It could be also a
// resolution stub if the class isn't visibly initialized yet.
const void* existing_entry_point = method->GetEntryPointFromQuickCompiledCode();
CHECK(existing_entry_point != nullptr);
@@ -856,13 +856,22 @@ void StackVisitor::WalkStack(bool include_transitions) {
if (code != nullptr) {
cur_oat_quick_method_header_ = OatQuickMethodHeader::FromEntryPoint(code);
} else {
- // This must be a JITted JNI stub frame. For non-debuggable runtimes we only generate
- // JIT stubs if there are no AOT stubs for native methods. Since we checked for AOT
- // code earlier, we must be running JITed code. For debuggable runtimes we might have
- // JIT code even when AOT code is present but we tag SP in JITed JNI stubs
+ // This may be either a JITed JNI stub frame or boot JNI stub frame. For
+ // non-debuggable runtimes we will generate JIT stubs if there are no AOT stubs or
+ // boot stubs for native methods. Since we checked for AOT code earlier, we must be
+ // running JITed code or boot stub code. For debuggable runtimes we might have JIT
+ // code even when AOT stub or boot stub is present but we tag SP in JITed JNI stubs
// in debuggable runtimes. This case is handled earlier.
- CHECK(runtime->GetJit() != nullptr);
- code = runtime->GetJit()->GetCodeCache()->GetJniStubCode(method);
+ if (runtime->GetJit() != nullptr) {
+ code = runtime->GetJit()->GetCodeCache()->GetJniStubCode(method);
+ }
+ if (code == nullptr) {
+ // Check if current method uses the boot JNI stub.
+ const void* boot_jni_stub = class_linker->FindBootJniStub(method);
+ if (boot_jni_stub != nullptr) {
+ code = boot_jni_stub;
+ }
+ }
CHECK(code != nullptr) << method->PrettyMethod();
cur_oat_quick_method_header_ = OatQuickMethodHeader::FromCodePointer(code);
}