diff --git a/src/hotspot/share/memory/arena.hpp b/src/hotspot/share/memory/arena.hpp index 4c95d656e25..ed441eca851 100644 --- a/src/hotspot/share/memory/arena.hpp +++ b/src/hotspot/share/memory/arena.hpp @@ -87,7 +87,7 @@ public: class Arena : public CHeapObjBase { public: - enum class Tag { + enum class Tag : uint8_t { tag_other = 0, tag_ra, // resource area tag_ha, // handle area @@ -101,6 +101,7 @@ protected: MEMFLAGS _flags; // Memory tracking flags const Tag _tag; + uint32_t _init_size; Chunk* _first; // First chunk Chunk* _chunk; // current chunk char* _hwm; // High water mark diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp index 1dc4e58169d..e5969bbaf8f 100644 --- a/src/hotspot/share/nmt/memReporter.cpp +++ b/src/hotspot/share/nmt/memReporter.cpp @@ -31,7 +31,14 @@ #include "nmt/memoryFileTracker.hpp" #include "nmt/threadStackTracker.hpp" #include "nmt/virtualMemoryTracker.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/ostream.hpp" + +#define INDENT_BY(num_chars, CODE) { \ + streamIndentor si(out, num_chars); \ + { CODE } \ +} // Diff two counters, express them as signed, with range checks static ssize_t counter_diff(size_t c1, size_t c2) { @@ -43,6 +50,15 @@ static ssize_t counter_diff(size_t c1, size_t c2) { return c1 - c2; } +MemReporterBase::MemReporterBase(outputStream* out, size_t scale) : + _scale(scale), _output(out) { + _output->set_autoindent(true); +} + +MemReporterBase::~MemReporterBase() { + _output->set_autoindent(false); +} + size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) { return malloc->malloc_size() + malloc->arena_size() + vm->reserved(); } @@ -105,27 +121,15 @@ void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed, si } } -void MemReporterBase::print_malloc_line(const MemoryCounter* c) const { - output()->print("%28s", " "); - print_malloc(c); - output()->print_cr(" "); -} - -void MemReporterBase::print_virtual_memory_line(size_t reserved, size_t committed, size_t peak) const { - output()->print("%28s", " "); - print_virtual_memory(reserved, committed, peak); - output()->print_cr(" "); -} - -void MemReporterBase::print_arena_line(const MemoryCounter* c) const { +void MemReporterBase::print_arena(const MemoryCounter* c) const { const char* scale = current_scale(); outputStream* out = output(); const size_t amount = c->size(); const size_t count = c->count(); - out->print("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", "", - amount_in_current_scale(amount), scale, count); + out->print("(arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", + amount_in_current_scale(amount), scale, count); size_t pk_amount = c->peak_size(); if (pk_amount == amount) { @@ -135,8 +139,6 @@ void MemReporterBase::print_arena_line(const MemoryCounter* c) const { out->print(" (peak=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", amount_in_current_scale(pk_amount), scale, pk_count); } - - out->cr(); } void MemReporterBase::print_virtual_memory_region(const char* type, address base, size_t size) const { @@ -156,7 +158,9 @@ void MemSummaryReporter::report() { size_t total_committed_amount = total_malloced_bytes + total_mmap_committed_bytes; // Overall total - out->print_cr("\nNative Memory Tracking:\n"); + out->cr(); + out->print_cr("Native Memory Tracking:"); + out->cr(); if (scale() > 1) { out->print_cr("(Omitting categories weighting less than 1%s)", current_scale()); @@ -166,13 +170,15 @@ void MemSummaryReporter::report() { out->print("Total: "); print_total(total_reserved_amount, total_committed_amount); out->cr(); - out->print_cr(" malloc: " SIZE_FORMAT "%s #" SIZE_FORMAT ", peak=" SIZE_FORMAT "%s #" SIZE_FORMAT, - amount_in_current_scale(total_malloced_bytes), current_scale(), - _malloc_snapshot->total_count(), - amount_in_current_scale(_malloc_snapshot->total_peak()), - current_scale(), _malloc_snapshot->total_peak_count()); - out->print(" mmap: "); - print_total(total_mmap_reserved_bytes, total_mmap_committed_bytes); + INDENT_BY(7, + out->print_cr("malloc: " SIZE_FORMAT "%s #" SIZE_FORMAT ", peak=" SIZE_FORMAT "%s #" SIZE_FORMAT, + amount_in_current_scale(total_malloced_bytes), current_scale(), + _malloc_snapshot->total_count(), + amount_in_current_scale(_malloc_snapshot->total_peak()), + current_scale(), _malloc_snapshot->total_peak_count()); + out->print("mmap: "); + print_total(total_mmap_reserved_bytes, total_mmap_committed_bytes); + ) out->cr(); out->cr(); @@ -218,7 +224,8 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, outputStream* out = output(); const char* scale = current_scale(); - out->print("-%26s (", NMTUtil::flag_to_name(flag)); + constexpr int indent = 28; + out->print("-%*s (", indent - 2, NMTUtil::flag_to_name(flag)); print_total(reserved_amount, committed_amount); #if INCLUDE_CDS if (flag == mtClassShared) { @@ -229,39 +236,43 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, #endif out->print_cr(")"); + streamIndentor si(out, indent); + if (flag == mtClass) { // report class count - out->print_cr("%27s (classes #" SIZE_FORMAT ")", - " ", (_instance_class_count + _array_class_count)); - out->print_cr("%27s ( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")", - " ", _instance_class_count, _array_class_count); + out->print_cr("(classes #" SIZE_FORMAT ")", (_instance_class_count + _array_class_count)); + out->print_cr("( instance classes #" SIZE_FORMAT ", array classes #" SIZE_FORMAT ")", + _instance_class_count, _array_class_count); } else if (flag == mtThread) { const VirtualMemory* thread_stack_usage = _vm_snapshot->by_type(mtThreadStack); // report thread count - out->print_cr("%27s (threads #" SIZE_FORMAT ")", " ", ThreadStackTracker::thread_count()); - out->print("%27s (stack: ", " "); + out->print_cr("(threads #" SIZE_FORMAT ")", ThreadStackTracker::thread_count()); + out->print("(stack: "); print_total(thread_stack_usage->reserved(), thread_stack_usage->committed(), thread_stack_usage->peak_size()); out->print_cr(")"); } // report malloc'd memory if (amount_in_current_scale(MAX2(malloc_memory->malloc_size(), pk_malloc)) > 0) { - print_malloc_line(malloc_memory->malloc_counter()); + print_malloc(malloc_memory->malloc_counter()); + out->cr(); } if (amount_in_current_scale(MAX2(virtual_memory->reserved(), pk_vm)) > 0) { - print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed(), virtual_memory->peak_size()); + print_virtual_memory(virtual_memory->reserved(), virtual_memory->committed(), virtual_memory->peak_size()); + out->cr(); } if (amount_in_current_scale(MAX2(malloc_memory->arena_size(), pk_arena)) > 0) { - print_arena_line(malloc_memory->arena_counter()); + print_arena(malloc_memory->arena_counter()); + out->cr(); } if (flag == mtNMT && amount_in_current_scale(_malloc_snapshot->malloc_overhead()) > 0) { - out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ", - amount_in_current_scale(_malloc_snapshot->malloc_overhead()), scale); + out->print_cr("(tracking overhead=" SIZE_FORMAT "%s)", + amount_in_current_scale(_malloc_snapshot->malloc_overhead()), scale); } else if (flag == mtClass) { // Metadata information report_metadata(Metaspace::NonClassType); @@ -269,7 +280,7 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, report_metadata(Metaspace::ClassType); } } - out->print_cr(" "); + out->cr(); } void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const { @@ -292,13 +303,13 @@ void MemSummaryReporter::report_metadata(Metaspace::MetadataType type) const { size_t waste = stats.committed() - stats.used(); float waste_percentage = stats.committed() > 0 ? (((float)waste * 100)/(float)stats.committed()) : 0.0f; - out->print_cr("%27s ( %s)", " ", name); - out->print("%27s ( ", " "); + out->print_cr("( %s)", name); + out->print("( "); print_total(stats.reserved(), stats.committed()); out->print_cr(")"); - out->print_cr("%27s ( used=" SIZE_FORMAT "%s)", " ", amount_in_current_scale(stats.used()), scale); - out->print_cr("%27s ( waste=" SIZE_FORMAT "%s =%2.2f%%)", " ", amount_in_current_scale(waste), - scale, waste_percentage); + out->print_cr("( used=" SIZE_FORMAT "%s)", amount_in_current_scale(stats.used()), scale); + out->print_cr("( waste=" SIZE_FORMAT "%s =%2.2f%%)", amount_in_current_scale(waste), + scale, waste_percentage); } void MemDetailReporter::report_detail() { @@ -333,12 +344,15 @@ int MemDetailReporter::report_malloc_sites() { } const NativeCallStack* stack = malloc_site->call_stack(); stack->print_on(out); - out->print("%29s", " "); MEMFLAGS flag = malloc_site->flag(); assert(NMTUtil::flag_is_valid(flag) && flag != mtNone, "Must have a valid memory type"); - print_malloc(malloc_site->counter(), flag); - out->print_cr("\n"); + INDENT_BY(29, + out->print("("); + print_malloc(malloc_site->counter(), flag); + out->print_cr(")"); + ) + out->cr(); } return num_omitted; } @@ -350,6 +364,7 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() { if (virtual_memory_itr.is_empty()) return 0; outputStream* out = output(); + const VirtualMemoryAllocationSite* virtual_memory_site; int num_omitted = 0; while ((virtual_memory_site = virtual_memory_itr.next()) != nullptr) { @@ -366,13 +381,16 @@ int MemDetailReporter::report_virtual_memory_allocation_sites() { } const NativeCallStack* stack = virtual_memory_site->call_stack(); stack->print_on(out); - out->print("%28s (", " "); - print_total(virtual_memory_site->reserved(), virtual_memory_site->committed()); - MEMFLAGS flag = virtual_memory_site->flag(); - if (flag != mtNone) { - out->print(" Type=%s", NMTUtil::flag_to_name(flag)); - } - out->print_cr(")\n"); + INDENT_BY(29, + out->print("("); + print_total(virtual_memory_site->reserved(), virtual_memory_site->committed()); + const MEMFLAGS flag = virtual_memory_site->flag(); + if (flag != mtNone) { + out->print(" Type=%s", NMTUtil::flag_to_name(flag)); + } + out->print_cr(")"); + ) + out->cr(); } return num_omitted; } @@ -409,14 +427,14 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* const NativeCallStack* stack = reserved_rgn->call_stack(); bool all_committed = reserved_rgn->size() == reserved_rgn->committed_size(); const char* region_type = (all_committed ? "reserved and committed" : "reserved"); - out->print_cr(" "); + out->cr(); print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size()); out->print(" for %s", NMTUtil::flag_to_name(reserved_rgn->flag())); if (stack->is_empty()) { - out->print_cr(" "); + out->cr(); } else { out->print_cr(" from"); - stack->print_on(out, 4); + INDENT_BY(4, stack->print_on(out);) } if (all_committed) { @@ -437,20 +455,33 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* // Don't report if size is too small if (amount_in_current_scale(committed_rgn->size()) == 0) continue; stack = committed_rgn->call_stack(); - out->print("\n\t"); - print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size()); - if (stack->is_empty()) { - out->print_cr(" "); - } else { - out->print_cr(" from"); - stack->print_on(out, 12); - } + out->cr(); + INDENT_BY(8, + print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size()); + if (stack->is_empty()) { + out->cr(); + } else { + out->print_cr(" from"); + INDENT_BY(4, stack->print_on(out);) + } + ) } } +void MemDetailReporter::report_memory_file_allocations() { + stringStream st; + { + MemoryFileTracker::Instance::Locker lock; + MemoryFileTracker::Instance::print_all_reports_on(&st, scale()); + } + output()->print_raw(st.freeze()); +} + void MemSummaryDiffReporter::report_diff() { outputStream* out = output(); - out->print_cr("\nNative Memory Tracking:\n"); + out->cr(); + out->print_cr("Native Memory Tracking:"); + out->cr(); if (scale() > 1) { out->print_cr("(Omitting categories weighting less than 1%s)", current_scale()); @@ -463,7 +494,8 @@ void MemSummaryDiffReporter::report_diff() { _current_baseline.total_committed_memory(), _early_baseline.total_reserved_memory(), _early_baseline.total_committed_memory()); - out->print_cr("\n"); + out->cr(); + out->cr(); // Summary diff by memory type for (int index = 0; index < mt_number_of_types; index ++) { @@ -548,6 +580,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, outputStream* out = output(); const char* scale = current_scale(); + constexpr int indent = 28; // Total reserved and committed memory in current baseline size_t current_reserved_amount = reserved_total (current_malloc, current_vm); @@ -581,15 +614,17 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, diff_in_current_scale(current_reserved_amount, early_reserved_amount) != 0) { // print summary line - out->print("-%26s (", NMTUtil::flag_to_name(flag)); + out->print("-%*s (", indent - 2, NMTUtil::flag_to_name(flag)); print_virtual_memory_diff(current_reserved_amount, current_committed_amount, early_reserved_amount, early_committed_amount); out->print_cr(")"); + streamIndentor si(out, indent); + // detail lines if (flag == mtClass) { // report class count - out->print("%27s (classes #" SIZE_FORMAT "", " ", _current_baseline.class_count()); + out->print("(classes #" SIZE_FORMAT, _current_baseline.class_count()); const ssize_t class_count_diff = counter_diff(_current_baseline.class_count(), _early_baseline.class_count()); if (class_count_diff != 0) { @@ -597,7 +632,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, } out->print_cr(")"); - out->print("%27s ( instance classes #" SIZE_FORMAT, " ", _current_baseline.instance_class_count()); + out->print("( instance classes #" SIZE_FORMAT, _current_baseline.instance_class_count()); const ssize_t instance_class_count_diff = counter_diff(_current_baseline.instance_class_count(), _early_baseline.instance_class_count()); if (instance_class_count_diff != 0) { @@ -613,14 +648,14 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, } else if (flag == mtThread) { // report thread count - out->print("%27s (threads #" SIZE_FORMAT "", " ", _current_baseline.thread_count()); + out->print("(threads #" SIZE_FORMAT, _current_baseline.thread_count()); const ssize_t thread_count_diff = counter_diff(_current_baseline.thread_count(), _early_baseline.thread_count()); if (thread_count_diff != 0) { out->print(" " SSIZE_PLUS_FORMAT, thread_count_diff); } out->print_cr(")"); - out->print("%27s (stack: ", " "); + out->print("(stack: "); // report thread stack const VirtualMemory* current_thread_stack = _current_baseline.virtual_memory(mtThreadStack); @@ -638,7 +673,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, size_t early_malloc_amount = early_malloc->malloc_size(); if (amount_in_current_scale(current_malloc_amount) > 0 || diff_in_current_scale(current_malloc_amount, early_malloc_amount) != 0) { - out->print("%28s(", " "); + out->print("("); print_malloc_diff(current_malloc_amount, (flag == mtChunk) ? 0 : current_malloc->malloc_count(), early_malloc_amount, early_malloc->malloc_count(), mtNone); out->print_cr(")"); @@ -647,7 +682,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, // Report virtual memory if (amount_in_current_scale(current_vm->reserved()) > 0 || diff_in_current_scale(current_vm->reserved(), early_vm->reserved()) != 0) { - out->print("%27s (mmap: ", " "); + out->print("(mmap: "); print_virtual_memory_diff(current_vm->reserved(), current_vm->committed(), early_vm->reserved(), early_vm->committed()); out->print_cr(")"); @@ -656,7 +691,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, // Report arena memory if (amount_in_current_scale(current_malloc->arena_size()) > 0 || diff_in_current_scale(current_malloc->arena_size(), early_malloc->arena_size()) != 0) { - out->print("%28s(", " "); + out->print("("); print_arena_diff(current_malloc->arena_size(), current_malloc->arena_count(), early_malloc->arena_size(), early_malloc->arena_count()); out->print_cr(")"); @@ -667,8 +702,8 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, size_t current_tracking_overhead = amount_in_current_scale(_current_baseline.malloc_tracking_overhead()); size_t early_tracking_overhead = amount_in_current_scale(_early_baseline.malloc_tracking_overhead()); - out->print("%27s (tracking overhead=" SIZE_FORMAT "%s", " ", - amount_in_current_scale(_current_baseline.malloc_tracking_overhead()), scale); + out->print("(tracking overhead=" SIZE_FORMAT "%s", + amount_in_current_scale(_current_baseline.malloc_tracking_overhead()), scale); int64_t overhead_diff = diff_in_current_scale(_current_baseline.malloc_tracking_overhead(), _early_baseline.malloc_tracking_overhead()); @@ -679,7 +714,7 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, } else if (flag == mtClass) { print_metaspace_diff(current_ms, early_ms); } - out->print_cr(" "); + out->cr(); } } @@ -697,8 +732,8 @@ void MemSummaryDiffReporter::print_metaspace_diff(const char* header, outputStream* out = output(); const char* scale = current_scale(); - out->print_cr("%27s: ( %s)", " ", header); - out->print("%27s ( ", " "); + out->print_cr("( %s)", header); + out->print("( "); print_virtual_memory_diff(current_stats.reserved(), current_stats.committed(), early_stats.reserved(), @@ -713,8 +748,8 @@ void MemSummaryDiffReporter::print_metaspace_diff(const char* header, int64_t diff_waste = diff_in_current_scale(current_waste, early_waste); // Diff used - out->print("%27s ( used=" SIZE_FORMAT "%s", " ", - amount_in_current_scale(current_stats.used()), scale); + out->print("( used=" SIZE_FORMAT "%s", + amount_in_current_scale(current_stats.used()), scale); if (diff_used != 0) { out->print(" " INT64_PLUS_FORMAT "%s", diff_used, scale); } @@ -723,8 +758,8 @@ void MemSummaryDiffReporter::print_metaspace_diff(const char* header, // Diff waste const float waste_percentage = current_stats.committed() == 0 ? 0.0f : ((float)current_waste * 100.0f) / (float)current_stats.committed(); - out->print("%27s ( waste=" SIZE_FORMAT "%s =%2.2f%%", " ", - amount_in_current_scale(current_waste), scale, waste_percentage); + out->print("( waste=" SIZE_FORMAT "%s =%2.2f%%", + amount_in_current_scale(current_waste), scale, waste_percentage); if (diff_waste != 0) { out->print(" " INT64_PLUS_FORMAT "%s", diff_waste, scale); } @@ -841,11 +876,13 @@ void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_ } stack->print_on(out); - out->print("%28s (", " "); - print_malloc_diff(current_size, current_count, - early_size, early_count, flags); + INDENT_BY(28, + out->print("("); + print_malloc_diff(current_size, current_count, early_size, early_count, flags); + out->print_cr(")"); + ) + out->cr(); - out->print_cr(")\n"); } @@ -874,22 +911,14 @@ void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stac } stack->print_on(out); - out->print("%28s (mmap: ", " "); - print_virtual_memory_diff(current_reserved, current_committed, - early_reserved, early_committed); - - if (flag != mtNone) { - out->print(" Type=%s", NMTUtil::flag_to_name(flag)); - } - - out->print_cr(")\n"); + INDENT_BY(28, + out->print("(mmap: "); + print_virtual_memory_diff(current_reserved, current_committed, early_reserved, early_committed); + if (flag != mtNone) { + out->print(" Type=%s", NMTUtil::flag_to_name(flag)); + } + out->print_cr(")"); + ) + out->cr(); } -void MemDetailReporter::report_memory_file_allocations() { - stringStream st; - { - MemoryFileTracker::Instance::Locker lock; - MemoryFileTracker::Instance::print_all_reports_on(&st, scale()); - } - output()->print_raw(st.freeze()); -} diff --git a/src/hotspot/share/nmt/memReporter.hpp b/src/hotspot/share/nmt/memReporter.hpp index 9355704531c..3f08ecbd284 100644 --- a/src/hotspot/share/nmt/memReporter.hpp +++ b/src/hotspot/share/nmt/memReporter.hpp @@ -44,9 +44,8 @@ class MemReporterBase : public StackObj { // Default scale to use if no scale given. static const size_t default_scale = K; - MemReporterBase(outputStream* out, size_t scale = default_scale) : - _scale(scale), _output(out) - {} + MemReporterBase(outputStream* out, size_t scale = default_scale); + ~MemReporterBase(); // Helper functions // Calculate total reserved and committed amount @@ -109,10 +108,7 @@ class MemReporterBase : public StackObj { void print_total(size_t reserved, size_t committed, size_t peak = 0) const; void print_malloc(const MemoryCounter* c, MEMFLAGS flag = mtNone) const; void print_virtual_memory(size_t reserved, size_t committed, size_t peak) const; - - void print_malloc_line(const MemoryCounter* c) const; - void print_virtual_memory_line(size_t reserved, size_t committed, size_t peak) const; - void print_arena_line(const MemoryCounter* c) const; + void print_arena(const MemoryCounter* c) const; void print_virtual_memory_region(const char* type, address base, size_t size) const; }; diff --git a/src/hotspot/share/nmt/memoryFileTracker.cpp b/src/hotspot/share/nmt/memoryFileTracker.cpp index a92f8e9f538..25f2667e5c3 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.cpp +++ b/src/hotspot/share/nmt/memoryFileTracker.cpp @@ -92,7 +92,10 @@ void MemoryFileTracker::print_report_on(const MemoryFile* file, outputStream* st NMTUtil::amount_in_scale(end_addr - start_addr, scale), NMTUtil::scale_name(scale), NMTUtil::flag_to_name(prev->val().out.flag())); - _stack_storage.get(prev->val().out.stack()).print_on(stream, 4); + { + streamIndentor si(stream, 4); + _stack_storage.get(prev->val().out.stack()).print_on(stream); + } stream->cr(); } prev = current; diff --git a/src/hotspot/share/utilities/nativeCallStack.cpp b/src/hotspot/share/utilities/nativeCallStack.cpp index 3ddf296506c..873f3856b74 100644 --- a/src/hotspot/share/utilities/nativeCallStack.cpp +++ b/src/hotspot/share/utilities/nativeCallStack.cpp @@ -71,24 +71,18 @@ int NativeCallStack::frames() const { return index; } -void NativeCallStack::print_on(outputStream* out) const { - print_on(out, 0); -} - // Decode and print this call path -void NativeCallStack::print_on(outputStream* out, int indent) const { +void NativeCallStack::print_on(outputStream* out) const { DEBUG_ONLY(assert_not_fake();) address pc; char buf[1024]; int offset; if (is_empty()) { - out->fill_to(indent); out->print("[BOOTSTRAP]"); } else { for (int frame = 0; frame < NMT_TrackingStackDepth; frame ++) { pc = get_frame(frame); if (pc == nullptr) break; - out->fill_to(indent); out->print("[" PTR_FORMAT "]", p2i(pc)); // Print function and library; shorten library name to just its last component // for brevity, and omit it completely for libjvm.so diff --git a/src/hotspot/share/utilities/nativeCallStack.hpp b/src/hotspot/share/utilities/nativeCallStack.hpp index 43e90512b52..6c04169146e 100644 --- a/src/hotspot/share/utilities/nativeCallStack.hpp +++ b/src/hotspot/share/utilities/nativeCallStack.hpp @@ -124,7 +124,6 @@ public: } void print_on(outputStream* out) const; - void print_on(outputStream* out, int indent) const; }; #define FAKE_CALLSTACK NativeCallStack(NativeCallStack::FakeMarker::its_fake) diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index 858f6798e28..72df31e12f9 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -44,18 +44,11 @@ extern "C" void jio_print(const char* s, size_t len); extern "C" int jio_printf(const char *fmt, ...); -outputStream::outputStream() { - _position = 0; - _precount = 0; - _indentation = 0; - _scratch = nullptr; - _scratch_len = 0; -} - outputStream::outputStream(bool has_time_stamps) { _position = 0; _precount = 0; _indentation = 0; + _autoindent = false; _scratch = nullptr; _scratch_len = 0; if (has_time_stamps) _stamp.update(); @@ -159,6 +152,9 @@ void outputStream::do_vsnprintf_and_write_with_scratch_buffer(const char* format } void outputStream::do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) { + if (_autoindent && _position == 0) { + indent(); + } if (_scratch) { do_vsnprintf_and_write_with_scratch_buffer(format, ap, add_cr); } else { @@ -188,6 +184,13 @@ void outputStream::vprint_cr(const char* format, va_list argptr) { do_vsnprintf_and_write(format, argptr, true); } +void outputStream::print_raw(const char* str, size_t len) { + if (_autoindent && _position == 0) { + indent(); + } + write(str, len); +} + void outputStream::fill_to(int col) { int need_fill = col - position(); sp(need_fill); diff --git a/src/hotspot/share/utilities/ostream.hpp b/src/hotspot/share/utilities/ostream.hpp index 98ea9f54a34..b4ce7c32c60 100644 --- a/src/hotspot/share/utilities/ostream.hpp +++ b/src/hotspot/share/utilities/ostream.hpp @@ -46,9 +46,10 @@ DEBUG_ONLY(class ResourceMark;) class outputStream : public CHeapObjBase { private: NONCOPYABLE(outputStream); + int _indentation; // current indentation + bool _autoindent; // if true, every line starts with indentation protected: - int _indentation; // current indentation int _position; // visual position on the current line uint64_t _precount; // number of chars output, less than _position TimeStamp _stamp; // for time stamps @@ -90,8 +91,7 @@ class outputStream : public CHeapObjBase { class TestSupport; // Unit test support // creation - outputStream(); - outputStream(bool has_time_stamps); + outputStream(bool has_time_stamps = false); // indentation outputStream& indent(); @@ -104,6 +104,13 @@ class outputStream : public CHeapObjBase { void fill_to(int col); void move_to(int col, int slop = 6, int min_space = 2); + // Automatic indentation: + // If autoindent mode is on, the following APIs will automatically indent + // line starts depending on the current indentation level: + // print(), print_cr(), print_raw(), print_raw_cr() + // Other APIs are unaffected + void set_autoindent(bool value) { _autoindent = value; } + // sizing int position() const { return _position; } julong count() const { return _precount + _position; } @@ -119,10 +126,10 @@ class outputStream : public CHeapObjBase { void print_cr(const char* format, ...) ATTRIBUTE_PRINTF(2, 3); void vprint(const char *format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); void vprint_cr(const char* format, va_list argptr) ATTRIBUTE_PRINTF(2, 0); - void print_raw(const char* str) { write(str, strlen(str)); } - void print_raw(const char* str, size_t len) { write(str, len); } - void print_raw_cr(const char* str) { write(str, strlen(str)); cr(); } - void print_raw_cr(const char* str, size_t len){ write(str, len); cr(); } + void print_raw(const char* str) { print_raw(str, strlen(str)); } + void print_raw(const char* str, size_t len); + void print_raw_cr(const char* str) { print_raw(str); cr(); } + void print_raw_cr(const char* str, size_t len) { print_raw(str, len); cr(); } void print_data(void* data, size_t len, bool with_ascii, bool rel_addr=true); void put(char ch); void sp(int count = 1); diff --git a/test/hotspot/gtest/utilities/test_ostream.cpp b/test/hotspot/gtest/utilities/test_ostream.cpp index 270ba59212a..26fd9d227c1 100644 --- a/test/hotspot/gtest/utilities/test_ostream.cpp +++ b/test/hotspot/gtest/utilities/test_ostream.cpp @@ -104,6 +104,53 @@ TEST_VM(ostream, bufferedStream_dynamic_small) { } } +static void test_autoindent(bool on) { + stringStream ss; + ss.set_autoindent(on); + { + streamIndentor si(&ss, 5); + ss.print("ABC"); + ss.print("DEF"); + ss.cr(); + ss.print_cr("0123"); + { + streamIndentor si(&ss, 5); + ss.print_cr("4567"); + ss.print_raw("89AB"); + ss.print_raw("CDEXXXX", 3); + ss.print_raw_cr("XYZ"); + } + ss.print("%u", 100); + ss.print_raw("KB"); + ss.cr(); + } + ss.print("end"); + + if (on) { + EXPECT_STREQ(ss.base(), + " ABCDEF\n" + " 0123\n" + " 4567\n" + " 89ABCDEXYZ\n" + " 100KB\n" + "end" + ); + } else { + // no autoindent: calls should work as always without indentation + EXPECT_STREQ(ss.base(), + "ABCDEF\n" + "0123\n" + "4567\n" + "89ABCDEXYZ\n" + "100KB\n" + "end" + ); + } +} + +TEST_VM(ostream, autoindent_on) { test_autoindent(true); } +TEST_VM(ostream, autoindent_off) { test_autoindent(false); } + /* Activate to manually test bufferedStream dynamic cap. TEST_VM(ostream, bufferedStream_dynamic_large) {