[runtime] Fix embedder fields offset calculations
Embedder fields are located between JSObject header and inobject fields and there must be no gaps. This CL adds respective check to Map verification and fixes existing issues. Bug: v8:10391 Change-Id: If55652095588f8704c9a375fb86be1599816aa86 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3482436 Auto-Submit: Igor Sheludko <ishell@chromium.org> Reviewed-by: Leszek Swirski <leszeks@chromium.org> Commit-Queue: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/main@{#79227}
This commit is contained in:
parent
5145860836
commit
c4712e8f7e
@ -526,8 +526,19 @@ void Map::MapVerify(Isolate* isolate) {
|
||||
TransitionsAccessor(isolate, *this).IsConsistentWithBackPointers());
|
||||
// Only JSFunction maps have has_prototype_slot() bit set and constructible
|
||||
// JSFunction objects must have prototype slot.
|
||||
CHECK_IMPLIES(has_prototype_slot(),
|
||||
InstanceTypeChecker::IsJSFunction(instance_type()));
|
||||
CHECK_IMPLIES(has_prototype_slot(), IsJSFunctionMap());
|
||||
|
||||
if (IsJSObjectMap()) {
|
||||
int header_end_offset = JSObject::GetHeaderSize(*this);
|
||||
int inobject_fields_start_offset = GetInObjectPropertyOffset(0);
|
||||
// Ensure that embedder fields are located exactly between header and
|
||||
// inobject properties.
|
||||
CHECK_EQ(header_end_offset, JSObject::GetEmbedderFieldsStartOffset(*this));
|
||||
CHECK_EQ(header_end_offset +
|
||||
JSObject::GetEmbedderFieldCount(*this) * kEmbedderDataSlotSize,
|
||||
inobject_fields_start_offset);
|
||||
}
|
||||
|
||||
if (!may_have_interesting_symbols()) {
|
||||
CHECK(!has_named_interceptor());
|
||||
CHECK(!is_dictionary_map());
|
||||
|
@ -432,6 +432,12 @@ V8_NOINLINE Handle<JSFunction> CreateFunctionForBuiltinWithPrototype(
|
||||
}
|
||||
Handle<Map> initial_map =
|
||||
factory->NewMap(type, instance_size, elements_kind, inobject_properties);
|
||||
if (type == JS_FUNCTION_TYPE) {
|
||||
DCHECK_EQ(instance_size, JSFunction::kSizeWithPrototype);
|
||||
// Since we are creating an initial map for JSFunction objects with
|
||||
// prototype slot, set the respective bit.
|
||||
initial_map->set_has_prototype_slot(true);
|
||||
}
|
||||
// TODO(littledan): Why do we have this is_generator test when
|
||||
// NewFunctionPrototype already handles finding an appropriately
|
||||
// shared prototype?
|
||||
|
@ -679,8 +679,9 @@ bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target,
|
||||
static_cast<int>(constructor->shared().expected_nof_properties()),
|
||||
JSFunction::CalculateExpectedNofProperties(isolate, new_target));
|
||||
JSFunction::CalculateInstanceSizeHelper(
|
||||
instance_type, true, embedder_fields, expected_nof_properties,
|
||||
&instance_size, &in_object_properties);
|
||||
instance_type, constructor_initial_map->has_prototype_slot(),
|
||||
embedder_fields, expected_nof_properties, &instance_size,
|
||||
&in_object_properties);
|
||||
|
||||
int pre_allocated = constructor_initial_map->GetInObjectProperties() -
|
||||
constructor_initial_map->UnusedPropertyFields();
|
||||
@ -1038,13 +1039,8 @@ void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
|
||||
DCHECK_LE(static_cast<unsigned>(requested_embedder_fields),
|
||||
JSObject::kMaxEmbedderFields);
|
||||
int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot);
|
||||
if (requested_embedder_fields) {
|
||||
// If there are embedder fields, then the embedder fields start offset must
|
||||
// be properly aligned (embedder fields are located between object header
|
||||
// and inobject fields).
|
||||
header_size = RoundUp<kSystemPointerSize>(header_size);
|
||||
requested_embedder_fields *= kEmbedderDataSlotSizeInTaggedSlots;
|
||||
}
|
||||
requested_embedder_fields *= kEmbedderDataSlotSizeInTaggedSlots;
|
||||
|
||||
int max_nof_fields =
|
||||
(JSObject::kMaxInstanceSize - header_size) >> kTaggedSizeLog2;
|
||||
CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties);
|
||||
|
@ -1751,9 +1751,8 @@ static void TestReconfigureElementsKind_GeneralizeFieldInPlace(
|
||||
Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
|
||||
|
||||
// Create a map, add required properties to it and initialize expectations.
|
||||
Handle<Map> initial_map = Map::Create(isolate, 0);
|
||||
initial_map->set_instance_type(JS_ARRAY_TYPE);
|
||||
initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
|
||||
Handle<Map> initial_map = isolate->factory()->NewMap(
|
||||
JS_ARRAY_TYPE, JSArray::kHeaderSize, PACKED_SMI_ELEMENTS);
|
||||
|
||||
Handle<Map> map = initial_map;
|
||||
map = expectations.AsElementsKind(map, PACKED_ELEMENTS);
|
||||
|
Loading…
Reference in New Issue
Block a user