Add runtime reasons for deopt.

Currently to help investigate. Also:
1) Log when deoptimization happens (which method and what reason)
2) Trace when deoptimization happens (to make it visible in systrace)

bug:37655083
Test: test-art-host test-art-target
Change-Id: I0c2d87b40db09e8e475cf97a7c784a034c585e97
diff --git a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
index 3820d85..5762e4f 100644
--- a/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_deoptimization_entrypoints.cc
@@ -16,6 +16,7 @@
 
 #include "base/logging.h"
 #include "base/mutex.h"
+#include "base/systrace.h"
 #include "callee_save_frame.h"
 #include "interpreter/interpreter.h"
 #include "obj_ptr-inl.h"  // TODO: Find the other include that isn't complete, and clean this up.
@@ -24,8 +25,9 @@
 
 namespace art {
 
-NO_RETURN static void artDeoptimizeImpl(Thread* self, bool single_frame)
+NO_RETURN static void artDeoptimizeImpl(Thread* self, DeoptimizationKind kind, bool single_frame)
     REQUIRES_SHARED(Locks::mutator_lock_) {
+  Runtime::Current()->IncrementDeoptimizationCount(kind);
   if (VLOG_IS_ON(deopt)) {
     if (single_frame) {
       // Deopt logging will be in DeoptimizeSingleFrame. It is there to take advantage of the
@@ -38,10 +40,13 @@
 
   self->AssertHasDeoptimizationContext();
   QuickExceptionHandler exception_handler(self, true);
-  if (single_frame) {
-    exception_handler.DeoptimizeSingleFrame();
-  } else {
-    exception_handler.DeoptimizeStack();
+  {
+    ScopedTrace trace(std::string("Deoptimization ") + GetDeoptimizationKindName(kind));
+    if (single_frame) {
+      exception_handler.DeoptimizeSingleFrame(kind);
+    } else {
+      exception_handler.DeoptimizeStack();
+    }
   }
   uintptr_t return_pc = exception_handler.UpdateInstrumentationStack();
   if (exception_handler.IsFullFragmentDone()) {
@@ -57,18 +62,18 @@
 
 extern "C" NO_RETURN void artDeoptimize(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
-  artDeoptimizeImpl(self, false);
+  artDeoptimizeImpl(self, DeoptimizationKind::kFullFrame, false);
 }
 
-// This is called directly from compiled code by an HDepptimize.
-extern "C" NO_RETURN void artDeoptimizeFromCompiledCode(Thread* self)
+// This is called directly from compiled code by an HDeoptimize.
+extern "C" NO_RETURN void artDeoptimizeFromCompiledCode(DeoptimizationKind kind, Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   ScopedQuickEntrypointChecks sqec(self);
   // Before deoptimizing to interpreter, we must push the deoptimization context.
   JValue return_value;
   return_value.SetJ(0);  // we never deoptimize from compiled code with an invoke result.
   self->PushDeoptimizationContext(return_value, false, /* from_code */ true, self->GetException());
-  artDeoptimizeImpl(self, true);
+  artDeoptimizeImpl(self, kind, true);
 }
 
 }  // namespace art
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index 915f18e..6cd9dc1 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -21,6 +21,7 @@
 
 #include "base/macros.h"
 #include "base/mutex.h"
+#include "deoptimization_kind.h"
 #include "offsets.h"
 
 #define QUICK_ENTRYPOINT_OFFSET(ptr_size, x) \
diff --git a/runtime/entrypoints/quick/quick_entrypoints_list.h b/runtime/entrypoints/quick/quick_entrypoints_list.h
index e0a2e3c..e2d45ac 100644
--- a/runtime/entrypoints/quick/quick_entrypoints_list.h
+++ b/runtime/entrypoints/quick/quick_entrypoints_list.h
@@ -140,7 +140,7 @@
   V(ThrowNullPointer, void, void) \
   V(ThrowStackOverflow, void, void*) \
   V(ThrowStringBounds, void, int32_t, int32_t) \
-  V(Deoptimize, void, void) \
+  V(Deoptimize, void, DeoptimizationKind) \
 \
   V(A64Load, int64_t, volatile const int64_t *) \
   V(A64Store, void, volatile int64_t *, int64_t) \
diff --git a/runtime/entrypoints/runtime_asm_entrypoints.h b/runtime/entrypoints/runtime_asm_entrypoints.h
index 4ca52de..fa287cb 100644
--- a/runtime/entrypoints/runtime_asm_entrypoints.h
+++ b/runtime/entrypoints/runtime_asm_entrypoints.h
@@ -17,6 +17,8 @@
 #ifndef ART_RUNTIME_ENTRYPOINTS_RUNTIME_ASM_ENTRYPOINTS_H_
 #define ART_RUNTIME_ENTRYPOINTS_RUNTIME_ASM_ENTRYPOINTS_H_
 
+#include "deoptimization_kind.h"
+
 namespace art {
 
 #ifndef BUILDING_LIBART
@@ -77,7 +79,7 @@
 }
 
 // Stub to deoptimize from compiled code.
-extern "C" void art_quick_deoptimize_from_compiled_code();
+extern "C" void art_quick_deoptimize_from_compiled_code(DeoptimizationKind);
 
 // The return_pc of instrumentation exit stub.
 extern "C" void art_quick_instrumentation_exit();