Improve `CanMethodUseNterp()`.
Avoid repeated reading of method's access flags and
repeated construction of `CodeItemDataAccessor`.
Avoid unnecessary rounding.
Test: testrunner.py --host --interpreter
Change-Id: I7390d5fc19f0e89a80c0b4ffe48a190eea21d998
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 308a070..16350e7 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -357,17 +357,19 @@
}
void SetMemorySharedMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
- if (!IsIntrinsic() && !IsAbstract()) {
+ uint32_t access_flags = GetAccessFlags();
+ if (!IsIntrinsic(access_flags) && !IsAbstract(access_flags)) {
AddAccessFlags(kAccMemorySharedMethod);
SetHotCounter();
}
}
void ClearMemorySharedMethod() REQUIRES_SHARED(Locks::mutator_lock_) {
- if (IsIntrinsic() || IsAbstract()) {
+ uint32_t access_flags = GetAccessFlags();
+ if (IsIntrinsic(access_flags) || IsAbstract(access_flags)) {
return;
}
- if (IsMemorySharedMethod()) {
+ if (IsMemorySharedMethod(access_flags)) {
ClearAccessFlags(kAccMemorySharedMethod);
}
}
@@ -797,7 +799,11 @@
}
bool HasCodeItem() REQUIRES_SHARED(Locks::mutator_lock_) {
- return !IsRuntimeMethod() && !IsNative() && !IsProxyMethod() && !IsAbstract();
+ uint32_t access_flags = GetAccessFlags();
+ return !IsNative(access_flags) &&
+ !IsAbstract(access_flags) &&
+ !IsRuntimeMethod() &&
+ !IsProxyMethod();
}
// We need to explicitly indicate whether the code item is obtained from the compact dex file,
diff --git a/runtime/nterp_helpers.cc b/runtime/nterp_helpers.cc
index 12afa3a..fb2046c 100644
--- a/runtime/nterp_helpers.cc
+++ b/runtime/nterp_helpers.cc
@@ -120,9 +120,7 @@
static_cast<size_t>(InstructionSetPointerSize(isa));
}
-static uint16_t GetNumberOfOutRegs(ArtMethod* method, InstructionSet isa)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- CodeItemDataAccessor accessor(method->DexInstructionData());
+static uint16_t GetNumberOfOutRegs(const CodeItemDataAccessor& accessor, InstructionSet isa) {
uint16_t out_regs = accessor.OutsSize();
switch (isa) {
case InstructionSet::kX86: {
@@ -136,14 +134,23 @@
return out_regs;
}
-size_t NterpGetFrameSize(ArtMethod* method, InstructionSet isa) {
+static uint16_t GetNumberOfOutRegs(ArtMethod* method, InstructionSet isa)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ CodeItemDataAccessor accessor(method->DexInstructionData());
+ return GetNumberOfOutRegs(accessor, isa);
+}
+
+// Note: There may be two pieces of alignment but there is no need to align
+// out args to `kPointerSize` separately before aligning to kStackAlignment.
+// This allows using the size without padding for the maximum frame size check
+// in `CanMethodUseNterp()`.
+static size_t NterpGetFrameSizeWithoutPadding(ArtMethod* method, InstructionSet isa)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
CodeItemDataAccessor accessor(method->DexInstructionData());
const uint16_t num_regs = accessor.RegistersSize();
- const uint16_t out_regs = GetNumberOfOutRegs(method, isa);
+ const uint16_t out_regs = GetNumberOfOutRegs(accessor, isa);
size_t pointer_size = static_cast<size_t>(InstructionSetPointerSize(isa));
- // Note: There may be two pieces of alignment but there is no need to align
- // out args to `kPointerSize` separately before aligning to kStackAlignment.
DCHECK(IsAlignedParam(kStackAlignment, pointer_size));
DCHECK(IsAlignedParam(NterpGetFrameEntrySize(isa), pointer_size));
DCHECK(IsAlignedParam(kVRegSize * 2, pointer_size));
@@ -154,7 +161,13 @@
pointer_size + // saved dex pc
(out_regs * kVRegSize) + // out arguments
pointer_size; // method
- return RoundUp(frame_size, kStackAlignment);
+ return frame_size;
+}
+
+// The frame size nterp will use for the given method.
+static inline size_t NterpGetFrameSize(ArtMethod* method, InstructionSet isa)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ return RoundUp(NterpGetFrameSizeWithoutPadding(method, isa), kStackAlignment);
}
QuickMethodFrameInfo NterpFrameInfo(ArtMethod** frame) {
@@ -162,7 +175,7 @@
RuntimeCalleeSaveFrame::GetCoreSpills(CalleeSaveType::kSaveAllCalleeSaves);
uint32_t fp_spills =
RuntimeCalleeSaveFrame::GetFpSpills(CalleeSaveType::kSaveAllCalleeSaves);
- return QuickMethodFrameInfo(NterpGetFrameSize(*frame), core_spills, fp_spills);
+ return QuickMethodFrameInfo(NterpGetFrameSize(*frame, kRuntimeISA), core_spills, fp_spills);
}
uintptr_t NterpGetRegistersArray(ArtMethod** frame) {
@@ -206,13 +219,20 @@
}
bool CanMethodUseNterp(ArtMethod* method, InstructionSet isa) {
- return !method->IsNative() &&
- method->IsInvokable() &&
- !method->MustCountLocks() &&
+ uint32_t access_flags = method->GetAccessFlags();
+ if (ArtMethod::IsNative(access_flags) ||
+ !ArtMethod::IsInvokable(access_flags) ||
+ ArtMethod::MustCountLocks(access_flags) ||
// Proxy methods do not go through the JIT like other methods, so we don't
// run them with nterp.
- !method->IsProxyMethod() &&
- NterpGetFrameSize(method, isa) <= interpreter::kNterpMaxFrame;
+ method->IsProxyMethod()) {
+ return false;
+ }
+ // There is no need to add the alignment padding size for comparison with aligned limit.
+ size_t frame_size_without_padding = NterpGetFrameSizeWithoutPadding(method, isa);
+ DCHECK_EQ(NterpGetFrameSize(method, isa), RoundUp(frame_size_without_padding, kStackAlignment));
+ static_assert(IsAligned<kStackAlignment>(interpreter::kNterpMaxFrame));
+ return frame_size_without_padding <= interpreter::kNterpMaxFrame;
}
} // namespace art
diff --git a/runtime/nterp_helpers.h b/runtime/nterp_helpers.h
index 0f9e758..236059b 100644
--- a/runtime/nterp_helpers.h
+++ b/runtime/nterp_helpers.h
@@ -24,12 +24,6 @@
class ArtMethod;
/**
- * The frame size nterp will use for the given method.
- */
-size_t NterpGetFrameSize(ArtMethod* method, InstructionSet isa = kRuntimeISA)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
-/**
* Returns the QuickMethodFrameInfo of the given frame corresponding to the
* given method.
*/