Commit c4712e8f authored by Igor Sheludko's avatar Igor Sheludko Committed by V8 LUCI CQ

[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: 's avatarLeszek Swirski <leszeks@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#79227}
parent 51458608
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment