Skip to content

Commit 6238ada

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
1 parent 37b3c26 commit 6238ada

7 files changed

Lines changed: 139 additions & 49 deletions

File tree

src/llscan.cc

Lines changed: 1 addition & 1 deletion
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);

src/llv8-constants.cc

Lines changed: 7 additions & 3 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,7 +404,7 @@ void JSArrayBufferView::Load() {
403404

404405

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

@@ -455,8 +456,11 @@ 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({"class_DescriptorArray__header_size__uintptr_t"}, 0);
460464
}
461465

462466

src/llv8-constants.h

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

409-
int64_t kDetailsOffset;
409+
Constant<int64_t> kDetailsOffset;
410410
int64_t kKeyOffset;
411411
int64_t kValueOffset;
412412

@@ -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: 60 additions & 13 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,71 @@ 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+
inline Smi DescriptorArray::GetDetails(int index) {
729+
// TODO(mmarchini): shouldn't need Error here.
730+
Error err;
731+
RETURN_IF_INVALID(v8()->descriptor_array()->kFirstIndex, Smi());
732+
RETURN_IF_INVALID(v8()->descriptor_array()->kSize, Smi());
733+
RETURN_IF_INVALID(v8()->descriptor_array()->kDetailsOffset, Smi());
734+
735+
index = index * *(v8()->descriptor_array()->kSize);
736+
if (v8()->descriptor_array()->kFirstIndex.Loaded()) {
737+
return Get<Smi>(*(v8()->descriptor_array()->kFirstIndex) +
738+
index +
739+
*(v8()->descriptor_array()->kDetailsOffset),
740+
err);
741+
} else if (v8()->descriptor_array()->kHeaderSize.Loaded()) {
742+
index *= v8()->common()->kPointerSize;
743+
index += *(v8()->descriptor_array()->kHeaderSize);
744+
index += (v8()->common()->kPointerSize * *(v8()->descriptor_array()->kDetailsOffset));
745+
return LoadFieldValue<Smi>(index, err);
746+
} else {
747+
PRINT_DEBUG("Missing FirstIndex and HeaderSize constants, can't get key from DescriptorArray");
748+
return Smi();
749+
}
732750
}
733751

734752
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);
753+
RETURN_IF_INVALID(v8()->descriptor_array()->kFirstIndex, Smi());
754+
RETURN_IF_INVALID(v8()->descriptor_array()->kSize, Smi());
755+
756+
index = index * *(v8()->descriptor_array()->kSize);
757+
if (v8()->descriptor_array()->kFirstIndex.Loaded()) {
758+
// TODO(mmarchini): check on `Get`
759+
return Get<Value>(*(v8()->descriptor_array()->kFirstIndex) +
760+
index +
761+
v8()->descriptor_array()->kKeyOffset,
762+
err);
763+
} else if (v8()->descriptor_array()->kHeaderSize.Loaded()) {
764+
index *= v8()->common()->kPointerSize;
765+
index += *(v8()->descriptor_array()->kHeaderSize);
766+
index += v8()->descriptor_array()->kKeyOffset;
767+
return LoadFieldValue<Value>(index, err);
768+
} else {
769+
PRINT_DEBUG("Missing FirstIndex and HeaderSize constants, can't get key from DescriptorArray");
770+
return Value();
771+
}
739772
}
740773

741774
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);
775+
RETURN_IF_INVALID(v8()->descriptor_array()->kFirstIndex, Smi());
776+
RETURN_IF_INVALID(v8()->descriptor_array()->kSize, Smi());
777+
778+
index = index * *(v8()->descriptor_array()->kSize);
779+
if (v8()->descriptor_array()->kFirstIndex.Loaded()) {
780+
return Get<Value>(*(v8()->descriptor_array()->kFirstIndex) +
781+
index +
782+
v8()->descriptor_array()->kValueOffset,
783+
err);
784+
} else if (v8()->descriptor_array()->kHeaderSize.Loaded()) {
785+
index *= v8()->common()->kPointerSize;
786+
index += *(v8()->descriptor_array()->kHeaderSize);
787+
index += (v8()->common()->kPointerSize * v8()->descriptor_array()->kValueOffset);
788+
return LoadFieldValue<Value>(index, err);
789+
} else {
790+
PRINT_DEBUG("Missing FirstIndex and HeaderSize constants, can't get key from DescriptorArray");
791+
return Value();
792+
}
746793
}
747794

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

src/llv8.cc

Lines changed: 22 additions & 9 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,8 +944,12 @@ 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

948954
Value key = descriptors.GetKey(i, err);
949955
if (err.Fail()) continue;
@@ -1037,15 +1043,19 @@ 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

10501060
Value key = descriptors.GetKey(i, err);
10511061
if (err.Fail()) return;
@@ -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,8 +1152,11 @@ 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

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

src/llv8.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ class DescriptorArray : public FixedArray {
455455
public:
456456
V8_VALUE_DEFAULT_METHODS(DescriptorArray, FixedArray)
457457

458-
inline Smi GetDetails(int index, Error& err);
458+
inline Smi GetDetails(int index);
459459
inline Value GetKey(int index, Error& err);
460460

461461
// NOTE: Only for DATA_CONSTANT

src/printer.cc

Lines changed: 43 additions & 19 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) + ":" + Stringify<v8::FixedArray>(descriptors, err) +
524+
">";
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,21 +1001,31 @@ 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();
1004+
if (!res.empty()) res += ",\n";
9921005

9931006
v8::Value key = descriptors.GetKey(i, err);
994-
if (err.Fail()) return std::string();
995-
996-
if (!res.empty()) res += ",\n";
9971007

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;

0 commit comments

Comments
 (0)