Use stack allocated context for VisitRoots

Prevents allocation of contexts for threads that do not throw
exceptions.

Saves up to 544 per thread on arm64.

Bug: 36457259

Test: mm test-art-host on with N6P target (build covers arm32, arm64)
Change-Id: I782a1115d624edcc1279fa2317d026408dfa8a10
diff --git a/runtime/arch/context-inl.h b/runtime/arch/context-inl.h
new file mode 100644
index 0000000..ddcbbb1
--- /dev/null
+++ b/runtime/arch/context-inl.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+// This file is special-purpose for cases where you want a stack context. Most users should use
+// Context::Create().
+
+#include "context.h"
+
+#ifndef ART_RUNTIME_ARCH_CONTEXT_INL_H_
+#define ART_RUNTIME_ARCH_CONTEXT_INL_H_
+
+#if defined(__arm__)
+#include "arm/context_arm.h"
+#define RUNTIME_CONTEXT_TYPE arm::ArmContext
+#elif defined(__aarch64__)
+#include "arm64/context_arm64.h"
+#define RUNTIME_CONTEXT_TYPE arm64::Arm64Context
+#elif defined(__mips__) && !defined(__LP64__)
+#include "mips/context_mips.h"
+#define RUNTIME_CONTEXT_TYPE mips::MipsContext
+#elif defined(__mips__) && defined(__LP64__)
+#include "mips64/context_mips64.h"
+#define RUNTIME_CONTEXT_TYPE mips64::Mips64Context
+#elif defined(__i386__)
+#include "x86/context_x86.h"
+#define RUNTIME_CONTEXT_TYPE x86::X86Context
+#elif defined(__x86_64__)
+#include "x86_64/context_x86_64.h"
+#define RUNTIME_CONTEXT_TYPE x86_64::X86_64Context
+#else
+#error unimplemented
+#endif
+
+namespace art {
+
+using RuntimeContextType = RUNTIME_CONTEXT_TYPE;
+
+}  // namespace art
+
+#undef RUNTIME_CONTEXT_TYPE
+
+#endif  // ART_RUNTIME_ARCH_CONTEXT_INL_H_
diff --git a/runtime/arch/context.cc b/runtime/arch/context.cc
index bf40a3f..82d8b6c 100644
--- a/runtime/arch/context.cc
+++ b/runtime/arch/context.cc
@@ -14,43 +14,12 @@
  * limitations under the License.
  */
 
-#include "context.h"
-
-#if defined(__arm__)
-#include "arm/context_arm.h"
-#elif defined(__aarch64__)
-#include "arm64/context_arm64.h"
-#elif defined(__mips__) && !defined(__LP64__)
-#include "mips/context_mips.h"
-#elif defined(__mips__) && defined(__LP64__)
-#include "mips64/context_mips64.h"
-#elif defined(__i386__)
-#include "x86/context_x86.h"
-#elif defined(__x86_64__)
-#include "x86_64/context_x86_64.h"
-#else
-#include "base/logging.h"
-#endif
+#include "context-inl.h"
 
 namespace art {
 
 Context* Context::Create() {
-#if defined(__arm__)
-  return new arm::ArmContext();
-#elif defined(__aarch64__)
-  return new arm64::Arm64Context();
-#elif defined(__mips__) && !defined(__LP64__)
-  return new mips::MipsContext();
-#elif defined(__mips__) && defined(__LP64__)
-  return new mips64::Mips64Context();
-#elif defined(__i386__)
-  return new x86::X86Context();
-#elif defined(__x86_64__)
-  return new x86_64::X86_64Context();
-#else
-  UNIMPLEMENTED(FATAL);
-  return nullptr;
-#endif
+  return new RuntimeContextType;
 }
 
 }  // namespace art
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 201701a..62a616b 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -35,6 +35,7 @@
 #include "android-base/stringprintf.h"
 
 #include "arch/context.h"
+#include "arch/context-inl.h"
 #include "art_field-inl.h"
 #include "art_method-inl.h"
 #include "base/bit_utils.h"
@@ -3413,11 +3414,10 @@
     verifier->VisitRoots(visitor, RootInfo(kRootNativeStack, thread_id));
   }
   // Visit roots on this thread's stack
-  Context* context = GetLongJumpContext();
+  RuntimeContextType context;
   RootCallbackVisitor visitor_to_callback(visitor, thread_id);
-  ReferenceMapVisitor<RootCallbackVisitor, kPrecise> mapper(this, context, visitor_to_callback);
+  ReferenceMapVisitor<RootCallbackVisitor, kPrecise> mapper(this, &context, visitor_to_callback);
   mapper.template WalkStack<StackVisitor::CountTransitions::kNo>(false);
-  ReleaseLongJumpContext(context);
   for (instrumentation::InstrumentationStackFrame& frame : *GetInstrumentationStack()) {
     visitor->VisitRootIfNonNull(&frame.this_object_, RootInfo(kRootVMInternal, thread_id));
   }