diff options
| author | 2013-11-05 16:12:57 -0800 | |
|---|---|---|
| committer | 2013-11-06 12:00:14 -0800 | |
| commit | fa82427c68b09f4aedbee319dc71579afbfc66f5 (patch) | |
| tree | b8ae1c7be4a00dce290887ee857be5e466a0902b | |
| parent | 6b98c91275d4361d1b74effad36995cc2d687a55 (diff) | |
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
diff --git a/Android.mk b/Android.mk index 0b4b2316fd..774353f419 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 3a32ff14bd..047d985796 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 bdcf6ac6ab..0eecd28831 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 804c66932e..de3ab0eb9d 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 c432e1ba8d..d055d4e3f4 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 8316bc56b3..4070324faf 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 7a0aaf7858..25a4eec976 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 34cf45b4c7..53c9b2efbb 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 0ce2642c98..24b4c87666 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); }; |