Increment hotness in nterp when doing lookups.
Test: test.py
Test: google/perf/app-transition/app-transition-to-recents
Bug: 112676029
Bug: 157402634
Change-Id: Ibe08720b442c5050062db1104be2d3a62641e629
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f7fe27d..8bf38d3 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -88,6 +88,7 @@
#include "imtable-inl.h"
#include "intern_table-inl.h"
#include "interpreter/interpreter.h"
+#include "interpreter/mterp/nterp.h"
#include "jit/debugger_interface.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
diff --git a/runtime/interpreter/mterp/arm64ng/main.S b/runtime/interpreter/mterp/arm64ng/main.S
index ea04b45..d1ff448 100644
--- a/runtime/interpreter/mterp/arm64ng/main.S
+++ b/runtime/interpreter/mterp/arm64ng/main.S
@@ -313,7 +313,7 @@
ldr x0, [sp]
ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
add x2, x2, #1
- and w2, w2, #0xffff
+ and w2, w2, #NTERP_HOTNESS_MASK
strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
// If the counter overflows, handle this in the runtime.
cbz w2, NterpHandleHotnessOverflow
@@ -382,7 +382,7 @@
ldr x0, [sp]
ldrh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
add x2, x2, #1
- and w2, w2, #0xffff
+ and w2, w2, #NTERP_HOTNESS_MASK
strh w2, [x0, #ART_METHOD_HOTNESS_COUNT_OFFSET]
// If the counter overflows, handle this in the runtime.
cbz w2, 2f
diff --git a/runtime/interpreter/mterp/mterp.h b/runtime/interpreter/mterp/mterp.h
index 7813fca..bc057c2 100644
--- a/runtime/interpreter/mterp/mterp.h
+++ b/runtime/interpreter/mterp/mterp.h
@@ -28,24 +28,15 @@
extern "C" void* artMterpAsmInstructionStart[];
extern "C" void* artMterpAsmInstructionEnd[];
-extern "C" void* artNterpAsmInstructionStart[];
-extern "C" void* artNterpAsmInstructionEnd[];
-
namespace art {
-class ArtMethod;
class Thread;
namespace interpreter {
void InitMterpTls(Thread* self);
void CheckMterpAsmConstants();
-void CheckNterpAsmConstants();
bool CanUseMterp();
-bool IsNterpSupported();
-bool CanRuntimeUseNterp();
-bool CanMethodUseNterp(ArtMethod* method);
-const void* GetNterpEntryPoint();
// Poison value for TestExportPC. If we segfault with this value, it means that a mterp
// handler for a recent opcode failed to export the Dalvik PC prior to a possible exit from
@@ -56,9 +47,6 @@
constexpr size_t kMterpHandlerSize = 128;
-// The maximum we will allow an nterp frame to be.
-constexpr size_t kMaxNterpFrame = 3 * KB;
-
} // namespace interpreter
} // namespace art
diff --git a/runtime/interpreter/mterp/nterp.cc b/runtime/interpreter/mterp/nterp.cc
index 2eb3650..95b4243 100644
--- a/runtime/interpreter/mterp/nterp.cc
+++ b/runtime/interpreter/mterp/nterp.cc
@@ -17,7 +17,7 @@
/*
* Mterp entry point and support functions.
*/
-#include "mterp.h"
+#include "nterp.h"
#include "base/quasi_atomic.h"
#include "dex/dex_instruction_utils.h"
@@ -45,7 +45,7 @@
return method->SkipAccessChecks() &&
!method->IsNative() &&
method->GetDexFile()->IsStandardDexFile() &&
- NterpGetFrameSize(method) < kMaxNterpFrame;
+ NterpGetFrameSize(method) < kNterpMaxFrame;
}
const void* GetNterpEntryPoint() {
@@ -71,6 +71,24 @@
}
}
+inline void UpdateHotness(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+ // The hotness we will add to a method when we perform a
+ // field/method/class/string lookup.
+ constexpr uint16_t kNterpHotnessLookup = 0xff;
+
+ // Convert to uint32_t to handle uint16_t overflow.
+ uint32_t counter = method->GetCounter();
+ uint32_t new_counter = counter + kNterpHotnessLookup;
+ if ((new_counter & kNterpHotnessMask) == 0) {
+ // Let the nterp code actually call the compilation: we want to make sure
+ // there's at least a second execution of the method or a back-edge to avoid
+ // compiling straightline initialization methods.
+ method->SetCounter(kNterpHotnessMask - 1);
+ } else {
+ method->SetCounter(new_counter);
+ }
+}
+
template<typename T>
inline void UpdateCache(Thread* self, uint16_t* dex_pc_ptr, T value) {
DCHECK(kUseReadBarrier) << "Nterp only works with read barriers";
@@ -129,6 +147,7 @@
extern "C" size_t NterpGetMethod(Thread* self, ArtMethod* caller, uint16_t* dex_pc_ptr)
REQUIRES_SHARED(Locks::mutator_lock_) {
+ UpdateHotness(caller);
const Instruction* inst = Instruction::At(dex_pc_ptr);
InvokeType invoke_type = kStatic;
uint16_t method_index = 0;
@@ -320,6 +339,7 @@
extern "C" size_t NterpGetStaticField(Thread* self, ArtMethod* caller, uint16_t* dex_pc_ptr)
REQUIRES_SHARED(Locks::mutator_lock_) {
+ UpdateHotness(caller);
const Instruction* inst = Instruction::At(dex_pc_ptr);
uint16_t field_index = inst->VRegB_21c();
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
@@ -360,6 +380,7 @@
ArtMethod* caller,
uint16_t* dex_pc_ptr)
REQUIRES_SHARED(Locks::mutator_lock_) {
+ UpdateHotness(caller);
const Instruction* inst = Instruction::At(dex_pc_ptr);
uint16_t field_index = inst->VRegC_22c();
ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
@@ -387,6 +408,7 @@
ArtMethod* caller,
uint16_t* dex_pc_ptr)
REQUIRES_SHARED(Locks::mutator_lock_) {
+ UpdateHotness(caller);
const Instruction* inst = Instruction::At(dex_pc_ptr);
dex::TypeIndex index;
switch (inst->Opcode()) {
@@ -446,6 +468,7 @@
switch (inst->Opcode()) {
case Instruction::CONST_STRING:
case Instruction::CONST_STRING_JUMBO: {
+ UpdateHotness(caller);
dex::StringIndex string_index(
(inst->Opcode() == Instruction::CONST_STRING)
? inst->VRegB_21c()
diff --git a/runtime/interpreter/mterp/nterp.h b/runtime/interpreter/mterp/nterp.h
new file mode 100644
index 0000000..a1bf941
--- /dev/null
+++ b/runtime/interpreter/mterp/nterp.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_INTERPRETER_MTERP_NTERP_H_
+#define ART_RUNTIME_INTERPRETER_MTERP_NTERP_H_
+
+#include "base/globals.h"
+
+extern "C" void* artNterpAsmInstructionStart[];
+extern "C" void* artNterpAsmInstructionEnd[];
+
+namespace art {
+
+class ArtMethod;
+
+namespace interpreter {
+
+void CheckNterpAsmConstants();
+bool IsNterpSupported();
+bool CanRuntimeUseNterp();
+bool CanMethodUseNterp(ArtMethod* method);
+const void* GetNterpEntryPoint();
+
+// The hotness threshold where we trigger JIT compilation or OSR.
+constexpr uint16_t kNterpHotnessMask = 0xffff;
+
+// The maximum we allow an nterp frame to be.
+constexpr size_t kNterpMaxFrame = 3 * KB;
+
+// The maximum size for each nterp opcode handler.
+constexpr size_t kNterpHandlerSize = 128;
+
+} // namespace interpreter
+} // namespace art
+
+#endif // ART_RUNTIME_INTERPRETER_MTERP_NTERP_H_
diff --git a/runtime/interpreter/mterp/x86_64ng/main.S b/runtime/interpreter/mterp/x86_64ng/main.S
index a890245..16bd1e4 100644
--- a/runtime/interpreter/mterp/x86_64ng/main.S
+++ b/runtime/interpreter/mterp/x86_64ng/main.S
@@ -255,6 +255,9 @@
GOTO_NEXT
3:
movq (%rsp), %rdi
+#if (NTERP_HOTNESS_MASK != 0xffff)
+#error "Nterp x86_64 expects Nterp hotness mask to be 0xffff"
+#endif
addw $$1, ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi)
// If the counter overflows, handle this in the runtime.
jo NterpHandleHotnessOverflow
@@ -741,6 +744,9 @@
// Increase method hotness and do suspend check before starting executing the method.
.macro START_EXECUTING_INSTRUCTIONS
movq (%rsp), %rdi
+#if (NTERP_HOTNESS_MASK != 0xffff)
+#error "Nterp x86_64 expects Nterp hotness mask to be 0xffff"
+#endif
addw $$1, ART_METHOD_HOTNESS_COUNT_OFFSET(%rdi)
jo 2f
testl $$(THREAD_SUSPEND_OR_CHECKPOINT_REQUEST), rSELF:THREAD_FLAGS_OFFSET
diff --git a/runtime/jit/jit.h b/runtime/jit/jit.h
index 853db10..e604738 100644
--- a/runtime/jit/jit.h
+++ b/runtime/jit/jit.h
@@ -27,7 +27,7 @@
#include "compilation_kind.h"
#include "handle.h"
#include "offsets.h"
-#include "interpreter/mterp/mterp.h"
+#include "interpreter/mterp/nterp.h"
#include "jit/debugger_interface.h"
#include "jit/profile_saver_options.h"
#include "obj_ptr.h"
diff --git a/runtime/nterp_helpers.cc b/runtime/nterp_helpers.cc
index d622241..7e76bc3 100644
--- a/runtime/nterp_helpers.cc
+++ b/runtime/nterp_helpers.cc
@@ -17,7 +17,7 @@
#include "art_method-inl.h"
#include "dex/code_item_accessors.h"
#include "entrypoints/quick/callee_save_frame.h"
-#include "interpreter/interpreter_mterp_impl.h"
+#include "interpreter/mterp/nterp.h"
#include "nterp_helpers.h"
#include "oat_quick_method_header.h"
#include "quick/quick_method_frame_info.h"
diff --git a/runtime/oat_quick_method_header.cc b/runtime/oat_quick_method_header.cc
index bbc3bfa..543ff72 100644
--- a/runtime/oat_quick_method_header.cc
+++ b/runtime/oat_quick_method_header.cc
@@ -20,7 +20,7 @@
#include "art_method.h"
#include "dex/dex_file_types.h"
#include "interpreter/interpreter_mterp_impl.h"
-#include "interpreter/mterp/mterp.h"
+#include "interpreter/mterp/nterp.h"
#include "nterp_helpers.h"
#include "scoped_thread_state_change-inl.h"
#include "stack_map.h"
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 58a73cc..a5e2f44 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -30,6 +30,7 @@
#include "entrypoints/runtime_asm_entrypoints.h"
#include "gc/space/image_space.h"
#include "gc/space/space-inl.h"
+#include "interpreter/mterp/nterp.h"
#include "interpreter/shadow_frame-inl.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
@@ -766,7 +767,7 @@
// 2 words HandleScope overhead
// 3+3 register spills
// const size_t kMaxExpectedFrameSize = (256 + 2 + 3 + 3) * sizeof(word);
- const size_t kMaxExpectedFrameSize = interpreter::kMaxNterpFrame;
+ const size_t kMaxExpectedFrameSize = interpreter::kNterpMaxFrame;
CHECK_LE(frame_size, kMaxExpectedFrameSize) << method->PrettyMethod();
size_t return_pc_offset = GetCurrentQuickFrameInfo().GetReturnPcOffset();
CHECK_LT(return_pc_offset, frame_size);
diff --git a/tools/cpp-define-generator/globals.def b/tools/cpp-define-generator/globals.def
index 6706fed..50ca3d6 100644
--- a/tools/cpp-define-generator/globals.def
+++ b/tools/cpp-define-generator/globals.def
@@ -23,6 +23,7 @@
#include "gc/accounting/card_table.h"
#include "gc/heap.h"
#include "interpreter/mterp/mterp.h"
+#include "interpreter/mterp/nterp.h"
#include "jit/jit.h"
#include "mirror/object.h"
#include "mirror/object_reference.h"
@@ -80,3 +81,5 @@
std::memory_order_relaxed)
ASM_DEFINE(STACK_OVERFLOW_RESERVED_BYTES,
GetStackOverflowReservedBytes(art::kRuntimeISA))
+ASM_DEFINE(NTERP_HOTNESS_MASK,
+ art::interpreter::kNterpHotnessMask)