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/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()