Skip to content

Commit

Permalink
src: fix object inspection for V8 6.4 (#192)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Matheus Marchini authored May 15, 2018
1 parent 7ae0dee commit 7f1e791
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 5 deletions.
5 changes: 4 additions & 1 deletion src/llv8-constants.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,12 @@ void Map::Load() {
"class_Map__inobject_properties_or_constructor_function_index__int",
"class_Map__inobject_properties__int");
if (kInObjectPropertiesOffset == -1) {
kInObjectPropertiesOffset = LoadConstant(
kInObjectPropertiesStartOffset = LoadConstant(
"class_Map__inobject_properties_start_or_constructor_function_index__"
"char");
}

kInstanceTypeOffset = LoadConstant("class_Map__instance_type__uint16_t");
kInstanceSizeOffset = LoadConstant("class_Map__instance_size__int",
"class_Map__instance_size_in_words__char");
kDictionaryMapShift = LoadConstant("bit_field3_dictionary_map_shift",
Expand Down Expand Up @@ -574,6 +575,8 @@ void Frame::Load() {

void Types::Load() {
kFirstNonstringType = LoadConstant("FirstNonstringType");
kFirstJSObjectType =
LoadConstant("type_JSGlobalObject__JS_GLOBAL_OBJECT_TYPE");

kHeapNumberType = LoadConstant("type_HeapNumber__HEAP_NUMBER_TYPE");
kMapType = LoadConstant("type_Map__MAP_TYPE");
Expand Down
3 changes: 3 additions & 0 deletions src/llv8-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ class Map : public Module {
int64_t kInstanceDescriptorsOffset;
int64_t kBitField3Offset;
int64_t kInObjectPropertiesOffset;
int64_t kInObjectPropertiesStartOffset;
int64_t kInstanceSizeOffset;
int64_t kInstanceTypeOffset;

int64_t kNumberOfOwnDescriptorsMask;
int64_t kNumberOfOwnDescriptorsShift;
Expand Down Expand Up @@ -479,6 +481,7 @@ class Types : public Module {
MODULE_DEFAULT_METHODS(Types);

int64_t kFirstNonstringType;
int64_t kFirstJSObjectType;

int64_t kHeapNumberType;
int64_t kMapType;
Expand Down
38 changes: 37 additions & 1 deletion src/llv8-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,44 @@ inline int64_t Map::BitField3(Error& err) {
return v8()->LoadUnsigned(LeaField(v8()->map()->kBitField3Offset), 4, err);
}

inline int64_t Map::InstanceType(Error& err) {
return v8()->LoadUnsigned(LeaField(v8()->map()->kInstanceTypeOffset), 2, err);
}

inline bool Map::IsJSObjectMap(Error& err) {
return InstanceType(err) >= v8()->types()->kFirstJSObjectType;
}


inline int64_t Map::InObjectProperties(Error& err) {
return LoadField(v8()->map()->kInObjectPropertiesOffset, err) & 0xff;
if (!IsJSObjectMap(err)) {
err = Error::Failure(
"Invalid call to Map::InObjectProperties with a non-JsObject type");
return 0;
}
if (v8()->map()->kInObjectPropertiesOffset != -1) {
return LoadField(v8()->map()->kInObjectPropertiesOffset, err) & 0xff;
} else {
// NOTE(mmarchini): V8 6.4 changed semantics for
// in_objects_properties_offset (see
// https://chromium-review.googlesource.com/c/v8/v8/+/776720). To keep
// changes to a minimum on llnode and to comply with V8, we're using the
// same implementation from
// https://chromium-review.googlesource.com/c/v8/v8/+/776720/9/src/objects-inl.h#3027.
int64_t in_object_properties_start_offset =
LoadField(v8()->map()->kInObjectPropertiesStartOffset, err) & 0xff;
int64_t instance_size =
v8()->LoadUnsigned(LeaField(v8()->map()->kInstanceSizeOffset), 1, err);
return instance_size - in_object_properties_start_offset;
}
}

inline int64_t Map::ConstructorFunctionIndex(Error& err) {
if (v8()->map()->kInObjectPropertiesOffset != -1) {
return LoadField(v8()->map()->kInObjectPropertiesOffset, err) & 0xff;
} else {
return LoadField(v8()->map()->kInObjectPropertiesStartOffset, err) & 0xff;
}
}

inline int64_t Map::InstanceSize(Error& err) {
Expand Down
16 changes: 13 additions & 3 deletions src/llv8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1278,18 +1278,28 @@ std::string Map::Inspect(InspectOptions* options, Error& err) {
int64_t own_descriptors_count = NumberOfOwnDescriptors(err);
if (err.Fail()) return std::string();

int64_t in_object_properties = InObjectProperties(err);
std::string in_object_properties_or_constructor;
int64_t in_object_properties_or_constructor_index;
if (IsJSObjectMap(err)) {
if (err.Fail()) return std::string();
in_object_properties_or_constructor_index = InObjectProperties(err);
in_object_properties_or_constructor = std::string("in_object_size");
} else {
in_object_properties_or_constructor_index = ConstructorFunctionIndex(err);
in_object_properties_or_constructor = std::string("constructor_index");
}
if (err.Fail()) return std::string();

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

char tmp[256];
snprintf(tmp, sizeof(tmp),
"<Map own_descriptors=%d in_object=%d instance_size=%d "
"<Map own_descriptors=%d %s=%d instance_size=%d "
"descriptors=0x%016" PRIx64,
static_cast<int>(own_descriptors_count),
static_cast<int>(in_object_properties),
in_object_properties_or_constructor.c_str(),
static_cast<int>(in_object_properties_or_constructor_index),
static_cast<int>(instance_size), descriptors_obj.raw());
if (!options->detailed) {
return std::string(tmp) + ">";
Expand Down
3 changes: 3 additions & 0 deletions src/llv8.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,9 +137,12 @@ class Map : public HeapObject {
inline HeapObject InstanceDescriptors(Error& err);
inline int64_t BitField3(Error& err);
inline int64_t InObjectProperties(Error& err);
inline int64_t ConstructorFunctionIndex(Error& err);
inline int64_t InstanceSize(Error& err);
inline int64_t InstanceType(Error& err);

inline bool IsDictionary(Error& err);
inline bool IsJSObjectMap(Error& err);
inline int64_t NumberOfOwnDescriptors(Error& err);

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

0 comments on commit 7f1e791

Please sign in to comment.