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
}
void String::StringPrint(std::ostream& os) { // NOLINT
if (!IsOneByteRepresentation()) {
os << "u";
}
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 << "\"";
os << PrefixForDebugPrint();
PrintUC16(os, 0, length());
os << SuffixForDebugPrint();
}
void Name::NamePrint(std::ostream& os) { // NOLINT
......@@ -1475,9 +1450,7 @@ void Code::CodePrint(std::ostream& os) { // NOLINT
PrintHeader(os, "Code");
os << "\n";
#ifdef ENABLE_DISASSEMBLER
if (FLAG_use_verbose_printer) {
Disassemble(nullptr, os, GetIsolate());
}
Disassemble(nullptr, os, GetIsolate());
#endif
}
......
......@@ -1251,7 +1251,6 @@ DEFINE_BOOL(native_code_counters, DEBUG_BOOL,
DEFINE_BOOL(thin_strings, true, "Enable ThinString support")
DEFINE_BOOL(trace_prototype_users, false,
"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_maps, false, "trace map creation")
DEFINE_BOOL(trace_maps_details, true, "also log map details")
......
......@@ -5840,10 +5840,8 @@ void Symbol::SymbolShortPrint(std::ostream& os) {
os << "<Symbol:";
if (!description().IsUndefined()) {
os << " ";
HeapStringAllocator allocator;
StringStream accumulator(&allocator);
String::cast(description()).StringShortPrint(&accumulator, false);
os << accumulator.ToCString().get();
String description_as_string = String::cast(description());
description_as_string.PrintUC16(os, 0, description_as_string.length());
} else {
os << " (" << PrivateSymbolToName() << ")";
}
......
......@@ -298,69 +298,60 @@ bool String::SupportsExternalization() {
return !isolate->heap()->IsInGCPostProcessing();
}
void String::StringShortPrint(StringStream* accumulator, bool show_details) {
const char* internalized_marker = this->IsInternalizedString() ? "#" : "";
int len = length();
if (len > kMaxShortPrintLength) {
accumulator->Add("<Very long string[%s%u]>", internalized_marker, len);
return;
const char* String::PrefixForDebugPrint() const {
StringShape shape(*this);
if (IsTwoByteRepresentation()) {
StringShape shape(*this);
if (shape.IsInternalized()) {
return "u#";
} 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()) {
accumulator->Add("<Invalid String>");
return;
}
StringCharacterStream stream(*this);
const int len = length();
accumulator->Add("<String[%u]: ", len);
accumulator->Add(PrefixForDebugPrint());
bool truncated = false;
if (len > kMaxShortPrintLength) {
len = kMaxShortPrintLength;
truncated = true;
accumulator->Add("...<truncated>>");
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) {
one_byte = false;
}
}
stream.Reset(*this);
if (one_byte) {
if (show_details)
accumulator->Add("<String[%s%u]: ", internalized_marker, length());
for (int i = 0; i < len; i++) {
accumulator->Put(static_cast<char>(stream.GetNext()));
}
if (show_details) accumulator->Put('>');
} else {
// Backslash indicates that the string contains control
// characters and that backslashes are therefore escaped.
if (show_details)
accumulator->Add("<String[%s%u]\\: ", internalized_marker, length());
for (int i = 0; i < len; i++) {
uint16_t c = stream.GetNext();
if (c == '\n') {
accumulator->Add("\\n");
} else if (c == '\r') {
accumulator->Add("\\r");
} else if (c == '\\') {
accumulator->Add("\\\\");
} else if (c < 32 || c > 126) {
accumulator->Add("\\x%02x", c);
} else {
accumulator->Put(static_cast<char>(c));
}
}
if (truncated) {
accumulator->Put('.');
accumulator->Put('.');
accumulator->Put('.');
}
if (show_details) accumulator->Put('>');
}
PrintUC16(accumulator, 0, len);
accumulator->Add(SuffixForDebugPrint());
accumulator->Put('>');
}
void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT
......@@ -371,6 +362,25 @@ void String::PrintUC16(std::ostream& os, int start, int end) { // NOLINT
}
}
void String::PrintUC16(StringStream* accumulator, int start, int end) {
if (end < 0) end = length();
StringCharacterStream stream(*this, start);
for (int i = start; i < end && stream.HasMore(); i++) {
uint16_t c = stream.GetNext();
if (c == '\n') {
accumulator->Add("\\n");
} else if (c == '\r') {
accumulator->Add("\\r");
} else if (c == '\\') {
accumulator->Add("\\\\");
} else if (!std::isprint(c)) {
accumulator->Add("\\x%02x", c);
} else {
accumulator->Put(static_cast<char>(c));
}
}
}
// static
Handle<String> String::Trim(Isolate* isolate, Handle<String> string,
TrimMode mode) {
......
......@@ -353,8 +353,11 @@ class String : public TorqueGeneratedString<String, Name> {
bool LooksValid();
// 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(StringStream* accumulator, int start, int end);
#if defined(DEBUG) || defined(OBJECT_PRINT)
char* ToAsciiArray();
#endif
......
......@@ -752,38 +752,21 @@ RUNTIME_FUNCTION(Runtime_DebugPrint) {
bool weak = maybe_object.IsWeak();
#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: ";
if (weak) {
os << "[weak] ";
}
object.Print(os);
}
os << "DebugPrint: ";
if (weak) os << "[weak] ";
object.Print(os);
if (object.IsHeapObject()) {
HeapObject::cast(object).map().Print(os);
}
#else
if (weak) {
os << "[weak] ";
}
if (weak) os << "[weak] ";
// ShortPrint is available in release mode. Print is not.
os << Brief(object);
#endif
}
os << std::endl;
return args[0]; // return TOS
return args[0];
}
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