Improve nterp -> compiled code transitions.
Use an unused bit in the access flags of an ArtMethod (0x00200000) to store
the information a method only takes ints or references and returns an
int, a reference, or a long. This avoids the need to fetch the shorty in nterp
when doing a call.
Test: test.py
Test: 821-many-args
Bug: 112676029
Change-Id: Ie657ccf69c17c1097dc2a97f18e3093ef3be391b
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 2040263..745e7cf 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -3838,21 +3838,34 @@
} else {
dst->SetCodeItem(dst->GetDexFile()->GetCodeItem(method.GetCodeItemOffset()));
}
- bool has_all_references = true;
- const char* shorty = dst->GetShorty();
- for (size_t i = 1, e = strlen(shorty); i < e; ++i) {
- if (shorty[i] != 'L') {
- has_all_references = false;
- break;
- }
- }
- if (has_all_references) {
- dst->SetNterpEntryPointFastPathFlag();
- }
} else {
dst->SetDataPtrSize(nullptr, image_pointer_size_);
DCHECK_EQ(method.GetCodeItemOffset(), 0u);
}
+
+ // Set optimization flags related to the shorty.
+ const char* shorty = dst->GetShorty();
+ bool all_parameters_are_reference = true;
+ bool all_parameters_are_reference_or_int = true;
+ bool return_type_is_fp = (shorty[0] == 'F' || shorty[0] == 'D');
+
+ for (size_t i = 1, e = strlen(shorty); i < e; ++i) {
+ if (shorty[i] != 'L') {
+ all_parameters_are_reference = false;
+ if (shorty[i] == 'F' || shorty[i] == 'D' || shorty[i] == 'J') {
+ all_parameters_are_reference_or_int = false;
+ break;
+ }
+ }
+ }
+
+ if (!dst->IsNative() && all_parameters_are_reference) {
+ dst->SetNterpEntryPointFastPathFlag();
+ }
+
+ if (!return_type_is_fp && all_parameters_are_reference_or_int) {
+ dst->SetNterpInvokeFastPathFlag();
+ }
}
void ClassLinker::AppendToBootClassPath(Thread* self, const DexFile* dex_file) {