Pulled out instrumentation into its own class separate from trace.

This is in preparation for Ian's debugger changes. The instrumentation
still needs support for debugging, which I'll add later.

Change-Id: I29ce0af1ff2eaec8f6d2f54963263381363ebf72
diff --git a/src/class_linker.cc b/src/class_linker.cc
index ce9b37b..689b928 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1577,12 +1577,12 @@
   for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
     AbstractMethod* method = klass->GetDirectMethod(i);
     if (Runtime::Current()->IsMethodTracingActive()) {
-      Trace* tracer = Runtime::Current()->GetTracer();
-      if (tracer->GetSavedCodeFromMap(method) == trampoline) {
+      Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+      if (instrumentation->GetSavedCodeFromMap(method) == trampoline) {
         const void* code = oat_class->GetOatMethod(method_index).GetCode();
-        tracer->ResetSavedCode(method);
+        instrumentation->ResetSavedCode(method);
         method->SetCode(code);
-        tracer->SaveAndUpdateCode(method);
+        instrumentation->SaveAndUpdateCode(method);
       }
     } else if (method->GetCode() == trampoline) {
       const void* code = oat_class->GetOatMethod(method_index).GetCode();
@@ -1618,8 +1618,8 @@
   }
 
   if (Runtime::Current()->IsMethodTracingActive()) {
-    Trace* tracer = Runtime::Current()->GetTracer();
-    tracer->SaveAndUpdateCode(method.get());
+    Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+    instrumentation->SaveAndUpdateCode(method.get());
   }
 }
 
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 0e0500c..43d1a4c 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -150,7 +150,7 @@
 void art_throw_null_pointer_exception_from_code(uint32_t dex_pc)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Thread* thread = art_get_current_thread_from_code();
-  NthCallerVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), 0);
+  NthCallerVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), 0);
   visitor.WalkStack();
   AbstractMethod* throw_method = visitor.caller;
   ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc);
@@ -160,7 +160,7 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Thread* thread = art_get_current_thread_from_code();
   if (Runtime::Current()->IsMethodTracingActive()) {
-    TraceMethodUnwindFromCode(thread);
+    InstrumentationMethodUnwindFromCode(thread);
   }
   thread->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute.
   thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;", "stack size %s",
diff --git a/src/debugger.cc b/src/debugger.cc
index 7de675c..1d8b997 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -1543,8 +1543,8 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   struct CountStackDepthVisitor : public StackVisitor {
     CountStackDepthVisitor(const ManagedStack* stack,
-                           const std::vector<TraceStackFrame>* trace_stack)
-        : StackVisitor(stack, trace_stack, NULL), depth(0) {}
+                           const std::vector<InstrumentationStackFrame>* instrumentation_stack)
+        : StackVisitor(stack, instrumentation_stack, NULL), depth(0) {}
 
     bool VisitFrame() {
       if (!GetMethod()->IsRuntimeMethod()) {
@@ -1559,7 +1559,7 @@
     MutexLock mu(Thread::Current(), *Locks::thread_suspend_count_lock_);
     CHECK(thread->IsSuspended());
   }
-  CountStackDepthVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack());
+  CountStackDepthVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack());
   visitor.WalkStack();
   return visitor.depth;
 }
@@ -1572,10 +1572,10 @@
 JDWP::JdwpError Dbg::GetThreadFrames(JDWP::ObjectId thread_id, size_t start_frame, size_t frame_count, JDWP::ExpandBuf* buf) {
   class GetFrameVisitor : public StackVisitor {
    public:
-    GetFrameVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
+    GetFrameVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack,
                     size_t start_frame, size_t frame_count, JDWP::ExpandBuf* buf)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : StackVisitor(stack, trace_stack, NULL), depth_(0),
+        : StackVisitor(stack, instrumentation_stack, NULL), depth_(0),
           start_frame_(start_frame), frame_count_(frame_count), buf_(buf) {
       expandBufAdd4BE(buf_, frame_count_);
     }
@@ -1610,7 +1610,7 @@
 
   ScopedObjectAccessUnchecked soa(Thread::Current());
   Thread* thread = DecodeThread(soa, thread_id);  // Caller already checked thread is suspended.
-  GetFrameVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), start_frame, frame_count, buf);
+  GetFrameVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), start_frame, frame_count, buf);
   visitor.WalkStack();
   return JDWP::ERR_NONE;
 }
@@ -1675,10 +1675,10 @@
 }
 
 struct GetThisVisitor : public StackVisitor {
-  GetThisVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
+  GetThisVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack,
                  Context* context, JDWP::FrameId frameId)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(stack, trace_stack, context), this_object(NULL), frame_id(frameId) {}
+      : StackVisitor(stack, instrumentation_stack, context), this_object(NULL), frame_id(frameId) {}
 
   // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
   // annotalysis.
@@ -1708,7 +1708,7 @@
   }
 
   UniquePtr<Context> context(Context::Create());
-  GetThisVisitor visitor(self->GetManagedStack(), self->GetTraceStack(), context.get(), frame_id);
+  GetThisVisitor visitor(self->GetManagedStack(), self->GetInstrumentationStack(), context.get(), frame_id);
   visitor.WalkStack();
   return visitor.this_object;
 }
@@ -1729,7 +1729,7 @@
     }
   }
   UniquePtr<Context> context(Context::Create());
-  GetThisVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), context.get(), frame_id);
+  GetThisVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), context.get(), frame_id);
   visitor.WalkStack();
   *result = gRegistry->Add(visitor.this_object);
   return JDWP::ERR_NONE;
@@ -1738,11 +1738,11 @@
 void Dbg::GetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag,
                         uint8_t* buf, size_t width) {
   struct GetLocalVisitor : public StackVisitor {
-    GetLocalVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
+    GetLocalVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack,
                     Context* context, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag,
                     uint8_t* buf, size_t width)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : StackVisitor(stack, trace_stack, context), frame_id_(frameId), slot_(slot), tag_(tag),
+        : StackVisitor(stack, instrumentation_stack, context), frame_id_(frameId), slot_(slot), tag_(tag),
           buf_(buf), width_(width) {}
 
     // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
@@ -1849,7 +1849,7 @@
   ScopedObjectAccessUnchecked soa(Thread::Current());
   Thread* thread = DecodeThread(soa, threadId);
   UniquePtr<Context> context(Context::Create());
-  GetLocalVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), context.get(),
+  GetLocalVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), context.get(),
                           frameId, slot, tag, buf, width);
   visitor.WalkStack();
 }
@@ -1857,11 +1857,11 @@
 void Dbg::SetLocalValue(JDWP::ObjectId threadId, JDWP::FrameId frameId, int slot, JDWP::JdwpTag tag,
                         uint64_t value, size_t width) {
   struct SetLocalVisitor : public StackVisitor {
-    SetLocalVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack, Context* context,
+    SetLocalVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack, Context* context,
                     JDWP::FrameId frame_id, int slot, JDWP::JdwpTag tag, uint64_t value,
                     size_t width)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : StackVisitor(stack, trace_stack, context),
+        : StackVisitor(stack, instrumentation_stack, context),
           frame_id_(frame_id), slot_(slot), tag_(tag), value_(value), width_(width) {}
 
     // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
@@ -1925,7 +1925,7 @@
   ScopedObjectAccessUnchecked soa(Thread::Current());
   Thread* thread = DecodeThread(soa, threadId);
   UniquePtr<Context> context(Context::Create());
-  SetLocalVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), context.get(),
+  SetLocalVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), context.get(),
                           frameId, slot, tag, value, width);
   visitor.WalkStack();
 }
@@ -1965,7 +1965,7 @@
 
   // We need 'this' for InstanceOnly filters.
   UniquePtr<Context> context(Context::Create());
-  GetThisVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack(), context.get(), throw_frame_id);
+  GetThisVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), context.get(), throw_frame_id);
   visitor.WalkStack();
   JDWP::ObjectId this_id = gRegistry->Add(visitor.this_object);
 
@@ -2147,10 +2147,10 @@
 
   struct SingleStepStackVisitor : public StackVisitor {
     SingleStepStackVisitor(const ManagedStack* stack,
-                           const std::vector<TraceStackFrame>* trace_stack)
+                           const std::vector<InstrumentationStackFrame>* instrumentation_stack)
         EXCLUSIVE_LOCKS_REQUIRED(gBreakpointsLock)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : StackVisitor(stack, trace_stack, NULL) {
+        : StackVisitor(stack, instrumentation_stack, NULL) {
       gBreakpointsLock.AssertHeld(Thread::Current());
       gSingleStepControl.method = NULL;
       gSingleStepControl.stack_depth = 0;
@@ -2176,7 +2176,7 @@
       return true;
     }
   };
-  SingleStepStackVisitor visitor(thread->GetManagedStack(), thread->GetTraceStack());
+  SingleStepStackVisitor visitor(thread->GetManagedStack(), thread->GetInstrumentationStack());
   visitor.WalkStack();
 
   //
@@ -2679,7 +2679,7 @@
     ScopedObjectAccessUnchecked soa(Thread::Current());
     SirtRef<String> name(soa.Self(), t->GetThreadName(soa));
     size_t char_count = (name.get() != NULL) ? name->GetLength() : 0;
-    const jchar* chars = name->GetCharArray()->GetData();
+    const jchar* chars = (name.get() != NULL) ? name->GetCharArray()->GetData() : NULL;
 
     std::vector<uint8_t> bytes;
     JDWP::Append4BE(bytes, t->GetThinLockId());
@@ -3130,9 +3130,9 @@
 
 struct AllocRecordStackVisitor : public StackVisitor {
   AllocRecordStackVisitor(const ManagedStack* stack,
-                          const std::vector<TraceStackFrame>* trace_stack, AllocRecord* record)
+                          const std::vector<InstrumentationStackFrame>* instrumentation_stack, AllocRecord* record)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(stack, trace_stack, NULL), record(record), depth(0) {}
+      : StackVisitor(stack, instrumentation_stack, NULL), record(record), depth(0) {}
 
   // TODO: Enable annotalysis. We know lock is held in constructor, but abstraction confuses
   // annotalysis.
@@ -3182,7 +3182,7 @@
   record->thin_lock_id = self->GetThinLockId();
 
   // Fill in the stack trace.
-  AllocRecordStackVisitor visitor(self->GetManagedStack(), self->GetTraceStack(), record);
+  AllocRecordStackVisitor visitor(self->GetManagedStack(), self->GetInstrumentationStack(), record);
   visitor.WalkStack();
 
   if (gAllocRecordCount < kNumAllocRecords) {
diff --git a/src/instrumentation.cc b/src/instrumentation.cc
new file mode 100644
index 0000000..d796aef
--- /dev/null
+++ b/src/instrumentation.cc
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "instrumentation.h"
+
+#include <sys/uio.h>
+
+#include "class_linker.h"
+#include "debugger.h"
+#include "dex_cache.h"
+#if !defined(ART_USE_LLVM_COMPILER)
+#include "oat/runtime/oat_support_entrypoints.h"
+#endif
+#include "object_utils.h"
+#include "os.h"
+#include "scoped_thread_state_change.h"
+#include "thread.h"
+#include "thread_list.h"
+#include "trace.h"
+
+namespace art {
+
+static bool InstallStubsClassVisitor(Class* klass, void*)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
+    AbstractMethod* method = klass->GetDirectMethod(i);
+    if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
+      instrumentation->SaveAndUpdateCode(method);
+    }
+  }
+
+  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
+    AbstractMethod* method = klass->GetVirtualMethod(i);
+    if (instrumentation->GetSavedCodeFromMap(method) == NULL) {
+      instrumentation->SaveAndUpdateCode(method);
+    }
+  }
+  return true;
+}
+
+static bool UninstallStubsClassVisitor(Class* klass, void*)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
+    AbstractMethod* method = klass->GetDirectMethod(i);
+    if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
+      instrumentation->ResetSavedCode(method);
+    }
+  }
+
+  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
+    AbstractMethod* method = klass->GetVirtualMethod(i);
+    if (instrumentation->GetSavedCodeFromMap(method) != NULL) {
+      instrumentation->ResetSavedCode(method);
+    }
+  }
+  return true;
+}
+
+static void InstrumentationRestoreStack(Thread* self, void*) NO_THREAD_SAFETY_ANALYSIS {
+  struct RestoreStackVisitor : public StackVisitor {
+    RestoreStackVisitor(Thread* self)
+        : StackVisitor(self->GetManagedStack(), self->GetInstrumentationStack(), NULL), self_(self) {}
+
+    virtual bool VisitFrame() {
+      if (self_->IsInstrumentationStackEmpty()) {
+        return false;  // Stop.
+      }
+      uintptr_t pc = GetReturnPc();
+      if (IsInstrumentationExitPc(pc)) {
+        InstrumentationStackFrame instrumentation_frame = self_->PopInstrumentationStackFrame();
+        SetReturnPc(instrumentation_frame.return_pc_);
+        CHECK(GetMethod() == instrumentation_frame.method_);
+      }
+      return true;  // Continue.
+    }
+
+    Thread* self_;
+  };
+  RestoreStackVisitor visitor(self);
+  visitor.WalkStack();
+}
+
+Instrumentation::~Instrumentation() {
+  delete trace_;
+}
+
+void Instrumentation::InstallStubs() {
+  Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, NULL);
+}
+
+void Instrumentation::UninstallStubs() {
+  Thread* self = Thread::Current();
+  Locks::thread_list_lock_->AssertNotHeld(self);
+  Runtime::Current()->GetClassLinker()->VisitClasses(UninstallStubsClassVisitor, NULL);
+  MutexLock mu(self, *Locks::thread_list_lock_);
+  Runtime::Current()->GetThreadList()->ForEach(InstrumentationRestoreStack, NULL);
+}
+
+void Instrumentation::AddSavedCodeToMap(const AbstractMethod* method, const void* code) {
+  saved_code_map_.Put(method, code);
+}
+
+void Instrumentation::RemoveSavedCodeFromMap(const AbstractMethod* method) {
+  saved_code_map_.erase(method);
+}
+
+const void* Instrumentation::GetSavedCodeFromMap(const AbstractMethod* method) {
+  typedef SafeMap<const AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto
+  It it = saved_code_map_.find(method);
+  if (it == saved_code_map_.end()) {
+    return NULL;
+  } else {
+    return it->second;
+  }
+}
+
+void Instrumentation::SaveAndUpdateCode(AbstractMethod* method) {
+#if defined(ART_USE_LLVM_COMPILER)
+  UNUSED(method);
+  UNIMPLEMENTED(FATAL);
+#else
+  void* instrumentation_stub = GetInstrumentationEntryPoint();
+  CHECK(GetSavedCodeFromMap(method) == NULL);
+  AddSavedCodeToMap(method, method->GetCode());
+  method->SetCode(instrumentation_stub);
+#endif
+}
+
+void Instrumentation::ResetSavedCode(AbstractMethod* method) {
+  CHECK(GetSavedCodeFromMap(method) != NULL);
+  method->SetCode(GetSavedCodeFromMap(method));
+  RemoveSavedCodeFromMap(method);
+}
+
+Trace* Instrumentation::GetTrace() const {
+  return trace_;
+}
+
+void Instrumentation::SetTrace(Trace* trace) {
+  trace_ = trace;
+}
+
+void Instrumentation::RemoveTrace() {
+  delete trace_;
+  trace_ = NULL;
+}
+
+uint32_t InstrumentationMethodUnwindFromCode(Thread* self) {
+  Trace* trace = Runtime::Current()->GetInstrumentation()->GetTrace();
+  InstrumentationStackFrame instrumentation_frame = self->PopInstrumentationStackFrame();
+  AbstractMethod* method = instrumentation_frame.method_;
+  uint32_t lr = instrumentation_frame.return_pc_;
+
+  trace->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
+
+  return lr;
+}
+
+}  // namespace art
diff --git a/src/instrumentation.h b/src/instrumentation.h
new file mode 100644
index 0000000..a5ab650
--- /dev/null
+++ b/src/instrumentation.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2011 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_SRC_INSTRUMENTATION_H_
+#define ART_SRC_INSTRUMENTATION_H_
+
+#include <ostream>
+#include <set>
+#include <string>
+
+#include "file.h"
+#include "globals.h"
+#include "macros.h"
+#include "safe_map.h"
+#include "trace.h"
+#include "UniquePtr.h"
+
+namespace art {
+
+class AbstractMethod;
+class Thread;
+
+uint32_t InstrumentationMethodUnwindFromCode(Thread* self);
+
+struct InstrumentationStackFrame {
+  InstrumentationStackFrame(AbstractMethod* method, uintptr_t return_pc)
+      : method_(method), return_pc_(return_pc) {
+  }
+
+  AbstractMethod* method_;
+  uintptr_t return_pc_;
+};
+
+class Instrumentation {
+ public:
+  Instrumentation() {}
+  ~Instrumentation();
+
+  // Replaces code of each method with a pointer to a stub for method tracing.
+  void InstallStubs();
+
+  // Restores original code for each method and fixes the return values of each thread's stack.
+  void UninstallStubs() LOCKS_EXCLUDED(Locks::thread_list_lock_);
+
+  const void* GetSavedCodeFromMap(const AbstractMethod* method);
+  void SaveAndUpdateCode(AbstractMethod* method);
+  void ResetSavedCode(AbstractMethod* method);
+
+  Trace* GetTrace() const;
+  void SetTrace(Trace* trace);
+  void RemoveTrace();
+
+ private:
+  void AddSavedCodeToMap(const AbstractMethod* method, const void* code);
+  void RemoveSavedCodeFromMap(const AbstractMethod* method);
+
+  // Maps a method to its original code pointer.
+  SafeMap<const AbstractMethod*, const void*> saved_code_map_;
+
+  Trace* trace_;
+
+  DISALLOW_COPY_AND_ASSIGN(Instrumentation);
+};
+
+}  // namespace art
+
+#endif  // ART_SRC_INSTRUMENTATION_H_
diff --git a/src/native/dalvik_system_VMStack.cc b/src/native/dalvik_system_VMStack.cc
index 24aa730..5ef512a 100644
--- a/src/native/dalvik_system_VMStack.cc
+++ b/src/native/dalvik_system_VMStack.cc
@@ -63,7 +63,7 @@
 // Returns the defining class loader of the caller's caller.
 static jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) {
   ScopedObjectAccess soa(env);
-  NthCallerVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetTraceStack(), 2);
+  NthCallerVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetInstrumentationStack(), 2);
   visitor.WalkStack();
   return soa.AddLocalReference<jobject>(visitor.caller->GetDeclaringClass()->GetClassLoader());
 }
@@ -71,9 +71,9 @@
 static jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass, jobject javaBootstrap, jobject javaSystem) {
   struct ClosestUserClassLoaderVisitor : public StackVisitor {
     ClosestUserClassLoaderVisitor(const ManagedStack* stack,
-                                  const std::vector<TraceStackFrame>* trace_stack,
+                                  const std::vector<InstrumentationStackFrame>* instrumentation_stack,
                                   Object* bootstrap, Object* system)
-      : StackVisitor(stack, trace_stack, NULL),
+      : StackVisitor(stack, instrumentation_stack, NULL),
         bootstrap(bootstrap), system(system), class_loader(NULL) {}
 
     bool VisitFrame() {
@@ -94,7 +94,7 @@
   ScopedObjectAccess soa(env);
   Object* bootstrap = soa.Decode<Object*>(javaBootstrap);
   Object* system = soa.Decode<Object*>(javaSystem);
-  ClosestUserClassLoaderVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetTraceStack(),
+  ClosestUserClassLoaderVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetInstrumentationStack(),
                                         bootstrap, system);
   visitor.WalkStack();
   return soa.AddLocalReference<jobject>(visitor.class_loader);
@@ -103,7 +103,7 @@
 // Returns the class of the caller's caller's caller.
 static jclass VMStack_getStackClass2(JNIEnv* env, jclass) {
   ScopedObjectAccess soa(env);
-  NthCallerVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetTraceStack(), 3);
+  NthCallerVisitor visitor(soa.Self()->GetManagedStack(), soa.Self()->GetInstrumentationStack(), 3);
   visitor.WalkStack();
   return soa.AddLocalReference<jclass>(visitor.caller->GetDeclaringClass());
 }
diff --git a/src/nth_caller_visitor.h b/src/nth_caller_visitor.h
index 6b3894e..3c1f2e0 100644
--- a/src/nth_caller_visitor.h
+++ b/src/nth_caller_visitor.h
@@ -24,8 +24,8 @@
 
 // Walks up the stack 'n' callers, when used with Thread::WalkStack.
 struct NthCallerVisitor : public StackVisitor {
-  NthCallerVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack, size_t n)
-      : StackVisitor(stack, trace_stack, NULL), n(n), count(0), caller(NULL) {}
+  NthCallerVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack, size_t n)
+      : StackVisitor(stack, instrumentation_stack, NULL), n(n), count(0), caller(NULL) {}
 
   bool VisitFrame() {
     DCHECK(caller == NULL);
diff --git a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
index 39674b6..e363cbe 100644
--- a/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
+++ b/src/oat/runtime/arm/oat_support_entrypoints_arm.cc
@@ -147,9 +147,9 @@
 extern "C" void art_throw_null_pointer_exception_from_code();
 extern "C" void art_throw_stack_overflow_from_code(void*);
 
-// Trace entrypoints.
-extern "C" void art_trace_entry_from_code(void*);
-extern "C" void art_trace_exit_from_code();
+// Instrumentation entrypoints.
+extern "C" void art_instrumentation_entry_from_code(void*);
+extern "C" void art_instrumentation_exit_from_code();
 
 void InitEntryPoints(EntryPoints* points) {
   // Alloc
@@ -275,13 +275,13 @@
   points->pUpdateDebuggerFromCode = (enabled ? art_update_debugger : NULL);
 }
 
-bool IsTraceExitPc(uintptr_t pc) {
-  uintptr_t trace_exit = reinterpret_cast<uintptr_t>(art_trace_exit_from_code);
+bool IsInstrumentationExitPc(uintptr_t pc) {
+  uintptr_t trace_exit = reinterpret_cast<uintptr_t>(art_instrumentation_exit_from_code);
   return pc == trace_exit;
 }
 
-void* GetLogTraceEntryPoint() {
-  return reinterpret_cast<void*>(art_trace_entry_from_code);
+void* GetInstrumentationEntryPoint() {
+  return reinterpret_cast<void*>(art_instrumentation_entry_from_code);
 }
 
 }  // namespace art
diff --git a/src/oat/runtime/arm/runtime_support_arm.S b/src/oat/runtime/arm/runtime_support_arm.S
index 7cb65e2..34caeac 100644
--- a/src/oat/runtime/arm/runtime_support_arm.S
+++ b/src/oat/runtime/arm/runtime_support_arm.S
@@ -771,25 +771,25 @@
     bxeq    lr                     @ return on success
     DELIVER_PENDING_EXCEPTION
 
-    .global art_trace_entry_from_code
-    .global art_trace_exit_from_code
-    .extern artTraceMethodEntryFromCode
-    .extern artTraceMethodExitFromCode
+    .global art_instrumentation_entry_from_code
+    .global art_instrumentation_exit_from_code
+    .extern artInstrumentationMethodEntryFromCode
+    .extern artInstrumentationMethodExitFromCode
     /*
      * Routine that intercepts method calls and returns.
      */
     ALIGN_FUNCTION_ENTRY
-art_trace_entry_from_code:
+art_instrumentation_entry_from_code:
     push  {r0-r3}        @ save arguments (4 words)
     mov   r1, r9         @ pass Thread::Current
     mov   r2, lr         @ pass LR
-    blx   artTraceMethodEntryFromCode  @ (Method*, Thread*, LR)
+    blx   artInstrumentationMethodEntryFromCode  @ (Method*, Thread*, LR)
     mov   r12, r0        @ r12 holds reference to code
     pop   {r0-r3}        @ restore arguments
     blx   r12            @ call method
-art_trace_exit_from_code:
+art_instrumentation_exit_from_code:
     push  {r0-r1}        @ save return value
-    blx   artTraceMethodExitFromCode  @ ()
+    blx   artInstrumentationMethodExitFromCode  @ ()
     mov   lr, r0         @ restore link register
     pop   {r0, r1}       @ restore return value
     bx    lr             @ return
diff --git a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
index 458933f..9327955 100644
--- a/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
+++ b/src/oat/runtime/mips/oat_support_entrypoints_mips.cc
@@ -149,9 +149,9 @@
 extern "C" void art_throw_null_pointer_exception_from_code();
 extern "C" void art_throw_stack_overflow_from_code(void*);
 
-// Trace entrypoints.
-extern "C" void art_trace_entry_from_code(void*);
-extern "C" void art_trace_exit_from_code();
+// Instrumentation entrypoints.
+extern "C" void art_instrumentation_entry_from_code(void*);
+extern "C" void art_instrumentation_exit_from_code();
 
 void InitEntryPoints(EntryPoints* points) {
   // Alloc
@@ -276,12 +276,12 @@
   points->pUpdateDebuggerFromCode = (enabled ? art_update_debugger : NULL);
 }
 
-bool IsTraceExitPc(uintptr_t) {
+bool IsInstrumentationExitPc(uintptr_t) {
   UNIMPLEMENTED(FATAL);
   return false;
 }
 
-void* GetLogTraceEntryPoint() {
+void* GetInstrumentationEntryPoint() {
   UNIMPLEMENTED(FATAL);
   return NULL;
 }
diff --git a/src/oat/runtime/mips/runtime_support_mips.S b/src/oat/runtime/mips/runtime_support_mips.S
index bc0aecf..849e5c4 100644
--- a/src/oat/runtime/mips/runtime_support_mips.S
+++ b/src/oat/runtime/mips/runtime_support_mips.S
@@ -859,13 +859,15 @@
 1:
     DELIVER_PENDING_EXCEPTION
 
-    .global art_trace_entry_from_code
-    .extern artTraceMethodEntryFromCode
+    .global art_instrumentation_entry_from_code
+    .global art_instrumentation_exit_from_code
+    .extern artInstrumentationMethodEntryFromCode
+    .extern artInstrumentationMethodExitFromCode
     /*
-     * Routine that intercepts method calls
+     * Routine that intercepts method calls and returns.
      */
     ALIGN_FUNCTION_ENTRY
-art_trace_entry_from_code:
+art_instrumentation_entry_from_code:
     .cpload $25
     addiu    $sp, $sp, -16
     sw       $a0, 0($sp)
@@ -873,7 +875,7 @@
     sw       $a2, 8($sp)
     sw       $a3, 12($sp)
     move     $a2, $ra       # pass $ra
-    jal      artTraceMethodEntryFromCode  # (Method*, Thread*, LR)
+    jal      artInstrumentationMethodEntryFromCode  # (Method*, Thread*, LR)
     move     $a1, rSELF     # pass Thread::Current
     move     $t9, $v0       # $t9 holds reference to code
     lw       $a0, 0($sp)
@@ -883,18 +885,11 @@
     jalr     $t9            # call method
     addiu    $sp, $sp, 16
     /* intentional fallthrough */
-
-    .global art_trace_exit_from_code
-    .extern artTraceMethodExitFromCode
-    /*
-     * Routine that intercepts method returns
-     */
-    ALIGN_FUNCTION_ENTRY
-art_trace_exit_from_code:
+art_instrumentation_exit_from_code:
     .cpload $25
     addiu    $sp, $sp, -16
     sw       $v0, 0($sp)
-    jal      artTraceMethodExitFromCode  # ()
+    jal      artInstrumentationMethodExitFromCode  # ()
     sw       $v1, 4($sp)
     move     $ra, $v0         # restore link register
     lw       $v0, 0($sp)
diff --git a/src/oat/runtime/oat_support_entrypoints.h b/src/oat/runtime/oat_support_entrypoints.h
index 5042bd1..e63e1fd 100644
--- a/src/oat/runtime/oat_support_entrypoints.h
+++ b/src/oat/runtime/oat_support_entrypoints.h
@@ -158,11 +158,11 @@
 // Change the debugger entry point in the data structure.
 void ChangeDebuggerEntryPoint(EntryPoints* points, bool enabled);
 
-// Is the given return_pc the trace exit return pc?
-bool IsTraceExitPc(uintptr_t pc);
+// Is the given return_pc the instrumentation exit return pc?
+bool IsInstrumentationExitPc(uintptr_t pc);
 
-// Return address of stub that logs method entries.
-void* GetLogTraceEntryPoint();
+// Return address of instrumentation stub.
+void* GetInstrumentationEntryPoint();
 
 }  // namespace art
 
diff --git a/src/oat/runtime/support_instrumentation.cc b/src/oat/runtime/support_instrumentation.cc
new file mode 100644
index 0000000..8c5e442
--- /dev/null
+++ b/src/oat/runtime/support_instrumentation.cc
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#include "instrumentation.h"
+#include "runtime.h"
+#include "thread.h"
+#include "trace.h"
+
+namespace art {
+
+extern "C" const void* artInstrumentationMethodEntryFromCode(AbstractMethod* method, Thread* self,
+                                                             uintptr_t lr) {
+  Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
+  Trace* trace = instrumentation->GetTrace();
+  InstrumentationStackFrame instrumentation_frame = InstrumentationStackFrame(method, lr);
+  self->PushInstrumentationStackFrame(instrumentation_frame);
+
+  trace->LogMethodTraceEvent(self, method, Trace::kMethodTraceEnter);
+
+  return instrumentation->GetSavedCodeFromMap(method);
+}
+
+extern "C" uintptr_t artInstrumentationMethodExitFromCode() {
+  Trace* trace = Runtime::Current()->GetInstrumentation()->GetTrace();
+  InstrumentationStackFrame instrumentation_frame = Thread::Current()->PopInstrumentationStackFrame();
+  AbstractMethod* method = instrumentation_frame.method_;
+  uintptr_t lr = instrumentation_frame.return_pc_;
+
+  trace->LogMethodTraceEvent(Thread::Current(), method, Trace::kMethodTraceExit);
+
+  return lr;
+}
+
+}  // namespace art
diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc
index 887e743..420b442 100644
--- a/src/oat/runtime/support_throw.cc
+++ b/src/oat/runtime/support_throw.cc
@@ -94,7 +94,7 @@
   CHECK(!self->IsHandlingStackOverflow()) << "Recursive stack overflow.";
   // Remove extra entry pushed onto second stack during method tracing.
   if (Runtime::Current()->IsMethodTracingActive()) {
-    TraceMethodUnwindFromCode(self);
+    InstrumentationMethodUnwindFromCode(self);
   }
   self->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute.
   JNIEnvExt* env = self->GetJniEnv();
diff --git a/src/oat/runtime/support_trace.cc b/src/oat/runtime/support_trace.cc
deleted file mode 100644
index 67317a9..0000000
--- a/src/oat/runtime/support_trace.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#include "runtime.h"
-#include "thread.h"
-#include "trace.h"
-
-namespace art {
-
-extern "C" const void* artTraceMethodEntryFromCode(AbstractMethod* method, Thread* self, uintptr_t lr) {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  TraceStackFrame trace_frame = TraceStackFrame(method, lr);
-  self->PushTraceStackFrame(trace_frame);
-
-  tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceEnter);
-
-  return tracer->GetSavedCodeFromMap(method);
-}
-
-extern "C" uintptr_t artTraceMethodExitFromCode() {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  TraceStackFrame trace_frame = Thread::Current()->PopTraceStackFrame();
-  AbstractMethod* method = trace_frame.method_;
-  uintptr_t lr = trace_frame.return_pc_;
-
-  tracer->LogMethodTraceEvent(Thread::Current(), method, Trace::kMethodTraceExit);
-
-  return lr;
-}
-
-}  // namespace art
diff --git a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
index 802c431..c2236d7 100644
--- a/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
+++ b/src/oat/runtime/x86/oat_support_entrypoints_x86.cc
@@ -245,11 +245,11 @@
   UNIMPLEMENTED(FATAL);
 }
 
-bool IsTraceExitPc(uintptr_t) {
+bool IsInstrumentationExitPc(uintptr_t) {
   return false;
 }
 
-void* GetLogTraceEntryPoint() {
+void* GetInstrumentationEntryPoint() {
   return NULL;
 }
 
diff --git a/src/object.cc b/src/object.cc
index cebbb2a..aaaa245 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -540,8 +540,8 @@
   Runtime* runtime = Runtime::Current();
   const void* code = m->GetCode();
   // Peel off any method tracing trampoline.
-  if (runtime->IsMethodTracingActive() && runtime->GetTracer()->GetSavedCodeFromMap(m) != NULL) {
-    code = runtime->GetTracer()->GetSavedCodeFromMap(m);
+  if (runtime->IsMethodTracingActive() && runtime->GetInstrumentation()->GetSavedCodeFromMap(m) != NULL) {
+    code = runtime->GetInstrumentation()->GetSavedCodeFromMap(m);
   }
   // Peel off any resolution stub.
   if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
diff --git a/src/runtime.cc b/src/runtime.cc
index c84f1f6..4cc3b4f 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -32,6 +32,7 @@
 #include "debugger.h"
 #include "heap.h"
 #include "image.h"
+#include "instrumentation.h"
 #include "intern_table.h"
 #include "jni_internal.h"
 #include "monitor.h"
@@ -88,7 +89,7 @@
       stats_enabled_(false),
       method_trace_(0),
       method_trace_file_size_(0),
-      tracer_(NULL),
+      instrumentation_(NULL),
       use_compile_time_class_path_(false),
       main_thread_group_(NULL),
       system_thread_group_(NULL)
@@ -128,6 +129,7 @@
   if (IsMethodTracingActive()) {
     Trace::Shutdown();
   }
+  delete instrumentation_;
 
   // Make sure to let the GC complete if it is running.
   heap_->WaitForConcurrentGcToComplete(self);
@@ -1149,15 +1151,26 @@
   callee_save_methods_[type] = method;
 }
 
-void Runtime::EnableMethodTracing(Trace* tracer) {
+void Runtime::EnableMethodTracing(Trace* trace) {
   CHECK(!IsMethodTracingActive());
-  tracer_ = tracer;
+  if (instrumentation_ == NULL) {
+    instrumentation_ = new Instrumentation();
+  }
+  instrumentation_->SetTrace(trace);
 }
 
 void Runtime::DisableMethodTracing() {
   CHECK(IsMethodTracingActive());
-  delete tracer_;
-  tracer_ = NULL;
+  instrumentation_->RemoveTrace();
+}
+
+bool Runtime::IsMethodTracingActive() const {
+  return instrumentation_ != NULL && instrumentation_->GetTrace() != NULL;
+}
+
+Instrumentation* Runtime::GetInstrumentation() const {
+  CHECK(IsMethodTracingActive());
+  return instrumentation_;
 }
 
 const std::vector<const DexFile*>& Runtime::GetCompileTimeClassPath(jobject class_loader) {
diff --git a/src/runtime.h b/src/runtime.h
index 94ab0c4..d2238ae 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -47,6 +47,7 @@
 class ClassLoader;
 class DexFile;
 class Heap;
+class Instrumentation;
 class InternTable;
 struct JavaVMExt;
 class AbstractMethod;
@@ -343,17 +344,10 @@
   void DidForkFromZygote();
   bool PreZygoteFork();
 
-  void EnableMethodTracing(Trace* tracer);
+  void EnableMethodTracing(Trace* trace);
   void DisableMethodTracing();
-
-  bool IsMethodTracingActive() const {
-    return tracer_ != NULL;
-  }
-
-  Trace* GetTracer() const {
-    CHECK(IsMethodTracingActive());
-    return tracer_;
-  }
+  bool IsMethodTracingActive() const;
+  Instrumentation* GetInstrumentation() const;
 
   bool UseCompileTimeClassPath() const {
     return use_compile_time_class_path_;
@@ -465,7 +459,7 @@
   bool method_trace_;
   std::string method_trace_file_;
   size_t method_trace_file_size_;
-  Trace* tracer_;
+  Instrumentation* instrumentation_;
 
   typedef SafeMap<jobject, std::vector<const DexFile*>, JobjectComparator> CompileTimeClassPaths;
   CompileTimeClassPaths compile_time_class_paths_;
diff --git a/src/stack.cc b/src/stack.cc
index 7ec57b4..b244975 100644
--- a/src/stack.cc
+++ b/src/stack.cc
@@ -145,8 +145,8 @@
 size_t StackVisitor::ComputeNumFrames() const {
   struct NumFramesVisitor : public StackVisitor {
     explicit NumFramesVisitor(const ManagedStack* stack,
-                              const std::vector<TraceStackFrame>* trace_stack)
-        : StackVisitor(stack, trace_stack, NULL), frames(0) {}
+                              const std::vector<InstrumentationStackFrame>* instrumentation_stack)
+        : StackVisitor(stack, instrumentation_stack, NULL), frames(0) {}
 
     virtual bool VisitFrame() {
       frames++;
@@ -156,7 +156,7 @@
     size_t frames;
   };
 
-  NumFramesVisitor visitor(stack_start_, trace_stack_);
+  NumFramesVisitor visitor(stack_start_, instrumentation_stack_);
   visitor.WalkStack(true);
   return visitor.frames;
 }
@@ -180,7 +180,7 @@
 
 void StackVisitor::WalkStack(bool include_transitions) {
   bool method_tracing_active = Runtime::Current()->IsMethodTracingActive();
-  uint32_t trace_stack_depth = 0;
+  uint32_t instrumentation_stack_depth = 0;
   for (const ManagedStack* current_fragment = stack_start_; current_fragment != NULL;
        current_fragment = current_fragment->GetLink()) {
     cur_shadow_frame_ = current_fragment->GetTopShadowFrame();
@@ -208,13 +208,13 @@
           // While profiling, the return pc is restored from the side stack, except when walking
           // the stack for an exception where the side stack will be unwound in VisitFrame.
           // TODO: stop using include_transitions as a proxy for is this the catch block visitor.
-          if (IsTraceExitPc(return_pc) && !include_transitions) {
+          if (IsInstrumentationExitPc(return_pc) && !include_transitions) {
             // TODO: unify trace and managed stack.
-            TraceStackFrame trace_frame = GetTraceStackFrame(trace_stack_depth);
-            trace_stack_depth++;
-            CHECK(trace_frame.method_ == GetMethod()) << "Excepted: " << PrettyMethod(method)
+            InstrumentationStackFrame instrumentation_frame = GetInstrumentationStackFrame(instrumentation_stack_depth);
+            instrumentation_stack_depth++;
+            CHECK(instrumentation_frame.method_ == GetMethod()) << "Excepted: " << PrettyMethod(method)
                 << " Found: " << PrettyMethod(GetMethod());
-            return_pc = trace_frame.return_pc_;
+            return_pc = instrumentation_frame.return_pc_;
           }
         }
         cur_quick_frame_pc_ = return_pc;
diff --git a/src/stack.h b/src/stack.h
index 3cf8577..fd2fd15 100644
--- a/src/stack.h
+++ b/src/stack.h
@@ -19,10 +19,10 @@
 
 #include "dex_file.h"
 #include "heap.h"
+#include "instrumentation.h"
 #include "jni.h"
 #include "macros.h"
 #include "oat/runtime/context.h"
-#include "trace.h"
 
 #include <stdint.h>
 
@@ -303,10 +303,10 @@
 
 class StackVisitor {
  protected:
-  StackVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
+  StackVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack,
                Context* context)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : stack_start_(stack), trace_stack_(trace_stack), cur_shadow_frame_(NULL),
+      : stack_start_(stack), instrumentation_stack_(instrumentation_stack), cur_shadow_frame_(NULL),
         cur_quick_frame_(NULL), cur_quick_frame_pc_(0), num_frames_(0), cur_depth_(0),
         context_(context) {}
 
@@ -463,14 +463,14 @@
  private:
   size_t ComputeNumFrames() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  TraceStackFrame GetTraceStackFrame(uint32_t depth) const {
-    return trace_stack_->at(trace_stack_->size() - depth - 1);
+  InstrumentationStackFrame GetInstrumentationStackFrame(uint32_t depth) const {
+    return instrumentation_stack_->at(instrumentation_stack_->size() - depth - 1);
   }
 
   void SanityCheckFrame() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   const ManagedStack* const stack_start_;
-  const std::vector<TraceStackFrame>* const trace_stack_;
+  const std::vector<InstrumentationStackFrame>* const instrumentation_stack_;
   ShadowFrame* cur_shadow_frame_;
   AbstractMethod** cur_quick_frame_;
   uintptr_t cur_quick_frame_pc_;
diff --git a/src/thread.cc b/src/thread.cc
index 00aaabd..0d06e42 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -808,7 +808,7 @@
 struct StackDumpVisitor : public StackVisitor {
   StackDumpVisitor(std::ostream& os, const Thread* thread, Context* context, bool can_allocate)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(thread->GetManagedStack(), thread->GetTraceStack(), context),
+      : StackVisitor(thread->GetManagedStack(), thread->GetInstrumentationStack(), context),
         os(os), thread(thread), can_allocate(can_allocate),
         last_method(NULL), last_line_number(0), repetition_count(0), frame_count(0) {
   }
@@ -953,7 +953,7 @@
       throwing_OutOfMemoryError_(false),
       debug_suspend_count_(0),
       debug_invoke_req_(new DebugInvokeReq),
-      trace_stack_(new std::vector<TraceStackFrame>),
+      instrumentation_stack_(new std::vector<InstrumentationStackFrame>),
       name_(new std::string(kThreadNameDuringStartup)),
       daemon_(daemon),
       pthread_self_(0),
@@ -1055,7 +1055,7 @@
 #endif
 
   delete debug_invoke_req_;
-  delete trace_stack_;
+  delete instrumentation_stack_;
   delete name_;
 
   TearDownAlternateSignalStack();
@@ -1229,9 +1229,9 @@
 class CountStackDepthVisitor : public StackVisitor {
  public:
   CountStackDepthVisitor(const ManagedStack* stack,
-                         const std::vector<TraceStackFrame>* trace_stack)
+                         const std::vector<InstrumentationStackFrame>* instrumentation_stack)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(stack, trace_stack, NULL),
+      : StackVisitor(stack, instrumentation_stack, NULL),
         depth_(0), skip_depth_(0), skipping_(true) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -1270,9 +1270,9 @@
 class BuildInternalStackTraceVisitor : public StackVisitor {
  public:
   explicit BuildInternalStackTraceVisitor(Thread* self, const ManagedStack* stack,
-                                          const std::vector<TraceStackFrame>* trace_stack,
+                                          const std::vector<InstrumentationStackFrame>* instrumentation_stack,
                                           int skip_depth)
-      : StackVisitor(stack, trace_stack, NULL), self_(self),
+      : StackVisitor(stack, instrumentation_stack, NULL), self_(self),
         skip_depth_(skip_depth), count_(0), dex_pc_trace_(NULL), method_trace_(NULL) {}
 
   bool Init(int depth)
@@ -1343,13 +1343,13 @@
 
 jobject Thread::CreateInternalStackTrace(const ScopedObjectAccessUnchecked& soa) const {
   // Compute depth of stack
-  CountStackDepthVisitor count_visitor(GetManagedStack(), GetTraceStack());
+  CountStackDepthVisitor count_visitor(GetManagedStack(), GetInstrumentationStack());
   count_visitor.WalkStack();
   int32_t depth = count_visitor.GetDepth();
   int32_t skip_depth = count_visitor.GetSkipDepth();
 
   // Build internal stack trace.
-  BuildInternalStackTraceVisitor build_trace_visitor(soa.Self(), GetManagedStack(), GetTraceStack(),
+  BuildInternalStackTraceVisitor build_trace_visitor(soa.Self(), GetManagedStack(), GetInstrumentationStack(),
                                                      skip_depth);
   if (!build_trace_visitor.Init(depth)) {
     return NULL;  // Allocation failed.
@@ -1667,7 +1667,7 @@
  public:
   CatchBlockStackVisitor(Thread* self, Throwable* exception)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(self->GetManagedStack(), self->GetTraceStack(), self->GetLongJumpContext()),
+      : StackVisitor(self->GetManagedStack(), self->GetInstrumentationStack(), self->GetLongJumpContext()),
         self_(self), exception_(exception), to_find_(exception->GetClass()), throw_method_(NULL),
         throw_frame_id_(0), throw_dex_pc_(0), handler_quick_frame_(NULL),
         handler_quick_frame_pc_(0), handler_dex_pc_(0), native_method_count_(0),
@@ -1702,9 +1702,9 @@
       if (method->IsNative()) {
         native_method_count_++;
       } else {
-        // Unwind stack when an exception occurs during method tracing
-        if (UNLIKELY(method_tracing_active_ && IsTraceExitPc(GetCurrentQuickFramePc()))) {
-          uintptr_t pc = TraceMethodUnwindFromCode(Thread::Current());
+        // Unwind stack when an exception occurs during instrumentation
+        if (UNLIKELY(method_tracing_active_ && IsInstrumentationExitPc(GetCurrentQuickFramePc()))) {
+          uintptr_t pc = InstrumentationMethodUnwindFromCode(Thread::Current());
           dex_pc = method->ToDexPc(pc);
         } else {
           dex_pc = GetDexPc();
@@ -1800,9 +1800,9 @@
 AbstractMethod* Thread::GetCurrentMethod(uint32_t* dex_pc, size_t* frame_id) const {
   struct CurrentMethodVisitor : public StackVisitor {
     CurrentMethodVisitor(const ManagedStack* stack,
-                         const std::vector<TraceStackFrame>* trace_stack)
+                         const std::vector<InstrumentationStackFrame>* instrumentation_stack)
         SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-        : StackVisitor(stack, trace_stack, NULL), method_(NULL), dex_pc_(0), frame_id_(0) {}
+        : StackVisitor(stack, instrumentation_stack, NULL), method_(NULL), dex_pc_(0), frame_id_(0) {}
 
     virtual bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
       AbstractMethod* m = GetMethod();
@@ -1820,7 +1820,7 @@
     size_t frame_id_;
   };
 
-  CurrentMethodVisitor visitor(GetManagedStack(), GetTraceStack());
+  CurrentMethodVisitor visitor(GetManagedStack(), GetInstrumentationStack());
   visitor.WalkStack(false);
   if (dex_pc != NULL) {
     *dex_pc = visitor.dex_pc_;
@@ -1842,10 +1842,10 @@
 template <typename Visitor>
 class ReferenceMapVisitor : public StackVisitor {
  public:
-  ReferenceMapVisitor(const ManagedStack* stack, const std::vector<TraceStackFrame>* trace_stack,
+  ReferenceMapVisitor(const ManagedStack* stack, const std::vector<InstrumentationStackFrame>* instrumentation_stack,
                       Context* context, const Visitor& visitor)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
-      : StackVisitor(stack, trace_stack, context), visitor_(visitor) {}
+      : StackVisitor(stack, instrumentation_stack, context), visitor_(visitor) {}
 
   bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
     if (false) {
@@ -2006,7 +2006,7 @@
   // Visit roots on this thread's stack
   Context* context = GetLongJumpContext();
   VerifyCallbackVisitor visitorToCallback(visitor, arg);
-  ReferenceMapVisitor<VerifyCallbackVisitor> mapper(GetManagedStack(), GetTraceStack(), context,
+  ReferenceMapVisitor<VerifyCallbackVisitor> mapper(GetManagedStack(), GetInstrumentationStack(), context,
                                                   visitorToCallback);
   mapper.WalkStack();
   ReleaseLongJumpContext(context);
@@ -2027,7 +2027,7 @@
   // Visit roots on this thread's stack
   Context* context = GetLongJumpContext();
   RootCallbackVisitor visitorToCallback(visitor, arg);
-  ReferenceMapVisitor<RootCallbackVisitor> mapper(GetManagedStack(), GetTraceStack(), context,
+  ReferenceMapVisitor<RootCallbackVisitor> mapper(GetManagedStack(), GetInstrumentationStack(), context,
                                                   visitorToCallback);
   mapper.WalkStack();
   ReleaseLongJumpContext(context);
@@ -2042,7 +2042,7 @@
 void Thread::VerifyStack() {
   UniquePtr<Context> context(Context::Create());
   RootCallbackVisitor visitorToCallback(VerifyObject, Runtime::Current()->GetHeap());
-  ReferenceMapVisitor<RootCallbackVisitor> mapper(GetManagedStack(), GetTraceStack(), context.get(),
+  ReferenceMapVisitor<RootCallbackVisitor> mapper(GetManagedStack(), GetInstrumentationStack(), context.get(),
                                                   visitorToCallback);
   mapper.WalkStack();
 }
diff --git a/src/thread.h b/src/thread.h
index 84b88f2..3eabe08 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -27,6 +27,7 @@
 
 #include "closure.h"
 #include "globals.h"
+#include "instrumentation.h"
 #include "macros.h"
 #include "oat/runtime/oat_support_entrypoints.h"
 #include "locks.h"
@@ -34,7 +35,6 @@
 #include "runtime_stats.h"
 #include "stack.h"
 #include "stack_indirect_reference_table.h"
-#include "trace.h"
 #include "UniquePtr.h"
 
 namespace art {
@@ -548,21 +548,21 @@
 
   void SetDebuggerUpdatesEnabled(bool enabled);
 
-  const std::vector<TraceStackFrame>* GetTraceStack() const {
-    return trace_stack_;
+  const std::vector<InstrumentationStackFrame>* GetInstrumentationStack() const {
+    return instrumentation_stack_;
   }
 
-  bool IsTraceStackEmpty() const {
-    return trace_stack_->empty();
+  bool IsInstrumentationStackEmpty() const {
+    return instrumentation_stack_->empty();
   }
 
-  void PushTraceStackFrame(const TraceStackFrame& frame) {
-    trace_stack_->push_back(frame);
+  void PushInstrumentationStackFrame(const InstrumentationStackFrame& frame) {
+    instrumentation_stack_->push_back(frame);
   }
 
-  TraceStackFrame PopTraceStackFrame() {
-    TraceStackFrame frame = trace_stack_->back();
-    trace_stack_->pop_back();
+  InstrumentationStackFrame PopInstrumentationStackFrame() {
+    InstrumentationStackFrame frame = instrumentation_stack_->back();
+    instrumentation_stack_->pop_back();
     return frame;
   }
 
@@ -746,9 +746,9 @@
   // JDWP invoke-during-breakpoint support.
   DebugInvokeReq* debug_invoke_req_;
 
-  // Additional stack used by method tracer to store method and return pc values.
+  // Additional stack used by method instrumentation to store method and return pc values.
   // Stored as a pointer since std::vector is not PACKED.
-  std::vector<TraceStackFrame>* trace_stack_;
+  std::vector<InstrumentationStackFrame>* instrumentation_stack_;
 
   // A cached copy of the java.lang.Thread's name.
   std::string* name_;
diff --git a/src/thread_list.cc b/src/thread_list.cc
index 84d0054..2a5b6c9 100644
--- a/src/thread_list.cc
+++ b/src/thread_list.cc
@@ -121,7 +121,7 @@
   MutexLock mu2(self, *Locks::thread_suspend_count_lock_);
   for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
     Thread* thread = *it;
-    if (thread != ignore1 || thread == ignore2) {
+    if (thread != ignore1 && thread != ignore2) {
       CHECK(thread->IsSuspended())
             << "\nUnsuspended thread: <<" << *thread << "\n"
             << "self: <<" << *Thread::Current();
diff --git a/src/trace.cc b/src/trace.cc
index 753b80f..f04b1db 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -21,6 +21,7 @@
 #include "class_linker.h"
 #include "debugger.h"
 #include "dex_cache.h"
+#include "instrumentation.h"
 #if !defined(ART_USE_LLVM_COMPILER)
 #include "oat/runtime/oat_support_entrypoints.h"
 #endif
@@ -158,105 +159,6 @@
   *buf++ = (uint8_t) (val >> 56);
 }
 
-static bool InstallStubsClassVisitor(Class* klass, void*)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    AbstractMethod* method = klass->GetDirectMethod(i);
-    if (tracer->GetSavedCodeFromMap(method) == NULL) {
-      tracer->SaveAndUpdateCode(method);
-    }
-  }
-
-  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    AbstractMethod* method = klass->GetVirtualMethod(i);
-    if (tracer->GetSavedCodeFromMap(method) == NULL) {
-      tracer->SaveAndUpdateCode(method);
-    }
-  }
-  return true;
-}
-
-static bool UninstallStubsClassVisitor(Class* klass, void*)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    AbstractMethod* method = klass->GetDirectMethod(i);
-    if (tracer->GetSavedCodeFromMap(method) != NULL) {
-      tracer->ResetSavedCode(method);
-    }
-  }
-
-  for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
-    AbstractMethod* method = klass->GetVirtualMethod(i);
-    if (tracer->GetSavedCodeFromMap(method) != NULL) {
-      tracer->ResetSavedCode(method);
-    }
-  }
-  return true;
-}
-
-static void TraceRestoreStack(Thread* self, void*) {
-  struct RestoreStackVisitor : public StackVisitor {
-    RestoreStackVisitor(Thread* self)
-        : StackVisitor(self->GetManagedStack(), self->GetTraceStack(), NULL), self_(self) {}
-
-    virtual bool VisitFrame() {
-      if (self_->IsTraceStackEmpty()) {
-        return false;  // Stop.
-      }
-      uintptr_t pc = GetReturnPc();
-      if (IsTraceExitPc(pc)) {
-        TraceStackFrame trace_frame = self_->PopTraceStackFrame();
-        SetReturnPc(trace_frame.return_pc_);
-        CHECK(GetMethod() == trace_frame.method_);
-      }
-      return true;  // Continue.
-    }
-
-    Thread* self_;
-  };
-  ScopedObjectAccess soa(self);
-  RestoreStackVisitor visitor(self);
-  visitor.WalkStack();
-}
-
-void Trace::AddSavedCodeToMap(const AbstractMethod* method, const void* code) {
-  saved_code_map_.Put(method, code);
-}
-
-void Trace::RemoveSavedCodeFromMap(const AbstractMethod* method) {
-  saved_code_map_.erase(method);
-}
-
-const void* Trace::GetSavedCodeFromMap(const AbstractMethod* method) {
-  typedef SafeMap<const AbstractMethod*, const void*>::const_iterator It; // TODO: C++0x auto
-  It it = saved_code_map_.find(method);
-  if (it == saved_code_map_.end()) {
-    return NULL;
-  } else {
-    return it->second;
-  }
-}
-
-void Trace::SaveAndUpdateCode(AbstractMethod* method) {
-#if defined(ART_USE_LLVM_COMPILER)
-  UNUSED(method);
-  UNIMPLEMENTED(FATAL);
-#else
-  void* trace_stub = GetLogTraceEntryPoint();
-  CHECK(GetSavedCodeFromMap(method) == NULL);
-  AddSavedCodeToMap(method, method->GetCode());
-  method->SetCode(trace_stub);
-#endif
-}
-
-void Trace::ResetSavedCode(AbstractMethod* method) {
-  CHECK(GetSavedCodeFromMap(method) != NULL);
-  method->SetCode(GetSavedCodeFromMap(method));
-  RemoveSavedCodeFromMap(method);
-}
-
 Trace::Trace(File* trace_file, int buffer_size, int flags)
     : trace_file_(trace_file), buf_(new uint8_t[buffer_size]()), flags_(flags),
       clock_source_(gDefaultTraceClockSource), overflow_(false),
@@ -269,7 +171,6 @@
     return;
   }
 
-  ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
   Runtime::Current()->GetThreadList()->SuspendAll();
 
   // Open trace file if not going directly to ddms.
@@ -309,10 +210,9 @@
     return;
   }
 
-  ScopedThreadStateChange tsc(Thread::Current(), kRunnable);
   Runtime::Current()->GetThreadList()->SuspendAll();
 
-  Runtime::Current()->GetTracer()->FinishTracing();
+  Runtime::Current()->GetInstrumentation()->GetTrace()->FinishTracing();
   Runtime::Current()->DisableMethodTracing();
 
   Runtime::Current()->GetThreadList()->ResumeAll();
@@ -323,7 +223,7 @@
     LOG(INFO) << "Trace shutdown requested, but no trace currently running";
     return;
   }
-  Runtime::Current()->GetTracer()->FinishTracing();
+  Runtime::Current()->GetInstrumentation()->GetTrace()->FinishTracing();
   Runtime::Current()->DisableMethodTracing();
 }
 
@@ -354,12 +254,12 @@
   cur_offset_ = kTraceHeaderLength;
 
   // Install all method tracing stubs.
-  InstallStubs();
+  Runtime::Current()->GetInstrumentation()->InstallStubs();
 }
 
 void Trace::FinishTracing() {
   // Uninstall all method tracing stubs.
-  UninstallStubs();
+  Runtime::Current()->GetInstrumentation()->UninstallStubs();
 
   // Compute elapsed time.
   uint64_t elapsed = MicroTime() - start_time_;
@@ -496,27 +396,4 @@
   Runtime::Current()->GetThreadList()->ForEach(DumpThread, &os);
 }
 
-void Trace::InstallStubs() {
-  Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, NULL);
-}
-
-void Trace::UninstallStubs() {
-  Thread* self = Thread::Current();
-  Locks::thread_list_lock_->AssertNotHeld(self);
-  Runtime::Current()->GetClassLinker()->VisitClasses(UninstallStubsClassVisitor, NULL);
-  MutexLock mu(self, *Locks::thread_list_lock_);
-  Runtime::Current()->GetThreadList()->ForEach(TraceRestoreStack, NULL);
-}
-
-uint32_t TraceMethodUnwindFromCode(Thread* self) {
-  Trace* tracer = Runtime::Current()->GetTracer();
-  TraceStackFrame trace_frame = self->PopTraceStackFrame();
-  AbstractMethod* method = trace_frame.method_;
-  uint32_t lr = trace_frame.return_pc_;
-
-  tracer->LogMethodTraceEvent(self, method, Trace::kMethodTraceUnwind);
-
-  return lr;
-}
-
 }  // namespace art
diff --git a/src/trace.h b/src/trace.h
index 43b0ff7..5dd29b9 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -32,17 +32,6 @@
 class AbstractMethod;
 class Thread;
 
-uint32_t TraceMethodUnwindFromCode(Thread* self);
-
-struct TraceStackFrame {
-  TraceStackFrame(AbstractMethod* method, uintptr_t return_pc)
-      : method_(method), return_pc_(return_pc) {
-  }
-
-  AbstractMethod* method_;
-  uintptr_t return_pc_;
-};
-
 enum ProfilerClockSource {
   kProfilerClockSourceThreadCpu,
   kProfilerClockSourceWall,
@@ -72,33 +61,17 @@
 
   void LogMethodTraceEvent(Thread* self, const AbstractMethod* method, TraceEvent event);
 
-  void AddSavedCodeToMap(const AbstractMethod* method, const void* code);
-  void RemoveSavedCodeFromMap(const AbstractMethod* method);
-  const void* GetSavedCodeFromMap(const AbstractMethod* method);
-
-  void SaveAndUpdateCode(AbstractMethod* method);
-  void ResetSavedCode(AbstractMethod* method);
-
  private:
   explicit Trace(File* trace_file, int buffer_size, int flags);
 
   void BeginTracing();
   void FinishTracing() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  // Replaces code of each method with a pointer to a stub for method tracing.
-  void InstallStubs();
-
-  // Restores original code for each method and fixes the return values of each thread's stack.
-  void UninstallStubs() LOCKS_EXCLUDED(Locks::thread_list_lock_);
-
   // Methods to output traced methods and threads.
   void GetVisitedMethods(size_t end_offset);
   void DumpMethodList(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void DumpThreadList(std::ostream& os) LOCKS_EXCLUDED(Locks::thread_list_lock_);
 
-  // Maps a method to its original code pointer.
-  SafeMap<const AbstractMethod*, const void*> saved_code_map_;
-
   // Set of methods visited by the profiler.
   std::set<const AbstractMethod*> visited_methods_;