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/build/Android.common.mk b/build/Android.common.mk
index 193afbf..d200874 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -162,6 +162,7 @@
src/image.cc \
src/image_writer.cc \
src/indirect_reference_table.cc \
+ src/instrumentation.cc \
src/intern_table.cc \
src/interpreter/interpreter.cc \
src/jdwp/jdwp_event.cc \
@@ -253,6 +254,7 @@
src/oat/runtime/support_dexcache.cc \
src/oat/runtime/support_field.cc \
src/oat/runtime/support_fillarray.cc \
+ src/oat/runtime/support_instrumentation.cc \
src/oat/runtime/support_invoke.cc \
src/oat/runtime/support_jni.cc \
src/oat/runtime/support_locks.cc \
@@ -260,8 +262,7 @@
src/oat/runtime/support_proxy.cc \
src/oat/runtime/support_stubs.cc \
src/oat/runtime/support_thread.cc \
- src/oat/runtime/support_throw.cc \
- src/oat/runtime/support_trace.cc
+ src/oat/runtime/support_throw.cc
LIBART_TARGET_SRC_FILES := \
$(LIBART_COMMON_SRC_FILES) \
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_;
diff --git a/test/ReferenceMap/stack_walk_refmap_jni.cc b/test/ReferenceMap/stack_walk_refmap_jni.cc
index a9dfbac..31bd57f 100644
--- a/test/ReferenceMap/stack_walk_refmap_jni.cc
+++ b/test/ReferenceMap/stack_walk_refmap_jni.cc
@@ -43,9 +43,9 @@
struct ReferenceMap2Visitor : public StackVisitor {
explicit ReferenceMap2Visitor(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) {
}
bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -281,7 +281,7 @@
// Visitor
ScopedObjectAccess ts(Thread::Current());
ReferenceMap2Visitor mapper(Thread::Current()->GetManagedStack(),
- Thread::Current()->GetTraceStack());
+ Thread::Current()->GetInstrumentationStack());
mapper.WalkStack();
return count + 1;
diff --git a/test/StackWalk/stack_walk_jni.cc b/test/StackWalk/stack_walk_jni.cc
index 2de117a..effc503 100644
--- a/test/StackWalk/stack_walk_jni.cc
+++ b/test/StackWalk/stack_walk_jni.cc
@@ -41,9 +41,9 @@
struct TestReferenceMapVisitor : public StackVisitor {
explicit TestReferenceMapVisitor(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) {
}
bool VisitFrame() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -108,7 +108,7 @@
// Visitor
TestReferenceMapVisitor mapper(Thread::Current()->GetManagedStack(),
- Thread::Current()->GetTraceStack());
+ Thread::Current()->GetInstrumentationStack());
mapper.WalkStack();
return count + 1;
@@ -120,7 +120,7 @@
// Visitor
TestReferenceMapVisitor mapper(Thread::Current()->GetManagedStack(),
- Thread::Current()->GetTraceStack());
+ Thread::Current()->GetInstrumentationStack());
mapper.WalkStack();
return count + 1;