summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 3112ab0288..8024a3d357 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 b9716d556f..90276c2678 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -715,14 +715,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);
};