Commit 86fee30e authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

Include standard heap object header when debug-printing String objects

This brings %DebugPrint(string) closer to %DebugPrint(object) by also
including the pointer, object kind, and RO/old space. Especially the
pointer can be useful while debugging.

One could consider going even further end printing full details of
the string object, e.g. first and second pointers for cons strings.

Before:

 $ out/debug/d8 --allow-natives-syntax -e '%DebugPrint("abc");'
 DebugPrint: #abc
 0x263f080402cd: [Map] in ReadOnlySpace
 [...]

After:

 $ out/debug/d8 --allow-natives-syntax -e '%DebugPrint("abc");'
 DebugPrint: 0xa830824ffe1: [String] in OldSpace: #abc
 0xa83080402cd: [Map] in ReadOnlySpace
 [...]

Drive-by: Document string printing functions.
Drive-by: Use PrintUC16 in spots that don't want a full debug print.

Bug: v8:10581
Change-Id: Ided59047b9c3edc1830ce7721376dddfd24fad1d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2228509Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68136}
parent 0262bc10
...@@ -97,19 +97,28 @@ void Object::Print(std::ostream& os) const { // NOLINT ...@@ -97,19 +97,28 @@ void Object::Print(std::ostream& os) const { // NOLINT
} }
} }
void HeapObject::PrintHeader(std::ostream& os, const char* id) { // NOLINT namespace {
os << reinterpret_cast<void*>(ptr()) << ": [";
void PrintHeapObjectHeaderWithoutMap(HeapObject object, std::ostream& os,
const char* id) { // NOLINT
os << reinterpret_cast<void*>(object.ptr()) << ": [";
if (id != nullptr) { if (id != nullptr) {
os << id; os << id;
} else { } else {
os << map().instance_type(); os << object.map().instance_type();
} }
os << "]"; os << "]";
if (ReadOnlyHeap::Contains(*this)) { if (ReadOnlyHeap::Contains(object)) {
os << " in ReadOnlySpace"; os << " in ReadOnlySpace";
} else if (GetHeapFromWritableObject(*this)->InOldSpace(*this)) { } else if (GetHeapFromWritableObject(object)->InOldSpace(object)) {
os << " in OldSpace"; os << " in OldSpace";
} }
}
} // namespace
void HeapObject::PrintHeader(std::ostream& os, const char* id) { // NOLINT
PrintHeapObjectHeaderWithoutMap(*this, os, id);
if (!IsMap()) os << "\n - map: " << Brief(map()); if (!IsMap()) os << "\n - map: " << Brief(map());
} }
...@@ -1046,6 +1055,8 @@ void JSMessageObject::JSMessageObjectPrint(std::ostream& os) { // NOLINT ...@@ -1046,6 +1055,8 @@ void JSMessageObject::JSMessageObjectPrint(std::ostream& os) { // NOLINT
} }
void String::StringPrint(std::ostream& os) { // NOLINT void String::StringPrint(std::ostream& os) { // NOLINT
PrintHeapObjectHeaderWithoutMap(*this, os, "String");
os << ": ";
os << PrefixForDebugPrint(); os << PrefixForDebugPrint();
PrintUC16(os, 0, length()); PrintUC16(os, 0, length());
os << SuffixForDebugPrint(); os << SuffixForDebugPrint();
......
...@@ -194,14 +194,14 @@ void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch( ...@@ -194,14 +194,14 @@ void InterpreterCompilationJob::CheckAndPrintBytecodeMismatch(
MaybeHandle<String> maybe_name = parse_info()->literal()->GetName(isolate); MaybeHandle<String> maybe_name = parse_info()->literal()->GetName(isolate);
Handle<String> name; Handle<String> name;
if (maybe_name.ToHandle(&name) && name->length() != 0) { if (maybe_name.ToHandle(&name) && name->length() != 0) {
name->StringPrint(std::cerr); name->PrintUC16(std::cerr);
} else { } else {
std::cerr << "anonymous"; std::cerr << "anonymous";
} }
Object script_name = script->GetNameOrSourceURL(); Object script_name = script->GetNameOrSourceURL();
if (script_name.IsString()) { if (script_name.IsString()) {
std::cerr << " "; std::cerr << " ";
String::cast(script_name).StringPrint(std::cerr); String::cast(script_name).PrintUC16(std::cerr);
std::cerr << ":" << parse_info()->literal()->start_position(); std::cerr << ":" << parse_info()->literal()->start_position();
} }
#endif #endif
......
...@@ -5802,7 +5802,7 @@ void Dictionary<Derived, Shape>::Print(std::ostream& os) { ...@@ -5802,7 +5802,7 @@ void Dictionary<Derived, Shape>::Print(std::ostream& os) {
if (!dictionary.ToKey(roots, i, &k)) continue; if (!dictionary.ToKey(roots, i, &k)) continue;
os << "\n "; os << "\n ";
if (k.IsString()) { if (k.IsString()) {
String::cast(k).StringPrint(os); String::cast(k).PrintUC16(os);
} else { } else {
os << Brief(k); os << Brief(k);
} }
......
...@@ -352,12 +352,20 @@ class String : public TorqueGeneratedString<String, Name> { ...@@ -352,12 +352,20 @@ class String : public TorqueGeneratedString<String, Name> {
// For use during stack traces. Performs rudimentary sanity check. // For use during stack traces. Performs rudimentary sanity check.
bool LooksValid(); bool LooksValid();
// Dispatched behavior. // Printing utility functions.
// - PrintUC16 prints the raw string contents to the given stream.
// Non-printable characters are formatted as hex, but otherwise the string
// is printed as-is.
// - StringShortPrint and StringPrint have extra formatting: they add a
// prefix and suffix depending on the string kind, may add other information
// such as the string heap object address, may truncate long strings, etc.
const char* PrefixForDebugPrint() const; const char* PrefixForDebugPrint() const;
const char* SuffixForDebugPrint() const; const char* SuffixForDebugPrint() const;
void StringShortPrint(StringStream* accumulator); 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); void PrintUC16(StringStream* accumulator, int start, int end);
// Dispatched behavior.
#if defined(DEBUG) || defined(OBJECT_PRINT) #if defined(DEBUG) || defined(OBJECT_PRINT)
char* ToAsciiArray(); char* ToAsciiArray();
#endif #endif
......
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