Skip to content

Commit

Permalink
src: support thin strings
Browse files Browse the repository at this point in the history
Fixes: nodejs#117
  • Loading branch information
joyeecheung committed Aug 16, 2017
1 parent bf416f1 commit 1ce2a40
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 9 deletions.
3 changes: 2 additions & 1 deletion src/llnode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ bool BacktraceCmd::DoExecute(SBDebugger d, char** cmd,
lldb::SBMemoryRegionInfo info;
if (target.GetProcess().GetMemoryRegionInfo(pc, info).Success() &&
info.IsExecutable() && info.IsWritable()) {
result.Printf(" %c frame #%u: 0x%016" PRIx64 " <builtin>\n", star, i, pc);
result.Printf(" %c frame #%u: 0x%016" PRIx64 " <builtin>\n", star, i,
pc);
continue;
}
}
Expand Down
16 changes: 16 additions & 0 deletions src/llscan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,14 @@ void FindReferencesCmd::ReferenceScanner::PrintRefs(
result.Printf("0x%" PRIx64 ": %s.%s=0x%" PRIx64 "\n", str.raw(),
type_name.c_str(), "<Second>", search_value_.raw());
}
} else if (repr == v8->string()->kThinStringTag) {
v8::ThinString thin_str(str);
v8::String actual = thin_str.Actual(err);
if (err.Success() && actual.raw() == search_value_.raw()) {
std::string type_name = thin_str.GetTypeName(err);
result.Printf("0x%" PRIx64 ": %s.%s=0x%" PRIx64 "\n", str.raw(),
type_name.c_str(), "<Actual>", search_value_.raw());
}
}
// Nothing to do for other kinds of string.
}
Expand Down Expand Up @@ -694,6 +702,14 @@ void FindReferencesCmd::ReferenceScanner::ScanRefs(v8::String& str,
references = llscan.GetReferencesByValue(second.raw());
references->push_back(str.raw());
}
} else if (repr == v8->string()->kThinStringTag) {
v8::ThinString thin_str(str);
v8::String actual = thin_str.Actual(err);

if (err.Success()) {
references = llscan.GetReferencesByValue(actual.raw());
references->push_back(str.raw());
}
}
// Nothing to do for other kinds of string.
}
Expand Down
4 changes: 4 additions & 0 deletions src/llv8-constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ void String::Load() {
kConsStringTag = LoadConstant("ConsStringTag");
kSlicedStringTag = LoadConstant("SlicedStringTag");
kExternalStringTag = LoadConstant("ExternalStringTag");
kThinStringTag = LoadConstant("ThinStringTag");

kLengthOffset = LoadConstant("class_String__length__SMI");
}
Expand Down Expand Up @@ -362,6 +363,9 @@ void SlicedString::Load() {
kOffsetOffset = LoadConstant("class_SlicedString__offset__SMI");
}

void ThinString::Load() {
kActualOffset = LoadConstant("class_ThinString__actual__String");
}

void FixedArrayBase::Load() {
kLengthOffset = LoadConstant("class_FixedArrayBase__length__SMI");
Expand Down
11 changes: 11 additions & 0 deletions src/llv8-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ class String : public Module {
int64_t kConsStringTag;
int64_t kSlicedStringTag;
int64_t kExternalStringTag;
int64_t kThinStringTag;

int64_t kLengthOffset;

Expand Down Expand Up @@ -297,6 +298,16 @@ class SlicedString : public Module {
void Load();
};

class ThinString : public Module {
public:
MODULE_DEFAULT_METHODS(ThinString);

int64_t kActualOffset;

protected:
void Load();
};

class FixedArrayBase : public Module {
public:
MODULE_DEFAULT_METHODS(FixedArrayBase);
Expand Down
12 changes: 12 additions & 0 deletions src/llv8-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ ACCESSOR(ConsString, Second, cons_string()->kSecondOffset, String);
ACCESSOR(SlicedString, Parent, sliced_string()->kParentOffset, String);
ACCESSOR(SlicedString, Offset, sliced_string()->kOffsetOffset, Smi);

ACCESSOR(ThinString, Actual, thin_string()->kActualOffset, String);

ACCESSOR(FixedArrayBase, Length, fixed_array_base()->kLengthOffset, Smi);

inline std::string OneByteString::ToString(Error& err) {
Expand Down Expand Up @@ -319,6 +321,16 @@ inline std::string SlicedString::ToString(Error& err) {
return tmp.substr(offset.GetValue(), length.GetValue());
}

inline std::string ThinString::ToString(Error& err) {
String actual = Actual(err);
if (err.Fail()) return std::string();

std::string tmp = actual.ToString(err);
if (err.Fail()) return std::string();

return tmp;
}

inline int64_t FixedArray::LeaData() const {
return LeaField(v8()->fixed_array()->kDataOffset);
}
Expand Down
19 changes: 12 additions & 7 deletions src/llv8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include <algorithm>
#include <cinttypes>
#include <algorithm>

#include "llv8-inl.h"
#include "llv8.h"
Expand Down Expand Up @@ -43,6 +42,7 @@ void LLV8::Load(SBTarget target) {
two_byte_string.Assign(target, &common);
cons_string.Assign(target, &common);
sliced_string.Assign(target, &common);
thin_string.Assign(target, &common);
fixed_array_base.Assign(target, &common);
fixed_array.Assign(target, &common);
oddball.Assign(target, &common);
Expand Down Expand Up @@ -90,8 +90,7 @@ double LLV8::LoadDouble(int64_t addr, Error& err) {
std::string LLV8::LoadBytes(int64_t length, int64_t addr, Error& err) {
uint8_t* buf = new uint8_t[length + 1];
SBError sberr;
process_.ReadMemory(addr, buf,
static_cast<size_t>(length), sberr);
process_.ReadMemory(addr, buf, static_cast<size_t>(length), sberr);
if (sberr.Fail()) {
err = Error::Failure("Failed to load V8 raw buffer");
delete[] buf;
Expand Down Expand Up @@ -957,6 +956,11 @@ std::string String::ToString(Error& err) {
return std::string("(external)");
}

if (repr == v8()->string()->kThinStringTag) {
ThinString thin(this);
return thin.ToString(err);
}

err = Error::Failure("Unsupported string representation");
return std::string();
}
Expand Down Expand Up @@ -1111,9 +1115,9 @@ std::string JSArrayBuffer::Inspect(InspectOptions* options, Error& err) {

char tmp[128];
snprintf(tmp, sizeof(tmp),
"<ArrayBuffer: backingStore=0x%016" PRIx64 ", byteLength=%d",
data, byte_length);
"<ArrayBuffer: backingStore=0x%016" PRIx64 ", byteLength=%d", data,
byte_length);

std::string res;
res += tmp;
if (options->detailed) {
Expand Down Expand Up @@ -1156,7 +1160,8 @@ std::string JSArrayBufferView::Inspect(InspectOptions* options, Error& err) {
int byte_offset = static_cast<int>(off.GetValue());
char tmp[128];
snprintf(tmp, sizeof(tmp),
"<ArrayBufferView: backingStore=0x%016" PRIx64 ", byteOffset=%d, byteLength=%d",
"<ArrayBufferView: backingStore=0x%016" PRIx64
", byteOffset=%d, byteLength=%d",
data, byte_offset, byte_length);

std::string res;
Expand Down
12 changes: 11 additions & 1 deletion src/llv8.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,15 @@ class SlicedString : public String {
inline std::string ToString(Error& err);
};

class ThinString : public String {
public:
V8_VALUE_DEFAULT_METHODS(ThinString, String)

inline String Actual(Error& err);

inline std::string ToString(Error& err);
};

class HeapNumber : public HeapObject {
public:
V8_VALUE_DEFAULT_METHODS(HeapNumber, HeapObject)
Expand Down Expand Up @@ -405,7 +414,6 @@ class JSArrayBuffer : public HeapObject {
inline bool WasNeutered(Error& err);

std::string Inspect(InspectOptions* options, Error& err);

};

class JSArrayBufferView : public HeapObject {
Expand Down Expand Up @@ -477,6 +485,7 @@ class LLV8 {
constants::TwoByteString two_byte_string;
constants::ConsString cons_string;
constants::SlicedString sliced_string;
constants::ThinString thin_string;
constants::FixedArrayBase fixed_array_base;
constants::FixedArray fixed_array;
constants::Oddball oddball;
Expand All @@ -503,6 +512,7 @@ class LLV8 {
friend class TwoByteString;
friend class ConsString;
friend class SlicedString;
friend class ThinString;
friend class HeapNumber;
friend class JSObject;
friend class JSArray;
Expand Down
10 changes: 10 additions & 0 deletions test/fixtures/inspect-scenario.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ let outerVar = 'outer variable';

exports.holder = {};

function makeThin(a, b) {
var str = a + b;
var obj = {};
obj[str]; // Turn the cons string into a thin string.
return str;
}

function closure() {

function Class() {
Expand All @@ -28,6 +35,9 @@ function closure() {
c.hashmap['cons-string'] =
'this could be a bit smaller, but v8 wants big str.';
c.hashmap['cons-string'] += c.hashmap['cons-string'];
c.hashmap['internalized-string'] = 'foobar';
// This thin string points to the previous 'foobar'.
c.hashmap['thin-string'] = makeThin('foo', 'bar');
c.hashmap['array'] = [true, 1, undefined, null, 'test', Class];
c.hashmap['long-array'] = new Array(20).fill(5);
c.hashmap['array-buffer'] = new Uint8Array(
Expand Down
15 changes: 15 additions & 0 deletions test/inspect-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ tape('v8 inspect', (t) => {

let regexp = null;
let cons = null;
let thin = null;
let arrowFunc = null;
let array = null;
let longArray = null;
Expand Down Expand Up @@ -112,6 +113,11 @@ tape('v8 inspect', (t) => {
t.ok(consMatch, '.cons-string ConsString property');
cons = consMatch[1];

const thinMatch = lines.match(
/.thin-string=(0x[0-9a-f]+):<String: "foobar">/);
t.ok(thinMatch, '.thin-string ThinString property');
thin = thinMatch[1];

sess.send(`v8 inspect ${regexp}`);
sess.send(`v8 inspect -F ${cons}`);
});
Expand Down Expand Up @@ -141,6 +147,15 @@ tape('v8 inspect', (t) => {
-1,
'--string-length truncates the string');

sess.send(`v8 inspect ${thin}`);
});

sess.linesUntil(/">/, (lines) => {
lines = lines.join('\n');
t.ok(
/0x[0-9a-f]+:<String: "foobar">/.test(lines),
'thin string content');

sess.send(`v8 inspect ${array}`);
});

Expand Down

0 comments on commit 1ce2a40

Please sign in to comment.