Commit a70348d0 authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

Unify string debug printing

This unifies functionality between release-mode ShortPrint and
debug-mode Print:

- Prefixes and suffixes are now consistent. 'u' for two-byte, '#' for
  internalized, 'c' for cons, '>' for thin.
- Logic was simplified and is now based on 3 functions:
  PrefixForDebugPrint, PrintUC16, SuffixForDebugPrint.
- %DebugPrint no longer interprets strings as 'code markers'.
- The ancient and unused use_verbose_printer flag was removed.

Bug: v8:10581
Change-Id: Iebc6a746a2683f9f5a8ef60579836e7f66a188fa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2224868Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68103}
parent 7c0c5286
...@@ -1046,34 +1046,9 @@ void JSMessageObject::JSMessageObjectPrint(std::ostream& os) { // NOLINT ...@@ -1046,34 +1046,9 @@ void JSMessageObject::JSMessageObjectPrint(std::ostream& os) { // NOLINT
} }
void String::StringPrint(std::ostream& os) { // NOLINT void String::StringPrint(std::ostream& os) { // NOLINT
if (!IsOneByteRepresentation()) { os << PrefixForDebugPrint();
os << "u"; PrintUC16(os, 0, length());
} os << SuffixForDebugPrint();
if (StringShape(*this).IsInternalized()) {
os << "#";
} else if (StringShape(*this).IsCons()) {
os << "c\"";
} else if (StringShape(*this).IsThin()) {
os << ">\"";
} else {
os << "\"";
}
const char truncated_epilogue[] = "...<truncated>";
int len = length();
if (!FLAG_use_verbose_printer) {
if (len > 100) {
len = 100 - sizeof(truncated_epilogue);
}
}
for (int i = 0; i < len; i++) {
os << AsUC16(Get(i));
}
if (len != length()) {
os << truncated_epilogue;
}
if (!StringShape(*this).IsInternalized()) os << "\"";
} }
void Name::NamePrint(std::ostream& os) { // NOLINT void Name::NamePrint(std::ostream& os) { // NOLINT
...@@ -1475,9 +1450,7 @@ void Code::CodePrint(std::ostream& os) { // NOLINT ...@@ -1475,9 +1450,7 @@ void Code::CodePrint(std::ostream& os) { // NOLINT
PrintHeader(os, "Code"); PrintHeader(os, "Code");
os << "\n"; os << "\n";
#ifdef ENABLE_DISASSEMBLER #ifdef ENABLE_DISASSEMBLER
if (FLAG_use_verbose_printer) {
Disassemble(nullptr, os, GetIsolate()); Disassemble(nullptr, os, GetIsolate());
}
#endif #endif
} }
......
...@@ -1251,7 +1251,6 @@ DEFINE_BOOL(native_code_counters, DEBUG_BOOL, ...@@ -1251,7 +1251,6 @@ DEFINE_BOOL(native_code_counters, DEBUG_BOOL,
DEFINE_BOOL(thin_strings, true, "Enable ThinString support") DEFINE_BOOL(thin_strings, true, "Enable ThinString support")
DEFINE_BOOL(trace_prototype_users, false, DEFINE_BOOL(trace_prototype_users, false,
"Trace updates to prototype user tracking") "Trace updates to prototype user tracking")
DEFINE_BOOL(use_verbose_printer, true, "allows verbose printing")
DEFINE_BOOL(trace_for_in_enumerate, false, "Trace for-in enumerate slow-paths") DEFINE_BOOL(trace_for_in_enumerate, false, "Trace for-in enumerate slow-paths")
DEFINE_BOOL(trace_maps, false, "trace map creation") DEFINE_BOOL(trace_maps, false, "trace map creation")
DEFINE_BOOL(trace_maps_details, true, "also log map details") DEFINE_BOOL(trace_maps_details, true, "also log map details")
......
...@@ -5840,10 +5840,8 @@ void Symbol::SymbolShortPrint(std::ostream& os) { ...@@ -5840,10 +5840,8 @@ void Symbol::SymbolShortPrint(std::ostream& os) {
os << "<Symbol:"; os << "<Symbol:";
if (!description().IsUndefined()) { if (!description().IsUndefined()) {
os << " "; os << " ";
HeapStringAllocator allocator; String description_as_string = String::cast(description());
StringStream accumulator(&allocator); description_as_string.PrintUC16(os, 0, description_as_string.length());
String::cast(description()).StringShortPrint(&accumulator, false);
os << accumulator.ToCString().get();
} else { } else {
os << " (" << PrivateSymbolToName() << ")"; os << " (" << PrivateSymbolToName() << ")";
} }
......
...@@ -298,49 +298,74 @@ bool String::SupportsExternalization() { ...@@ -298,49 +298,74 @@ bool String::SupportsExternalization() {
return !isolate->heap()->IsInGCPostProcessing(); return !isolate->heap()->IsInGCPostProcessing();
} }
void String::StringShortPrint(StringStream* accumulator, bool show_details) { const char* String::PrefixForDebugPrint() const {
const char* internalized_marker = this->IsInternalizedString() ? "#" : ""; StringShape shape(*this);
if (IsTwoByteRepresentation()) {
int len = length(); StringShape shape(*this);
if (len > kMaxShortPrintLength) { if (shape.IsInternalized()) {
accumulator->Add("<Very long string[%s%u]>", internalized_marker, len); return "u#";
return; } else if (shape.IsCons()) {
return "uc\"";
} else if (shape.IsThin()) {
return "u>\"";
} else {
return "u\"";
}
} else {
StringShape shape(*this);
if (shape.IsInternalized()) {
return "#";
} else if (shape.IsCons()) {
return "c\"";
} else if (shape.IsThin()) {
return ">\"";
} else {
return "\"";
}
} }
UNREACHABLE();
}
const char* String::SuffixForDebugPrint() const {
StringShape shape(*this);
if (shape.IsInternalized()) return "";
return "\"";
}
void String::StringShortPrint(StringStream* accumulator) {
if (!LooksValid()) { if (!LooksValid()) {
accumulator->Add("<Invalid String>"); accumulator->Add("<Invalid String>");
return; return;
} }
StringCharacterStream stream(*this); const int len = length();
accumulator->Add("<String[%u]: ", len);
accumulator->Add(PrefixForDebugPrint());
bool truncated = false;
if (len > kMaxShortPrintLength) { if (len > kMaxShortPrintLength) {
len = kMaxShortPrintLength; accumulator->Add("...<truncated>>");
truncated = true; accumulator->Add(SuffixForDebugPrint());
accumulator->Put('>');
return;
} }
bool one_byte = true;
for (int i = 0; i < len; i++) {
uint16_t c = stream.GetNext();
if (c < 32 || c >= 127) { PrintUC16(accumulator, 0, len);
one_byte = false; accumulator->Add(SuffixForDebugPrint());
} accumulator->Put('>');
} }
stream.Reset(*this);
if (one_byte) { void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT
if (show_details) if (end < 0) end = length();
accumulator->Add("<String[%s%u]: ", internalized_marker, length()); StringCharacterStream stream(*this, start);
for (int i = 0; i < len; i++) { for (int i = start; i < end && stream.HasMore(); i++) {
accumulator->Put(static_cast<char>(stream.GetNext())); os << AsUC16(stream.GetNext());
} }
if (show_details) accumulator->Put('>'); }
} else {
// Backslash indicates that the string contains control void String::PrintUC16(StringStream* accumulator, int start, int end) {
// characters and that backslashes are therefore escaped. if (end < 0) end = length();
if (show_details) StringCharacterStream stream(*this, start);
accumulator->Add("<String[%s%u]\\: ", internalized_marker, length()); for (int i = start; i < end && stream.HasMore(); i++) {
for (int i = 0; i < len; i++) {
uint16_t c = stream.GetNext(); uint16_t c = stream.GetNext();
if (c == '\n') { if (c == '\n') {
accumulator->Add("\\n"); accumulator->Add("\\n");
...@@ -348,27 +373,12 @@ void String::StringShortPrint(StringStream* accumulator, bool show_details) { ...@@ -348,27 +373,12 @@ void String::StringShortPrint(StringStream* accumulator, bool show_details) {
accumulator->Add("\\r"); accumulator->Add("\\r");
} else if (c == '\\') { } else if (c == '\\') {
accumulator->Add("\\\\"); accumulator->Add("\\\\");
} else if (c < 32 || c > 126) { } else if (!std::isprint(c)) {
accumulator->Add("\\x%02x", c); accumulator->Add("\\x%02x", c);
} else { } else {
accumulator->Put(static_cast<char>(c)); accumulator->Put(static_cast<char>(c));
} }
} }
if (truncated) {
accumulator->Put('.');
accumulator->Put('.');
accumulator->Put('.');
}
if (show_details) accumulator->Put('>');
}
}
void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT
if (end < 0) end = length();
StringCharacterStream stream(*this, start);
for (int i = start; i < end && stream.HasMore(); i++) {
os << AsUC16(stream.GetNext());
}
} }
// static // static
......
...@@ -353,8 +353,11 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -353,8 +353,11 @@ class String : public TorqueGeneratedString<String, Name> {
bool LooksValid(); bool LooksValid();
// Dispatched behavior. // Dispatched behavior.
void StringShortPrint(StringStream* accumulator, bool show_details = true); const char* PrefixForDebugPrint() const;
const char* SuffixForDebugPrint() const;
void StringShortPrint(StringStream* accumulator);
void PrintUC16(std::ostream& os, int start = 0, int end = -1); // NOLINT void PrintUC16(std::ostream& os, int start = 0, int end = -1); // NOLINT
void PrintUC16(StringStream* accumulator, int start, int end);
#if defined(DEBUG) || defined(OBJECT_PRINT) #if defined(DEBUG) || defined(OBJECT_PRINT)
char* ToAsciiArray(); char* ToAsciiArray();
#endif #endif
......
...@@ -752,38 +752,21 @@ RUNTIME_FUNCTION(Runtime_DebugPrint) { ...@@ -752,38 +752,21 @@ RUNTIME_FUNCTION(Runtime_DebugPrint) {
bool weak = maybe_object.IsWeak(); bool weak = maybe_object.IsWeak();
#ifdef OBJECT_PRINT #ifdef OBJECT_PRINT
if (object.IsString() && !isolate->context().is_null()) {
DCHECK(!weak);
// If we have a string, assume it's a code "marker"
// and print some interesting cpu debugging info.
object.Print(os);
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
os << "fp = " << reinterpret_cast<void*>(frame->fp())
<< ", sp = " << reinterpret_cast<void*>(frame->sp())
<< ", caller_sp = " << reinterpret_cast<void*>(frame->caller_sp())
<< ": ";
} else {
os << "DebugPrint: "; os << "DebugPrint: ";
if (weak) { if (weak) os << "[weak] ";
os << "[weak] ";
}
object.Print(os); object.Print(os);
}
if (object.IsHeapObject()) { if (object.IsHeapObject()) {
HeapObject::cast(object).map().Print(os); HeapObject::cast(object).map().Print(os);
} }
#else #else
if (weak) { if (weak) os << "[weak] ";
os << "[weak] ";
}
// ShortPrint is available in release mode. Print is not. // ShortPrint is available in release mode. Print is not.
os << Brief(object); os << Brief(object);
#endif #endif
} }
os << std::endl; os << std::endl;
return args[0]; // return TOS return args[0];
} }
RUNTIME_FUNCTION(Runtime_PrintWithNameForAssert) { RUNTIME_FUNCTION(Runtime_PrintWithNameForAssert) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment