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/+/2224868 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#68103}
This commit is contained in:
parent
7c0c52861f
commit
a70348d0e0
@ -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());
|
||||
}
|
||||
#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] ";
|
||||
}
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user