summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-11-05 16:12:57 -0800
committerIan Rogers <irogers@google.com>2013-11-06 12:00:14 -0800
commitfa82427c68b09f4aedbee319dc71579afbfc66f5 (patch)
treeb8ae1c7be4a00dce290887ee857be5e466a0902b
parent6b98c91275d4361d1b74effad36995cc2d687a55 (diff)
downloadart-fa82427c68b09f4aedbee319dc71579afbfc66f5.zip
art-fa82427c68b09f4aedbee319dc71579afbfc66f5.tar.gz
art-fa82427c68b09f4aedbee319dc71579afbfc66f5.tar.bz2
Fix oatdump and valgrind.
Bug: 11531382 Move allocation instrumentation out of runtime into instrumentation. Don't attempt to suspend threads in unstarted runtimes. Make indentation support sputc returning eof, on which it will sync and try again. A further failure likely means the disk is full. Move the dump-oat output directory to be art as now there's too much output to fit all the dump-oat data in our standard /tmp. Change-Id: I8ea848ace318552c180e2efa46570288ff1ca62c
-rw-r--r--Android.mk18
-rw-r--r--oatdump/oatdump.cc19
-rw-r--r--runtime/debugger.cc4
-rw-r--r--runtime/gc/heap.cc2
-rw-r--r--runtime/indenter.h27
-rw-r--r--runtime/instrumentation.cc52
-rw-r--r--runtime/instrumentation.h13
-rw-r--r--runtime/runtime.cc49
-rw-r--r--runtime/runtime.h5
9 files changed, 114 insertions, 75 deletions
diff --git a/Android.mk b/Android.mk
index 0b4b231..774353f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -305,6 +305,8 @@ build-art-target: $(ART_TARGET_EXECUTABLES) $(ART_TARGET_TEST_EXECUTABLES) $(TAR
########################################################################
# oatdump targets
+ART_DUMP_OAT_PATH ?= $(OUT_DIR)
+
.PHONY: dump-oat
dump-oat: dump-oat-core dump-oat-boot
@@ -314,29 +316,29 @@ dump-oat-core: dump-oat-core-host dump-oat-core-target
.PHONY: dump-oat-core-host
ifeq ($(ART_BUILD_HOST),true)
dump-oat-core-host: $(HOST_CORE_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --image=$(HOST_CORE_IMG_OUT) --output=/tmp/core.host.oatdump.txt --host-prefix=""
- @echo Output in /tmp/core.host.oatdump.txt
+ $(OATDUMP) --image=$(HOST_CORE_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/core.host.oatdump.txt --host-prefix=""
+ @echo Output in $(ART_DUMP_OAT_PATH)/core.host.oatdump.txt
endif
.PHONY: dump-oat-core-target
ifeq ($(ART_BUILD_TARGET),true)
dump-oat-core-target: $(TARGET_CORE_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --image=$(TARGET_CORE_IMG_OUT) --output=/tmp/core.target.oatdump.txt
- @echo Output in /tmp/core.target.oatdump.txt
+ $(OATDUMP) --image=$(TARGET_CORE_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/core.target.oatdump.txt
+ @echo Output in $(ART_DUMP_OAT_PATH)/core.target.oatdump.txt
endif
.PHONY: dump-oat-boot
ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
dump-oat-boot: $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=/tmp/boot.oatdump.txt
- @echo Output in /tmp/boot.oatdump.txt
+ $(OATDUMP) --image=$(TARGET_BOOT_IMG_OUT) --output=$(ART_DUMP_OAT_PATH)/boot.oatdump.txt
+ @echo Output in $(ART_DUMP_OAT_PATH)/boot.oatdump.txt
endif
.PHONY: dump-oat-Calculator
ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.odex $(TARGET_BOOT_IMG_OUT) $(OATDUMP)
- $(OATDUMP) --oat-file=$< --output=/tmp/Calculator.oatdump.txt
- @echo Output in /tmp/Calculator.oatdump.txt
+ $(OATDUMP) --oat-file=$< --output=$(ART_DUMP_OAT_PATH)/Calculator.oatdump.txt
+ @echo Output in $(ART_DUMP_OAT_PATH)/Calculator.oatdump.txt
endif
########################################################################
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 3a32ff1..047d985 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -712,14 +712,25 @@ class ImageDumper {
if (image_root_object->IsObjectArray()) {
Indenter indent2_filter(indent1_os.rdbuf(), kIndentChar, kIndentBy1Count);
std::ostream indent2_os(&indent2_filter);
- // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
mirror::ObjectArray<mirror::Object>* image_root_object_array
- = down_cast<mirror::ObjectArray<mirror::Object>*>(image_root_object);
- // = image_root_object->AsObjectArray<Object>();
+ = image_root_object->AsObjectArray<mirror::Object>();
for (int i = 0; i < image_root_object_array->GetLength(); i++) {
mirror::Object* value = image_root_object_array->Get(i);
+ size_t run = 0;
+ for (int32_t j = i + 1; j < image_root_object_array->GetLength(); j++) {
+ if (value == image_root_object_array->Get(j)) {
+ run++;
+ } else {
+ break;
+ }
+ }
+ if (run == 0) {
+ indent2_os << StringPrintf("%d: ", i);
+ } else {
+ indent2_os << StringPrintf("%d to %zd: ", i, i + run);
+ i = i + run;
+ }
if (value != NULL) {
- indent2_os << i << ": ";
PrettyObjectValue(indent2_os, value->GetClass(), value);
} else {
indent2_os << i << ": null\n";
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index bdcf6ac..0eecd28 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -3489,9 +3489,9 @@ void Dbg::SetAllocTrackingEnabled(bool enabled) {
recent_allocation_records_ = new AllocRecord[gAllocRecordMax];
CHECK(recent_allocation_records_ != NULL);
}
- Runtime::Current()->InstrumentQuickAllocEntryPoints();
+ Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints();
} else {
- Runtime::Current()->UninstrumentQuickAllocEntryPoints();
+ Runtime::Current()->GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
delete[] recent_allocation_records_;
recent_allocation_records_ = NULL;
}
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 804c669..de3ab0e 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -237,7 +237,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max
CHECK_NE(max_allowed_footprint_, 0U);
if (running_on_valgrind_) {
- Runtime::Current()->InstrumentQuickAllocEntryPoints();
+ Runtime::Current()->GetInstrumentation()->InstrumentQuickAllocEntryPoints();
}
if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
diff --git a/runtime/indenter.h b/runtime/indenter.h
index c432e1b..d055d4e 100644
--- a/runtime/indenter.h
+++ b/runtime/indenter.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_INDENTER_H_
#define ART_RUNTIME_INDENTER_H_
+#include "base/logging.h"
#include "base/macros.h"
#include <streambuf>
@@ -30,16 +31,28 @@ class Indenter : public std::streambuf {
private:
int_type overflow(int_type c) {
- if (c != std::char_traits<char>::eof()) {
- if (indent_next_) {
- for (size_t i = 0; i < count_; ++i) {
- out_sbuf_->sputc(text_);
+ if (UNLIKELY(c == std::char_traits<char>::eof())) {
+ out_sbuf_->pubsync();
+ return c;
+ }
+ if (indent_next_) {
+ for (size_t i = 0; i < count_; ++i) {
+ int_type r = out_sbuf_->sputc(text_);
+ if (UNLIKELY(r != text_)) {
+ out_sbuf_->pubsync();
+ r = out_sbuf_->sputc(text_);
+ CHECK_EQ(r, text_) << "Error writing to buffer. Disk full?";
}
}
- out_sbuf_->sputc(c);
- indent_next_ = (c == '\n');
}
- return std::char_traits<char>::not_eof(c);
+ indent_next_ = (c == '\n');
+ int_type r = out_sbuf_->sputc(c);
+ if (UNLIKELY(r != c)) {
+ out_sbuf_->pubsync();
+ r = out_sbuf_->sputc(c);
+ CHECK_EQ(r, c) << "Error writing to buffer. Disk full?";
+ }
+ return r;
}
int sync() {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 8316bc5..4070324 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -39,6 +39,9 @@
#include "thread_list.h"
namespace art {
+
+extern void SetQuickAllocEntryPointsInstrumented(bool instrumented);
+
namespace instrumentation {
// Do we want to deoptimize for method entry and exit listeners or just try to intercept
@@ -391,6 +394,55 @@ void Instrumentation::ConfigureStubs(bool require_entry_exit_stubs, bool require
}
}
+static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg) {
+ thread->ResetQuickAllocEntryPointsForThread();
+}
+
+void Instrumentation::InstrumentQuickAllocEntryPoints() {
+ // TODO: the read of quick_alloc_entry_points_instrumentation_counter_ is racey and this code
+ // should be guarded by a lock.
+ DCHECK_GE(quick_alloc_entry_points_instrumentation_counter_, 0U);
+ bool enable_instrumentation = (quick_alloc_entry_points_instrumentation_counter_ == 0);
+ quick_alloc_entry_points_instrumentation_counter_++;
+ if (enable_instrumentation) {
+ // Instrumentation wasn't enabled so enable it.
+ SetQuickAllocEntryPointsInstrumented(true);
+ Runtime* runtime = Runtime::Current();
+ if (runtime->IsStarted()) {
+ ThreadList* tl = runtime->GetThreadList();
+ Thread* self = Thread::Current();
+ tl->SuspendAll();
+ {
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
+ }
+ tl->ResumeAll();
+ }
+ }
+}
+
+void Instrumentation::UninstrumentQuickAllocEntryPoints() {
+ // TODO: the read of quick_alloc_entry_points_instrumentation_counter_ is racey and this code
+ // should be guarded by a lock.
+ DCHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0U);
+ quick_alloc_entry_points_instrumentation_counter_--;
+ bool disable_instrumentation = (quick_alloc_entry_points_instrumentation_counter_ == 0);
+ if (disable_instrumentation) {
+ SetQuickAllocEntryPointsInstrumented(false);
+ Runtime* runtime = Runtime::Current();
+ if (runtime->IsStarted()) {
+ ThreadList* tl = Runtime::Current()->GetThreadList();
+ Thread* self = Thread::Current();
+ tl->SuspendAll();
+ {
+ MutexLock mu(self, *Locks::thread_list_lock_);
+ tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
+ }
+ tl->ResumeAll();
+ }
+ }
+}
+
void Instrumentation::UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const {
if (LIKELY(!instrumentation_stubs_installed_)) {
method->SetEntryPointFromCompiledCode(code);
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 7a0aaf7..25a4eec 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -104,7 +104,8 @@ class Instrumentation {
have_method_entry_listeners_(false), have_method_exit_listeners_(false),
have_method_unwind_listeners_(false), have_dex_pc_listeners_(false),
have_exception_caught_listeners_(false),
- interpreter_handler_table_(kMainHandlerTable) {}
+ interpreter_handler_table_(kMainHandlerTable),
+ quick_alloc_entry_points_instrumentation_counter_(0) {}
// Add a listener to be notified of the masked together sent of instrumentation events. This
// suspend the runtime to install stubs. You are expected to hold the mutator lock as a proxy
@@ -123,6 +124,9 @@ class Instrumentation {
return interpreter_handler_table_;
}
+ void InstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
+ void UninstrumentQuickAllocEntryPoints() LOCKS_EXCLUDED(Locks::thread_list_lock_);
+
// Update the code of a method respecting any installed stubs.
void UpdateMethodsCode(mirror::ArtMethod* method, const void* code) const;
@@ -289,9 +293,14 @@ class Instrumentation {
std::list<InstrumentationListener*> dex_pc_listeners_ GUARDED_BY(Locks::mutator_lock_);
std::list<InstrumentationListener*> exception_caught_listeners_ GUARDED_BY(Locks::mutator_lock_);
- // Current interpreter handler table. This is updated each time the thread state flags are modified.
+ // Current interpreter handler table. This is updated each time the thread state flags are
+ // modified.
InterpreterHandlerTable interpreter_handler_table_;
+ // Greater than 0 if quick alloc entry points instrumented.
+ // TODO: The access and changes to this is racy and should be guarded by a lock.
+ size_t quick_alloc_entry_points_instrumentation_counter_;
+
DISALLOW_COPY_AND_ASSIGN(Instrumentation);
};
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 34cf45b..53c9b2e 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -102,8 +102,7 @@ Runtime::Runtime()
use_compile_time_class_path_(false),
main_thread_group_(NULL),
system_thread_group_(NULL),
- system_class_loader_(NULL),
- quick_alloc_entry_points_instrumentation_counter_(0) {
+ system_class_loader_(NULL) {
for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
callee_save_methods_[i] = NULL;
}
@@ -1077,9 +1076,9 @@ void Runtime::SetStatsEnabled(bool new_state) {
GetStats()->Clear(~0);
// TODO: wouldn't it make more sense to clear _all_ threads' stats?
Thread::Current()->GetStats()->Clear(~0);
- InstrumentQuickAllocEntryPoints();
+ GetInstrumentation()->InstrumentQuickAllocEntryPoints();
} else {
- UninstrumentQuickAllocEntryPoints();
+ GetInstrumentation()->UninstrumentQuickAllocEntryPoints();
}
stats_enabled_ = new_state;
}
@@ -1336,46 +1335,4 @@ void Runtime::SetCompileTimeClassPath(jobject class_loader, std::vector<const De
compile_time_class_paths_.Put(class_loader, class_path);
}
-static void ResetQuickAllocEntryPointsForThread(Thread* thread, void* arg) {
- thread->ResetQuickAllocEntryPointsForThread();
-}
-
-void SetQuickAllocEntryPointsInstrumented(bool instrumented);
-
-void Runtime::InstrumentQuickAllocEntryPoints() {
- ThreadList* tl = thread_list_;
- Thread* self = Thread::Current();
- tl->SuspendAll();
- {
- MutexLock mu(self, *Locks::runtime_shutdown_lock_);
- MutexLock mu2(self, *Locks::thread_list_lock_);
- DCHECK_GE(quick_alloc_entry_points_instrumentation_counter_, 0);
- int old_counter = quick_alloc_entry_points_instrumentation_counter_++;
- if (old_counter == 0) {
- // If it was disabled, enable it.
- SetQuickAllocEntryPointsInstrumented(true);
- tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
- }
- }
- tl->ResumeAll();
-}
-
-void Runtime::UninstrumentQuickAllocEntryPoints() {
- ThreadList* tl = thread_list_;
- Thread* self = Thread::Current();
- tl->SuspendAll();
- {
- MutexLock mu(self, *Locks::runtime_shutdown_lock_);
- MutexLock mu2(self, *Locks::thread_list_lock_);
- DCHECK_GT(quick_alloc_entry_points_instrumentation_counter_, 0);
- int new_counter = --quick_alloc_entry_points_instrumentation_counter_;
- if (new_counter == 0) {
- // Disable it if the counter becomes zero.
- SetQuickAllocEntryPointsInstrumented(false);
- tl->ForEach(ResetQuickAllocEntryPointsForThread, NULL);
- }
- }
- tl->ResumeAll();
-}
-
} // namespace art
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 0ce2642..24b4c87 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -442,9 +442,6 @@ class Runtime {
const std::vector<const DexFile*>& GetCompileTimeClassPath(jobject class_loader);
void SetCompileTimeClassPath(jobject class_loader, std::vector<const DexFile*>& class_path);
- void InstrumentQuickAllocEntryPoints();
- void UninstrumentQuickAllocEntryPoints();
-
private:
static void InitPlatformSignalHandlers();
@@ -567,8 +564,6 @@ class Runtime {
// As returned by ClassLoader.getSystemClassLoader().
jobject system_class_loader_;
- int quick_alloc_entry_points_instrumentation_counter_;
-
DISALLOW_COPY_AND_ASSIGN(Runtime);
};