Added code to allow method tracing from command line.
Crated a set of command line switches to allow method tracing to be
enabled from the command line. They are -Xmethod-trace,
-Xmethod-trace-file, and -Xmethod-trace-file-size.
Change-Id: I7ecaa07aba3d7ca41f2ff3a9a9341d97833afe36
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 06ae301..6ab849a 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1397,7 +1397,15 @@
const void* trampoline = Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod)->GetData();
for (size_t i = 0; it.HasNextDirectMethod(); i++, it.Next()) {
Method* method = klass->GetDirectMethod(i);
- if (method->GetCode() == trampoline) {
+ if (Runtime::Current()->IsMethodTracingActive()) {
+ Trace* tracer = Runtime::Current()->GetTracer();
+ if (tracer->GetSavedCodeFromMap(method) == trampoline) {
+ const void* code = oat_class->GetOatMethod(method_index).GetCode();
+ tracer->ResetSavedCode(method);
+ method->SetCode(code);
+ tracer->SaveAndUpdateCode(method);
+ }
+ } else if (method->GetCode() == trampoline) {
const void* code = oat_class->GetOatMethod(method_index).GetCode();
CHECK(code != NULL);
method->SetCode(code);
@@ -1428,13 +1436,8 @@
}
if (Runtime::Current()->IsMethodTracingActive()) {
-#if defined(__arm__)
Trace* tracer = Runtime::Current()->GetTracer();
- void* trace_stub = reinterpret_cast<void*>(art_trace_entry_from_code);
- tracer->SaveAndUpdateCode(method.get(), trace_stub);
-#else
- UNIMPLEMENTED(WARNING);
-#endif
+ tracer->SaveAndUpdateCode(method.get());
}
}
diff --git a/src/runtime.cc b/src/runtime.cc
index c53ede1..96c4451 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -38,6 +38,7 @@
#include "space.h"
#include "thread.h"
#include "thread_list.h"
+#include "trace.h"
#include "UniquePtr.h"
// TODO: this drags in cutil/log.h, which conflicts with our logging.h.
@@ -81,6 +82,10 @@
Runtime::~Runtime() {
shutting_down_ = true;
+ if (IsMethodTracingActive()) {
+ Trace::Shutdown();
+ }
+
Dbg::StopJdwp();
// Make sure our internal threads are dead before we start tearing down things they're using.
@@ -310,6 +315,10 @@
// gLogVerbosity.third_party_jni = true; // TODO: don't check this in!
// gLogVerbosity.threads = true; // TODO: don't check this in!
+ parsed->method_trace_ = false;
+ parsed->method_trace_file_ = "/data/method-trace-file.bin";
+ parsed->method_trace_file_size_ = 10 * MB;
+
for (size_t i = 0; i < options.size(); ++i) {
const std::string option(options[i].first);
if (true && options[0].first == "-Xzygote") {
@@ -442,6 +451,12 @@
parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second);
} else if (option == "-Xgenregmap" || option == "-Xgc:precise") {
// We silently ignore these for backwards compatibility.
+ } else if (option == "-Xmethod-trace") {
+ parsed->method_trace_ = true;
+ } else if (StartsWith(option, "-Xmethod-trace-file:")) {
+ parsed->method_trace_file_ = option.substr(strlen("-Xmethod-trace-file:"));
+ } else if (StartsWith(option, "-Xmethod-trace-file-size:")) {
+ parsed->method_trace_file_size_ = ParseIntegerOrDie(option);
} else {
if (!ignore_unrecognized) {
// TODO: print usage via vfprintf
@@ -651,6 +666,14 @@
}
CHECK(class_linker_ != NULL);
+ method_trace_ = options->method_trace_;
+ method_trace_file_ = options->method_trace_file_;
+ method_trace_file_size_ = options->method_trace_file_size_;
+
+ if (options->method_trace_) {
+ Trace::Start(options->method_trace_file_.c_str(), -1, options->method_trace_file_size_, 0, false);
+ }
+
VLOG(startup) << "Runtime::Init exiting";
return true;
}
diff --git a/src/runtime.h b/src/runtime.h
index a2ec08e..4bbe54e 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -77,6 +77,9 @@
size_t jni_globals_max_;
size_t lock_profiling_threshold_;
std::string stack_trace_file_;
+ bool method_trace_;
+ std::string method_trace_file_;
+ size_t method_trace_file_size_;
bool (*hook_is_sensitive_thread_)();
jint (*hook_vfprintf_)(FILE* stream, const char* format, va_list ap);
void (*hook_exit_)(jint status);
@@ -321,6 +324,9 @@
bool stats_enabled_;
RuntimeStats stats_;
+ bool method_trace_;
+ std::string method_trace_file_;
+ size_t method_trace_file_size_;
Trace* tracer_;
typedef std::map<const ClassLoader*, std::vector<const DexFile*> > CompileTimeClassPaths;
diff --git a/src/trace.cc b/src/trace.cc
index b481b74..e4be356 100644
--- a/src/trace.cc
+++ b/src/trace.cc
@@ -108,26 +108,25 @@
*buf++ = (uint8_t) (val >> 56);
}
-#if defined(__arm__)
-static bool InstallStubsClassVisitor(Class* klass, void* trace_stub) {
+static bool InstallStubsClassVisitor(Class* klass, void*) {
Trace* tracer = Runtime::Current()->GetTracer();
for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
Method* method = klass->GetDirectMethod(i);
- if (method->GetCode() != trace_stub) {
- tracer->SaveAndUpdateCode(method, trace_stub);
+ if (tracer->GetSavedCodeFromMap(method) == NULL) {
+ tracer->SaveAndUpdateCode(method);
}
}
for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
Method* method = klass->GetVirtualMethod(i);
- if (method->GetCode() != trace_stub) {
- tracer->SaveAndUpdateCode(method, trace_stub);
+ if (tracer->GetSavedCodeFromMap(method) == NULL) {
+ tracer->SaveAndUpdateCode(method);
}
}
return true;
}
-static bool UninstallStubsClassVisitor(Class* klass, void* trace_stub) {
+static bool UninstallStubsClassVisitor(Class* klass, void*) {
Trace* tracer = Runtime::Current()->GetTracer();
for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
Method* method = klass->GetDirectMethod(i);
@@ -146,6 +145,7 @@
}
static void TraceRestoreStack(Thread* t, void*) {
+#if defined(__arm__)
uintptr_t trace_exit = reinterpret_cast<uintptr_t>(art_trace_exit_from_code);
Frame frame = t->GetTopOfStack();
@@ -163,8 +163,10 @@
}
}
}
-}
+#else
+ UNIMPLEMENTED(WARNING);
#endif
+}
void Trace::AddSavedCodeToMap(const Method* method, const void* code) {
saved_code_map_.insert(std::make_pair(method, code));
@@ -184,10 +186,15 @@
}
}
-void Trace::SaveAndUpdateCode(Method* method, const void* new_code) {
+void Trace::SaveAndUpdateCode(Method* method) {
+#if defined(__arm__)
+ void* trace_stub = reinterpret_cast<void*>(art_trace_entry_from_code);
CHECK(GetSavedCodeFromMap(method) == NULL);
AddSavedCodeToMap(method, method->GetCode());
- method->SetCode(new_code);
+ method->SetCode(trace_stub);
+#else
+ UNIMPLEMENTED(WARNING);
+#endif
}
void Trace::ResetSavedCode(Method* method) {
@@ -214,7 +221,7 @@
trace_file = OS::FileFromFd("tracefile", trace_fd);
}
if (trace_file == NULL) {
- PLOG(ERROR) << "Unable to open trace file '" << trace_filename;
+ PLOG(ERROR) << "Unable to open trace file '" << trace_filename << "'";
Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;",
StringPrintf("Unable to open trace file '%s'", trace_filename).c_str());
Runtime::Current()->GetThreadList()->ResumeAll(false);
@@ -245,6 +252,15 @@
Runtime::Current()->GetThreadList()->ResumeAll(false);
}
+void Trace::Shutdown() {
+ if (!Runtime::Current()->IsMethodTracingActive()) {
+ LOG(INFO) << "Trace shutdown requested, but no trace currently running";
+ return;
+ }
+ Runtime::Current()->GetTracer()->FinishTracing();
+ Runtime::Current()->DisableMethodTracing();
+}
+
void Trace::BeginTracing() {
// Set the start time of tracing.
start_time_ = MicroTime();
@@ -406,27 +422,17 @@
}
void Trace::InstallStubs() {
-#if defined(__arm__)
- void* trace_stub = reinterpret_cast<void*>(art_trace_entry_from_code);
- Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, trace_stub);
-#else
- UNIMPLEMENTED(WARNING);
-#endif
+ Runtime::Current()->GetClassLinker()->VisitClasses(InstallStubsClassVisitor, NULL);
}
void Trace::UninstallStubs() {
-#if defined(__arm__)
- void* trace_stub = reinterpret_cast<void*>(art_trace_entry_from_code);
- Runtime::Current()->GetClassLinker()->VisitClasses(UninstallStubsClassVisitor, trace_stub);
+ Runtime::Current()->GetClassLinker()->VisitClasses(UninstallStubsClassVisitor, NULL);
// Restore stacks of all threads
{
ScopedThreadListLock thread_list_lock;
Runtime::Current()->GetThreadList()->ForEach(TraceRestoreStack, NULL);
}
-#else
- UNIMPLEMENTED(WARNING);
-#endif
}
} // namespace art
diff --git a/src/trace.h b/src/trace.h
index c84e99e..d545b14 100644
--- a/src/trace.h
+++ b/src/trace.h
@@ -52,6 +52,7 @@
static void Start(const char* trace_filename, int trace_fd, int buffer_size, int flags, bool direct_to_ddms);
static void Stop();
+ static void Shutdown();
void LogMethodTraceEvent(Thread* self, const Method* method, TraceEvent event);
@@ -59,7 +60,7 @@
void RemoveSavedCodeFromMap(const Method* method);
const void* GetSavedCodeFromMap(const Method* method);
- void SaveAndUpdateCode(Method* method, const void* new_code);
+ void SaveAndUpdateCode(Method* method);
void ResetSavedCode(Method* method);
private: