diff options
author | Ian Rogers <irogers@google.com> | 2013-11-05 16:12:57 -0800 |
---|---|---|
committer | Ian Rogers <irogers@google.com> | 2013-11-06 12:00:14 -0800 |
commit | fa82427c68b09f4aedbee319dc71579afbfc66f5 (patch) | |
tree | b8ae1c7be4a00dce290887ee857be5e466a0902b | |
parent | 6b98c91275d4361d1b74effad36995cc2d687a55 (diff) | |
download | art-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.mk | 18 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 19 | ||||
-rw-r--r-- | runtime/debugger.cc | 4 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 2 | ||||
-rw-r--r-- | runtime/indenter.h | 27 | ||||
-rw-r--r-- | runtime/instrumentation.cc | 52 | ||||
-rw-r--r-- | runtime/instrumentation.h | 13 | ||||
-rw-r--r-- | runtime/runtime.cc | 49 | ||||
-rw-r--r-- | runtime/runtime.h | 5 |
9 files changed, 114 insertions, 75 deletions
@@ -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); }; |