Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: v12.x-compatible DescriptorArray #325

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/llscan.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1563,7 +1563,7 @@ bool FindJSObjectsVisitor::MapCacheEntry::Load(v8::Map map,
if (is_histogram) type_name = heap_object.GetTypeName(err);

v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
if (err.Fail()) return false;
RETURN_IF_INVALID(descriptors_obj, false);

v8::DescriptorArray descriptors(descriptors_obj);
own_descriptors_count_ = map.NumberOfOwnDescriptors(err);
Expand All @@ -1579,8 +1579,8 @@ bool FindJSObjectsVisitor::MapCacheEntry::Load(v8::Map map,
}

for (uint64_t i = 0; i < own_descriptors_count_; i++) {
v8::Value key = descriptors.GetKey(i, err);
if (err.Fail()) continue;
v8::Value key = descriptors.GetKey(i);
if (!key.Check()) continue;
properties_.emplace_back(key.ToString(err));
}

Expand Down
15 changes: 10 additions & 5 deletions src/llv8-constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ void Map::Load() {
"class_Map__constructor__Object");
kInstanceDescriptorsOffset = LoadConstant({
"class_Map__instance_descriptors__DescriptorArray",
"class_Map__instance_descriptors_offset",
});
kBitField3Offset =
LoadConstant("class_Map__bit_field3__int", "class_Map__bit_field3__SMI");
Expand Down Expand Up @@ -403,9 +404,9 @@ void JSArrayBufferView::Load() {


void DescriptorArray::Load() {
kDetailsOffset = LoadConstant("prop_desc_details");
kKeyOffset = LoadConstant("prop_desc_key");
kValueOffset = LoadConstant("prop_desc_value");
kDetailsOffset = LoadConstant({"prop_desc_details"});
kKeyOffset = LoadConstant({"prop_desc_key"});
kValueOffset = LoadConstant({"prop_desc_value"});

kPropertyIndexMask = LoadConstant("prop_index_mask");
kPropertyIndexShift = LoadConstant("prop_index_shift");
Expand Down Expand Up @@ -455,8 +456,12 @@ void DescriptorArray::Load() {
kRepresentationDouble = 7;
}

kFirstIndex = LoadConstant("prop_idx_first");
kSize = LoadConstant("prop_desc_size");
// NOTE(mmarchini): removed from V8 7.2.
// https://github.com/v8/v8/commit/1ad0cd5
kFirstIndex = LoadOptionalConstant({"prop_idx_first"}, 0);
kSize = LoadConstant({"prop_desc_size"});
kHeaderSize = LoadOptionalConstant(
{"class_DescriptorArray__header_size__uintptr_t"}, 0);
}


Expand Down
12 changes: 7 additions & 5 deletions src/llv8-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,9 +406,9 @@ class DescriptorArray : public Module {
public:
CONSTANTS_DEFAULT_METHODS(DescriptorArray);

int64_t kDetailsOffset;
int64_t kKeyOffset;
int64_t kValueOffset;
Constant<int64_t> kDetailsOffset;
Constant<int64_t> kKeyOffset;
Constant<int64_t> kValueOffset;

int64_t kPropertyIndexMask;
int64_t kPropertyIndexShift;
Expand All @@ -417,8 +417,10 @@ class DescriptorArray : public Module {

int64_t kRepresentationDouble;

int64_t kFirstIndex;
int64_t kSize;
Constant<int64_t> kFirstIndex;
Constant<int64_t> kHeaderSize;
Constant<int64_t> kSize;
Constant<int64_t> kEntrySize;

// node.js <= 7
int64_t kPropertyTypeMask = -1;
Expand Down
48 changes: 33 additions & 15 deletions src/llv8-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ inline bool Context::IsContext(LLV8* v8, HeapObject heap_object, Error& err) {
}

inline int64_t Map::InObjectProperties(Error& err) {
RETURN_IF_THIS_INVALID(-1);
if (!IsJSObjectMap(err)) {
err = Error::Failure(
"Invalid call to Map::InObjectProperties with a non-JsObject type");
Expand Down Expand Up @@ -724,25 +725,42 @@ inline T FixedArray::Get(int index, Error& err) {
return LoadFieldValue<T>(off, err);
}

inline Smi DescriptorArray::GetDetails(int index, Error& err) {
return Get<Smi>(v8()->descriptor_array()->kFirstIndex +
index * v8()->descriptor_array()->kSize +
v8()->descriptor_array()->kDetailsOffset,
err);
template <class T>
inline T DescriptorArray::Get(int index, int64_t offset) {
// TODO(mmarchini): shouldn't need Error here.
Error err;
RETURN_IF_INVALID(v8()->descriptor_array()->kSize, T());

index = index * *(v8()->descriptor_array()->kSize);
if (v8()->descriptor_array()->kFirstIndex.Loaded()) {
return FixedArray::Get<T>(
*(v8()->descriptor_array()->kFirstIndex) + index + offset, err);
} else if (v8()->descriptor_array()->kHeaderSize.Loaded()) {
index *= v8()->common()->kPointerSize;
index += *(v8()->descriptor_array()->kHeaderSize);
index += (v8()->common()->kPointerSize * offset);
return LoadFieldValue<T>(index, err);
} else {
PRINT_DEBUG(
"Missing FirstIndex and HeaderSize constants, can't get key from "
"DescriptorArray");
return T();
}
}

inline Smi DescriptorArray::GetDetails(int index) {
RETURN_IF_INVALID(v8()->descriptor_array()->kDetailsOffset, Smi());
return Get<Smi>(index, *v8()->descriptor_array()->kDetailsOffset);
}

inline Value DescriptorArray::GetKey(int index, Error& err) {
return Get<Value>(v8()->descriptor_array()->kFirstIndex +
index * v8()->descriptor_array()->kSize +
v8()->descriptor_array()->kKeyOffset,
err);
inline Value DescriptorArray::GetKey(int index) {
RETURN_IF_INVALID(v8()->descriptor_array()->kKeyOffset, Value());
return Get<Value>(index, *v8()->descriptor_array()->kKeyOffset);
}

inline Value DescriptorArray::GetValue(int index, Error& err) {
return Get<Value>(v8()->descriptor_array()->kFirstIndex +
index * v8()->descriptor_array()->kSize +
v8()->descriptor_array()->kValueOffset,
err);
inline Value DescriptorArray::GetValue(int index) {
RETURN_IF_INVALID(v8()->descriptor_array()->kValueOffset, Value());
return Get<Value>(index, *v8()->descriptor_array()->kValueOffset);
}

inline bool DescriptorArray::IsDescriptorDetails(Smi details) {
Expand Down
51 changes: 32 additions & 19 deletions src/llv8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,8 @@ std::string Value::GetTypeName(Error& err) {


std::string Value::ToString(Error& err) {
RETURN_IF_THIS_INVALID(std::string());

Smi smi(this);
if (smi.Check()) return smi.ToString(err);

Expand Down Expand Up @@ -922,7 +924,7 @@ std::vector<std::pair<Value, Value>> JSObject::DictionaryEntries(Error& err) {
std::vector<std::pair<Value, Value>> JSObject::DescriptorEntries(Map map,
Error& err) {
HeapObject descriptors_obj = map.InstanceDescriptors(err);
if (err.Fail()) return {};
RETURN_IF_INVALID(descriptors_obj, {});

DescriptorArray descriptors(descriptors_obj);

Expand All @@ -942,18 +944,22 @@ std::vector<std::pair<Value, Value>> JSObject::DescriptorEntries(Map map,

std::vector<std::pair<Value, Value>> entries;
for (int64_t i = 0; i < own_descriptors_count; i++) {
Smi details = descriptors.GetDetails(i, err);
if (err.Fail()) continue;
Smi details = descriptors.GetDetails(i);
if (!details.Check()) {
PRINT_DEBUG("Failed to get details for index %ld", i);
entries.push_back(std::pair<Value, Value>(Value(), Value()));
continue;
}

Value key = descriptors.GetKey(i, err);
if (err.Fail()) continue;
Value key = descriptors.GetKey(i);
if (!key.Check()) continue;

if (descriptors.IsConstFieldDetails(details) ||
descriptors.IsDescriptorDetails(details)) {
Value value;

value = descriptors.GetValue(i, err);
if (err.Fail()) continue;
value = descriptors.GetValue(i);
if (!value.Check()) continue;

entries.push_back(std::pair<Value, Value>(key, value));
continue;
Expand Down Expand Up @@ -1037,18 +1043,22 @@ void JSObject::DictionaryKeys(std::vector<std::string>& keys, Error& err) {
void JSObject::DescriptorKeys(std::vector<std::string>& keys, Map map,
Error& err) {
HeapObject descriptors_obj = map.InstanceDescriptors(err);
if (err.Fail()) return;
RETURN_IF_INVALID(descriptors_obj, );

DescriptorArray descriptors(descriptors_obj);
int64_t own_descriptors_count = map.NumberOfOwnDescriptors(err);
if (err.Fail()) return;

for (int64_t i = 0; i < own_descriptors_count; i++) {
Smi details = descriptors.GetDetails(i, err);
if (err.Fail()) return;
Smi details = descriptors.GetDetails(i);
if (!details.Check()) {
PRINT_DEBUG("Failed to get details for index %ld", i);
keys.push_back("???");
continue;
}

Value key = descriptors.GetKey(i, err);
if (err.Fail()) return;
Value key = descriptors.GetKey(i);
RETURN_IF_INVALID(key, );

// Skip non-fields for now, Object.keys(obj) does
// not seem to return these (for example the "length"
Expand Down Expand Up @@ -1124,7 +1134,7 @@ Value JSObject::GetDictionaryProperty(std::string key_name, Error& err) {
Value JSObject::GetDescriptorProperty(std::string key_name, Map map,
Error& err) {
HeapObject descriptors_obj = map.InstanceDescriptors(err);
if (err.Fail()) return Value();
RETURN_IF_INVALID(descriptors_obj, Value());

DescriptorArray descriptors(descriptors_obj);
int64_t own_descriptors_count = map.NumberOfOwnDescriptors(err);
Expand All @@ -1142,11 +1152,14 @@ Value JSObject::GetDescriptorProperty(std::string key_name, Map map,
FixedArray extra_properties(extra_properties_obj);

for (int64_t i = 0; i < own_descriptors_count; i++) {
Smi details = descriptors.GetDetails(i, err);
if (err.Fail()) return Value();
Smi details = descriptors.GetDetails(i);
if (!details.Check()) {
PRINT_DEBUG("Failed to get details for index %ld", i);
continue;
}

Value key = descriptors.GetKey(i, err);
if (err.Fail()) return Value();
Value key = descriptors.GetKey(i);
RETURN_IF_INVALID(key, Value());

if (key.ToString(err) != key_name) {
continue;
Expand All @@ -1159,8 +1172,8 @@ Value JSObject::GetDescriptorProperty(std::string key_name, Map map,
descriptors.IsDescriptorDetails(details)) {
Value value;

value = descriptors.GetValue(i, err);
if (err.Fail()) return Value();
value = descriptors.GetValue(i);
RETURN_IF_INVALID(value, Value());

continue;
}
Expand Down
9 changes: 6 additions & 3 deletions src/llv8.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,11 +455,14 @@ class DescriptorArray : public FixedArray {
public:
V8_VALUE_DEFAULT_METHODS(DescriptorArray, FixedArray)

inline Smi GetDetails(int index, Error& err);
inline Value GetKey(int index, Error& err);
template <class T>
inline T Get(int index, int64_t offset);

inline Smi GetDetails(int index);
inline Value GetKey(int index);

// NOTE: Only for DATA_CONSTANT
inline Value GetValue(int index, Error& err);
inline Value GetValue(int index);

inline bool IsFieldDetails(Smi details);
inline bool IsDescriptorDetails(Smi details);
Expand Down
67 changes: 46 additions & 21 deletions src/printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -467,9 +467,7 @@ std::string Printer::Stringify(v8::JSArrayBufferView js_array_buffer_view,

template <>
std::string Printer::Stringify(v8::Map map, Error& err) {
v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
if (err.Fail()) return std::string();

// TODO(mmarchini): don't fail if can't load NumberOfOwnDescriptors
int64_t own_descriptors_count = map.NumberOfOwnDescriptors(err);
if (err.Fail()) return std::string();

Expand All @@ -492,25 +490,41 @@ std::string Printer::Stringify(v8::Map map, Error& err) {
char tmp[256];
std::stringstream ss;
ss << rang::fg::yellow
<< "<Map own_descriptors=%d %s=%d instance_size=%d "
"descriptors=0x%016" PRIx64
<< rang::fg::reset;
<< "<Map own_descriptors=%d %s=%d instance_size=%d descriptors=";

// TODO(mmarchini): this should be a reusable method
std::string descriptors_str = "???";
v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
if (descriptors_obj.Check()) {
char descriptors_raw[50];
snprintf(descriptors_raw, 50, "0x%016" PRIx64, descriptors_obj.raw());
ss << descriptors_raw;
} else {
PRINT_DEBUG("Failed to load InstanceDescriptors");
ss << rang::fg::red << "???";
}

ss << rang::fg::reset;

snprintf(tmp, sizeof(tmp), ss.str().c_str(),
static_cast<int>(own_descriptors_count),
in_object_properties_or_constructor.c_str(),
static_cast<int>(in_object_properties_or_constructor_index),
static_cast<int>(instance_size), descriptors_obj.raw());
static_cast<int>(instance_size));

if (!options_.detailed) {
return std::string(tmp) + ">";
}

v8::DescriptorArray descriptors(descriptors_obj);
if (err.Fail()) return std::string();
if (descriptors_obj.Check()) {
v8::DescriptorArray descriptors(descriptors_obj);
if (err.Fail()) return std::string();

return std::string(tmp) + ":" + Stringify<v8::FixedArray>(descriptors, err) +
">";
return std::string(tmp) + ":" +
Stringify<v8::FixedArray>(descriptors, err) + ">";
} else {
std::string(tmp) + ">";
}
}

template <>
Expand Down Expand Up @@ -965,7 +979,7 @@ std::string Printer::StringifyDictionary(v8::JSObject js_object, Error& err) {
std::string Printer::StringifyDescriptors(v8::JSObject js_object, v8::Map map,
Error& err) {
v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
if (err.Fail()) return std::string();
RETURN_IF_INVALID(descriptors_obj, std::string());

v8::DescriptorArray descriptors(descriptors_obj);
int64_t own_descriptors_count = map.NumberOfOwnDescriptors(err);
Expand All @@ -987,26 +1001,37 @@ std::string Printer::StringifyDescriptors(v8::JSObject js_object, v8::Map map,
std::string res;
std::stringstream ss;
for (int64_t i = 0; i < own_descriptors_count; i++) {
v8::Smi details = descriptors.GetDetails(i, err);
if (err.Fail()) return std::string();

v8::Value key = descriptors.GetKey(i, err);
if (err.Fail()) return std::string();

if (!res.empty()) res += ",\n";

v8::Value key = descriptors.GetKey(i);

ss.str("");
ss.clear();
ss << rang::style::bold << rang::fg::yellow << " ." + key.ToString(err)
<< rang::fg::reset << rang::style::reset;
ss << rang::style::bold << rang::fg::yellow << " .";
if (key.Check()) {
ss << key.ToString(err);
} else {
PRINT_DEBUG("Failed to get key for index %ld", i);
ss << "???";
}
ss << rang::fg::reset << rang::style::reset;

res += ss.str() + "=";
if (err.Fail()) return std::string();

v8::Smi details = descriptors.GetDetails(i);
if (!details.Check()) {
PRINT_DEBUG("Failed to get details for index %ld", i);
res += "???";
continue;
}

if (descriptors.IsConstFieldDetails(details) ||
descriptors.IsDescriptorDetails(details)) {
v8::Value value;

value = descriptors.GetValue(i, err);
value = descriptors.GetValue(i);
RETURN_IF_INVALID(value, std::string());
if (err.Fail()) return std::string();

res += printer.Stringify(value, err);
Expand Down