Skip to content

Commit 7f1e791

Browse files
author
Matheus Marchini
authored
src: fix object inspection for V8 6.4 (#192)
V8 6.4 "replaces the in-object properties count byte in the map with the byte that stores the start offset of in-object properties". Object inspection on llnode relies on in-object properties being count bytes, so these are minimal changes to make object inspection work again with V8 6.4 while keeping compatibility with previous versions. Ref: https://chromium-review.googlesource.com/c/v8/v8/+/776720 Fixes: #158
1 parent 7ae0dee commit 7f1e791

File tree

5 files changed

+60
-5
lines changed

5 files changed

+60
-5
lines changed

src/llv8-constants.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,11 +204,12 @@ void Map::Load() {
204204
"class_Map__inobject_properties_or_constructor_function_index__int",
205205
"class_Map__inobject_properties__int");
206206
if (kInObjectPropertiesOffset == -1) {
207-
kInObjectPropertiesOffset = LoadConstant(
207+
kInObjectPropertiesStartOffset = LoadConstant(
208208
"class_Map__inobject_properties_start_or_constructor_function_index__"
209209
"char");
210210
}
211211

212+
kInstanceTypeOffset = LoadConstant("class_Map__instance_type__uint16_t");
212213
kInstanceSizeOffset = LoadConstant("class_Map__instance_size__int",
213214
"class_Map__instance_size_in_words__char");
214215
kDictionaryMapShift = LoadConstant("bit_field3_dictionary_map_shift",
@@ -574,6 +575,8 @@ void Frame::Load() {
574575

575576
void Types::Load() {
576577
kFirstNonstringType = LoadConstant("FirstNonstringType");
578+
kFirstJSObjectType =
579+
LoadConstant("type_JSGlobalObject__JS_GLOBAL_OBJECT_TYPE");
577580

578581
kHeapNumberType = LoadConstant("type_HeapNumber__HEAP_NUMBER_TYPE");
579582
kMapType = LoadConstant("type_Map__MAP_TYPE");

src/llv8-constants.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ class Map : public Module {
9494
int64_t kInstanceDescriptorsOffset;
9595
int64_t kBitField3Offset;
9696
int64_t kInObjectPropertiesOffset;
97+
int64_t kInObjectPropertiesStartOffset;
9798
int64_t kInstanceSizeOffset;
99+
int64_t kInstanceTypeOffset;
98100

99101
int64_t kNumberOfOwnDescriptorsMask;
100102
int64_t kNumberOfOwnDescriptorsShift;
@@ -479,6 +481,7 @@ class Types : public Module {
479481
MODULE_DEFAULT_METHODS(Types);
480482

481483
int64_t kFirstNonstringType;
484+
int64_t kFirstJSObjectType;
482485

483486
int64_t kHeapNumberType;
484487
int64_t kMapType;

src/llv8-inl.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,44 @@ inline int64_t Map::BitField3(Error& err) {
159159
return v8()->LoadUnsigned(LeaField(v8()->map()->kBitField3Offset), 4, err);
160160
}
161161

162+
inline int64_t Map::InstanceType(Error& err) {
163+
return v8()->LoadUnsigned(LeaField(v8()->map()->kInstanceTypeOffset), 2, err);
164+
}
165+
166+
inline bool Map::IsJSObjectMap(Error& err) {
167+
return InstanceType(err) >= v8()->types()->kFirstJSObjectType;
168+
}
169+
170+
162171
inline int64_t Map::InObjectProperties(Error& err) {
163-
return LoadField(v8()->map()->kInObjectPropertiesOffset, err) & 0xff;
172+
if (!IsJSObjectMap(err)) {
173+
err = Error::Failure(
174+
"Invalid call to Map::InObjectProperties with a non-JsObject type");
175+
return 0;
176+
}
177+
if (v8()->map()->kInObjectPropertiesOffset != -1) {
178+
return LoadField(v8()->map()->kInObjectPropertiesOffset, err) & 0xff;
179+
} else {
180+
// NOTE(mmarchini): V8 6.4 changed semantics for
181+
// in_objects_properties_offset (see
182+
// https://chromium-review.googlesource.com/c/v8/v8/+/776720). To keep
183+
// changes to a minimum on llnode and to comply with V8, we're using the
184+
// same implementation from
185+
// https://chromium-review.googlesource.com/c/v8/v8/+/776720/9/src/objects-inl.h#3027.
186+
int64_t in_object_properties_start_offset =
187+
LoadField(v8()->map()->kInObjectPropertiesStartOffset, err) & 0xff;
188+
int64_t instance_size =
189+
v8()->LoadUnsigned(LeaField(v8()->map()->kInstanceSizeOffset), 1, err);
190+
return instance_size - in_object_properties_start_offset;
191+
}
192+
}
193+
194+
inline int64_t Map::ConstructorFunctionIndex(Error& err) {
195+
if (v8()->map()->kInObjectPropertiesOffset != -1) {
196+
return LoadField(v8()->map()->kInObjectPropertiesOffset, err) & 0xff;
197+
} else {
198+
return LoadField(v8()->map()->kInObjectPropertiesStartOffset, err) & 0xff;
199+
}
164200
}
165201

166202
inline int64_t Map::InstanceSize(Error& err) {

src/llv8.cc

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,18 +1278,28 @@ std::string Map::Inspect(InspectOptions* options, Error& err) {
12781278
int64_t own_descriptors_count = NumberOfOwnDescriptors(err);
12791279
if (err.Fail()) return std::string();
12801280

1281-
int64_t in_object_properties = InObjectProperties(err);
1281+
std::string in_object_properties_or_constructor;
1282+
int64_t in_object_properties_or_constructor_index;
1283+
if (IsJSObjectMap(err)) {
1284+
if (err.Fail()) return std::string();
1285+
in_object_properties_or_constructor_index = InObjectProperties(err);
1286+
in_object_properties_or_constructor = std::string("in_object_size");
1287+
} else {
1288+
in_object_properties_or_constructor_index = ConstructorFunctionIndex(err);
1289+
in_object_properties_or_constructor = std::string("constructor_index");
1290+
}
12821291
if (err.Fail()) return std::string();
12831292

12841293
int64_t instance_size = InstanceSize(err);
12851294
if (err.Fail()) return std::string();
12861295

12871296
char tmp[256];
12881297
snprintf(tmp, sizeof(tmp),
1289-
"<Map own_descriptors=%d in_object=%d instance_size=%d "
1298+
"<Map own_descriptors=%d %s=%d instance_size=%d "
12901299
"descriptors=0x%016" PRIx64,
12911300
static_cast<int>(own_descriptors_count),
1292-
static_cast<int>(in_object_properties),
1301+
in_object_properties_or_constructor.c_str(),
1302+
static_cast<int>(in_object_properties_or_constructor_index),
12931303
static_cast<int>(instance_size), descriptors_obj.raw());
12941304
if (!options->detailed) {
12951305
return std::string(tmp) + ">";

src/llv8.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,12 @@ class Map : public HeapObject {
137137
inline HeapObject InstanceDescriptors(Error& err);
138138
inline int64_t BitField3(Error& err);
139139
inline int64_t InObjectProperties(Error& err);
140+
inline int64_t ConstructorFunctionIndex(Error& err);
140141
inline int64_t InstanceSize(Error& err);
142+
inline int64_t InstanceType(Error& err);
141143

142144
inline bool IsDictionary(Error& err);
145+
inline bool IsJSObjectMap(Error& err);
143146
inline int64_t NumberOfOwnDescriptors(Error& err);
144147

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

0 commit comments

Comments
 (0)