Skip to content

Commit 1faa880

Browse files
committed
src: v12.x-compatible DescriptorArray
V8 changed DescriptorArray from a FixedArray to a proper HeapObject. These changes update accessors for DescriptorArray fields to make them compatible with FixedArray-like and HeapObject-like access. Ref: #255 PR-URL: #330 Reviewed-By: Gireesh Punathil <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent 878b514 commit 1faa880

File tree

7 files changed

+137
-71
lines changed

7 files changed

+137
-71
lines changed

src/llscan.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,7 +1563,7 @@ bool FindJSObjectsVisitor::MapCacheEntry::Load(v8::Map map,
15631563
if (is_histogram) type_name = heap_object.GetTypeName(err);
15641564

15651565
v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
1566-
if (err.Fail()) return false;
1566+
RETURN_IF_INVALID(descriptors_obj, false);
15671567

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

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

src/llv8-constants.cc

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ void Map::Load() {
9595
"class_Map__constructor__Object");
9696
kInstanceDescriptorsOffset = LoadConstant({
9797
"class_Map__instance_descriptors__DescriptorArray",
98+
"class_Map__instance_descriptors_offset",
9899
});
99100
kBitField3Offset =
100101
LoadConstant("class_Map__bit_field3__int", "class_Map__bit_field3__SMI");
@@ -403,9 +404,9 @@ void JSArrayBufferView::Load() {
403404

404405

405406
void DescriptorArray::Load() {
406-
kDetailsOffset = LoadConstant("prop_desc_details");
407-
kKeyOffset = LoadConstant("prop_desc_key");
408-
kValueOffset = LoadConstant("prop_desc_value");
407+
kDetailsOffset = LoadConstant({"prop_desc_details"});
408+
kKeyOffset = LoadConstant({"prop_desc_key"});
409+
kValueOffset = LoadConstant({"prop_desc_value"});
409410

410411
kPropertyIndexMask = LoadConstant("prop_index_mask");
411412
kPropertyIndexShift = LoadConstant("prop_index_shift");
@@ -455,8 +456,12 @@ void DescriptorArray::Load() {
455456
kRepresentationDouble = 7;
456457
}
457458

458-
kFirstIndex = LoadConstant("prop_idx_first");
459-
kSize = LoadConstant("prop_desc_size");
459+
// NOTE(mmarchini): removed from V8 7.2.
460+
// https://github.com/v8/v8/commit/1ad0cd5
461+
kFirstIndex = LoadOptionalConstant({"prop_idx_first"}, 0);
462+
kSize = LoadConstant({"prop_desc_size"});
463+
kHeaderSize = LoadOptionalConstant(
464+
{"class_DescriptorArray__header_size__uintptr_t"}, 0);
460465
}
461466

462467

src/llv8-constants.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -406,9 +406,9 @@ class DescriptorArray : public Module {
406406
public:
407407
CONSTANTS_DEFAULT_METHODS(DescriptorArray);
408408

409-
int64_t kDetailsOffset;
410-
int64_t kKeyOffset;
411-
int64_t kValueOffset;
409+
Constant<int64_t> kDetailsOffset;
410+
Constant<int64_t> kKeyOffset;
411+
Constant<int64_t> kValueOffset;
412412

413413
int64_t kPropertyIndexMask;
414414
int64_t kPropertyIndexShift;
@@ -417,8 +417,10 @@ class DescriptorArray : public Module {
417417

418418
int64_t kRepresentationDouble;
419419

420-
int64_t kFirstIndex;
421-
int64_t kSize;
420+
Constant<int64_t> kFirstIndex;
421+
Constant<int64_t> kHeaderSize;
422+
Constant<int64_t> kSize;
423+
Constant<int64_t> kEntrySize;
422424

423425
// node.js <= 7
424426
int64_t kPropertyTypeMask = -1;

src/llv8-inl.h

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ inline bool Context::IsContext(LLV8* v8, HeapObject heap_object, Error& err) {
271271
}
272272

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

727-
inline Smi DescriptorArray::GetDetails(int index, Error& err) {
728-
return Get<Smi>(v8()->descriptor_array()->kFirstIndex +
729-
index * v8()->descriptor_array()->kSize +
730-
v8()->descriptor_array()->kDetailsOffset,
731-
err);
728+
template <class T>
729+
inline T DescriptorArray::Get(int index, int64_t offset) {
730+
// TODO(mmarchini): shouldn't need Error here.
731+
Error err;
732+
RETURN_IF_INVALID(v8()->descriptor_array()->kSize, T());
733+
734+
index = index * *(v8()->descriptor_array()->kSize);
735+
if (v8()->descriptor_array()->kFirstIndex.Loaded()) {
736+
return FixedArray::Get<T>(
737+
*(v8()->descriptor_array()->kFirstIndex) + index + offset, err);
738+
} else if (v8()->descriptor_array()->kHeaderSize.Loaded()) {
739+
index *= v8()->common()->kPointerSize;
740+
index += *(v8()->descriptor_array()->kHeaderSize);
741+
index += (v8()->common()->kPointerSize * offset);
742+
return LoadFieldValue<T>(index, err);
743+
} else {
744+
PRINT_DEBUG(
745+
"Missing FirstIndex and HeaderSize constants, can't get key from "
746+
"DescriptorArray");
747+
return T();
748+
}
749+
}
750+
751+
inline Smi DescriptorArray::GetDetails(int index) {
752+
RETURN_IF_INVALID(v8()->descriptor_array()->kDetailsOffset, Smi());
753+
return Get<Smi>(index, *v8()->descriptor_array()->kDetailsOffset);
732754
}
733755

734-
inline Value DescriptorArray::GetKey(int index, Error& err) {
735-
return Get<Value>(v8()->descriptor_array()->kFirstIndex +
736-
index * v8()->descriptor_array()->kSize +
737-
v8()->descriptor_array()->kKeyOffset,
738-
err);
756+
inline Value DescriptorArray::GetKey(int index) {
757+
RETURN_IF_INVALID(v8()->descriptor_array()->kKeyOffset, Value());
758+
return Get<Value>(index, *v8()->descriptor_array()->kKeyOffset);
739759
}
740760

741-
inline Value DescriptorArray::GetValue(int index, Error& err) {
742-
return Get<Value>(v8()->descriptor_array()->kFirstIndex +
743-
index * v8()->descriptor_array()->kSize +
744-
v8()->descriptor_array()->kValueOffset,
745-
err);
761+
inline Value DescriptorArray::GetValue(int index) {
762+
RETURN_IF_INVALID(v8()->descriptor_array()->kValueOffset, Value());
763+
return Get<Value>(index, *v8()->descriptor_array()->kValueOffset);
746764
}
747765

748766
inline bool DescriptorArray::IsDescriptorDetails(Smi details) {

src/llv8.cc

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,8 @@ std::string Value::GetTypeName(Error& err) {
571571

572572

573573
std::string Value::ToString(Error& err) {
574+
RETURN_IF_THIS_INVALID(std::string());
575+
574576
Smi smi(this);
575577
if (smi.Check()) return smi.ToString(err);
576578

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

927929
DescriptorArray descriptors(descriptors_obj);
928930

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

943945
std::vector<std::pair<Value, Value>> entries;
944946
for (int64_t i = 0; i < own_descriptors_count; i++) {
945-
Smi details = descriptors.GetDetails(i, err);
946-
if (err.Fail()) continue;
947+
Smi details = descriptors.GetDetails(i);
948+
if (!details.Check()) {
949+
PRINT_DEBUG("Failed to get details for index %ld", i);
950+
entries.push_back(std::pair<Value, Value>(Value(), Value()));
951+
continue;
952+
}
947953

948-
Value key = descriptors.GetKey(i, err);
949-
if (err.Fail()) continue;
954+
Value key = descriptors.GetKey(i);
955+
if (!key.Check()) continue;
950956

951957
if (descriptors.IsConstFieldDetails(details) ||
952958
descriptors.IsDescriptorDetails(details)) {
953959
Value value;
954960

955-
value = descriptors.GetValue(i, err);
956-
if (err.Fail()) continue;
961+
value = descriptors.GetValue(i);
962+
if (!value.Check()) continue;
957963

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

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

10461052
for (int64_t i = 0; i < own_descriptors_count; i++) {
1047-
Smi details = descriptors.GetDetails(i, err);
1048-
if (err.Fail()) return;
1053+
Smi details = descriptors.GetDetails(i);
1054+
if (!details.Check()) {
1055+
PRINT_DEBUG("Failed to get details for index %ld", i);
1056+
keys.push_back("???");
1057+
continue;
1058+
}
10491059

1050-
Value key = descriptors.GetKey(i, err);
1051-
if (err.Fail()) return;
1060+
Value key = descriptors.GetKey(i);
1061+
RETURN_IF_INVALID(key, );
10521062

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

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

11441154
for (int64_t i = 0; i < own_descriptors_count; i++) {
1145-
Smi details = descriptors.GetDetails(i, err);
1146-
if (err.Fail()) return Value();
1155+
Smi details = descriptors.GetDetails(i);
1156+
if (!details.Check()) {
1157+
PRINT_DEBUG("Failed to get details for index %ld", i);
1158+
continue;
1159+
}
11471160

1148-
Value key = descriptors.GetKey(i, err);
1149-
if (err.Fail()) return Value();
1161+
Value key = descriptors.GetKey(i);
1162+
RETURN_IF_INVALID(key, Value());
11501163

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

1162-
value = descriptors.GetValue(i, err);
1163-
if (err.Fail()) return Value();
1175+
value = descriptors.GetValue(i);
1176+
RETURN_IF_INVALID(value, Value());
11641177

11651178
continue;
11661179
}

src/llv8.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,11 +455,14 @@ class DescriptorArray : public FixedArray {
455455
public:
456456
V8_VALUE_DEFAULT_METHODS(DescriptorArray, FixedArray)
457457

458-
inline Smi GetDetails(int index, Error& err);
459-
inline Value GetKey(int index, Error& err);
458+
template <class T>
459+
inline T Get(int index, int64_t offset);
460+
461+
inline Smi GetDetails(int index);
462+
inline Value GetKey(int index);
460463

461464
// NOTE: Only for DATA_CONSTANT
462-
inline Value GetValue(int index, Error& err);
465+
inline Value GetValue(int index);
463466

464467
inline bool IsFieldDetails(Smi details);
465468
inline bool IsDescriptorDetails(Smi details);

src/printer.cc

Lines changed: 46 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -467,9 +467,7 @@ std::string Printer::Stringify(v8::JSArrayBufferView js_array_buffer_view,
467467

468468
template <>
469469
std::string Printer::Stringify(v8::Map map, Error& err) {
470-
v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
471-
if (err.Fail()) return std::string();
472-
470+
// TODO(mmarchini): don't fail if can't load NumberOfOwnDescriptors
473471
int64_t own_descriptors_count = map.NumberOfOwnDescriptors(err);
474472
if (err.Fail()) return std::string();
475473

@@ -492,25 +490,41 @@ std::string Printer::Stringify(v8::Map map, Error& err) {
492490
char tmp[256];
493491
std::stringstream ss;
494492
ss << rang::fg::yellow
495-
<< "<Map own_descriptors=%d %s=%d instance_size=%d "
496-
"descriptors=0x%016" PRIx64
497-
<< rang::fg::reset;
493+
<< "<Map own_descriptors=%d %s=%d instance_size=%d descriptors=";
494+
495+
// TODO(mmarchini): this should be a reusable method
496+
std::string descriptors_str = "???";
497+
v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
498+
if (descriptors_obj.Check()) {
499+
char descriptors_raw[50];
500+
snprintf(descriptors_raw, 50, "0x%016" PRIx64, descriptors_obj.raw());
501+
ss << descriptors_raw;
502+
} else {
503+
PRINT_DEBUG("Failed to load InstanceDescriptors");
504+
ss << rang::fg::red << "???";
505+
}
506+
507+
ss << rang::fg::reset;
498508

499509
snprintf(tmp, sizeof(tmp), ss.str().c_str(),
500510
static_cast<int>(own_descriptors_count),
501511
in_object_properties_or_constructor.c_str(),
502512
static_cast<int>(in_object_properties_or_constructor_index),
503-
static_cast<int>(instance_size), descriptors_obj.raw());
513+
static_cast<int>(instance_size));
504514

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

509-
v8::DescriptorArray descriptors(descriptors_obj);
510-
if (err.Fail()) return std::string();
519+
if (descriptors_obj.Check()) {
520+
v8::DescriptorArray descriptors(descriptors_obj);
521+
if (err.Fail()) return std::string();
511522

512-
return std::string(tmp) + ":" + Stringify<v8::FixedArray>(descriptors, err) +
513-
">";
523+
return std::string(tmp) + ":" +
524+
Stringify<v8::FixedArray>(descriptors, err) + ">";
525+
} else {
526+
std::string(tmp) + ">";
527+
}
514528
}
515529

516530
template <>
@@ -965,7 +979,7 @@ std::string Printer::StringifyDictionary(v8::JSObject js_object, Error& err) {
965979
std::string Printer::StringifyDescriptors(v8::JSObject js_object, v8::Map map,
966980
Error& err) {
967981
v8::HeapObject descriptors_obj = map.InstanceDescriptors(err);
968-
if (err.Fail()) return std::string();
982+
RETURN_IF_INVALID(descriptors_obj, std::string());
969983

970984
v8::DescriptorArray descriptors(descriptors_obj);
971985
int64_t own_descriptors_count = map.NumberOfOwnDescriptors(err);
@@ -987,26 +1001,37 @@ std::string Printer::StringifyDescriptors(v8::JSObject js_object, v8::Map map,
9871001
std::string res;
9881002
std::stringstream ss;
9891003
for (int64_t i = 0; i < own_descriptors_count; i++) {
990-
v8::Smi details = descriptors.GetDetails(i, err);
991-
if (err.Fail()) return std::string();
992-
993-
v8::Value key = descriptors.GetKey(i, err);
994-
if (err.Fail()) return std::string();
995-
9961004
if (!res.empty()) res += ",\n";
9971005

1006+
v8::Value key = descriptors.GetKey(i);
1007+
9981008
ss.str("");
9991009
ss.clear();
1000-
ss << rang::style::bold << rang::fg::yellow << " ." + key.ToString(err)
1001-
<< rang::fg::reset << rang::style::reset;
1010+
ss << rang::style::bold << rang::fg::yellow << " .";
1011+
if (key.Check()) {
1012+
ss << key.ToString(err);
1013+
} else {
1014+
PRINT_DEBUG("Failed to get key for index %ld", i);
1015+
ss << "???";
1016+
}
1017+
ss << rang::fg::reset << rang::style::reset;
1018+
10021019
res += ss.str() + "=";
10031020
if (err.Fail()) return std::string();
10041021

1022+
v8::Smi details = descriptors.GetDetails(i);
1023+
if (!details.Check()) {
1024+
PRINT_DEBUG("Failed to get details for index %ld", i);
1025+
res += "???";
1026+
continue;
1027+
}
1028+
10051029
if (descriptors.IsConstFieldDetails(details) ||
10061030
descriptors.IsDescriptorDetails(details)) {
10071031
v8::Value value;
10081032

1009-
value = descriptors.GetValue(i, err);
1033+
value = descriptors.GetValue(i);
1034+
RETURN_IF_INVALID(value, std::string());
10101035
if (err.Fail()) return std::string();
10111036

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

0 commit comments

Comments
 (0)