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) { ...@@ -526,8 +526,19 @@ void Map::MapVerify(Isolate* isolate) {
TransitionsAccessor(isolate, *this).IsConsistentWithBackPointers()); TransitionsAccessor(isolate, *this).IsConsistentWithBackPointers());
// Only JSFunction maps have has_prototype_slot() bit set and constructible // Only JSFunction maps have has_prototype_slot() bit set and constructible
// JSFunction objects must have prototype slot. // JSFunction objects must have prototype slot.
CHECK_IMPLIES(has_prototype_slot(), CHECK_IMPLIES(has_prototype_slot(), IsJSFunctionMap());
InstanceTypeChecker::IsJSFunction(instance_type()));
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()) { if (!may_have_interesting_symbols()) {
CHECK(!has_named_interceptor()); CHECK(!has_named_interceptor());
CHECK(!is_dictionary_map()); CHECK(!is_dictionary_map());
......
...@@ -432,6 +432,12 @@ V8_NOINLINE Handle<JSFunction> CreateFunctionForBuiltinWithPrototype( ...@@ -432,6 +432,12 @@ V8_NOINLINE Handle<JSFunction> CreateFunctionForBuiltinWithPrototype(
} }
Handle<Map> initial_map = Handle<Map> initial_map =
factory->NewMap(type, instance_size, elements_kind, inobject_properties); 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 // TODO(littledan): Why do we have this is_generator test when
// NewFunctionPrototype already handles finding an appropriately // NewFunctionPrototype already handles finding an appropriately
// shared prototype? // shared prototype?
......
...@@ -679,8 +679,9 @@ bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target, ...@@ -679,8 +679,9 @@ bool FastInitializeDerivedMap(Isolate* isolate, Handle<JSFunction> new_target,
static_cast<int>(constructor->shared().expected_nof_properties()), static_cast<int>(constructor->shared().expected_nof_properties()),
JSFunction::CalculateExpectedNofProperties(isolate, new_target)); JSFunction::CalculateExpectedNofProperties(isolate, new_target));
JSFunction::CalculateInstanceSizeHelper( JSFunction::CalculateInstanceSizeHelper(
instance_type, true, embedder_fields, expected_nof_properties, instance_type, constructor_initial_map->has_prototype_slot(),
&instance_size, &in_object_properties); embedder_fields, expected_nof_properties, &instance_size,
&in_object_properties);
int pre_allocated = constructor_initial_map->GetInObjectProperties() - int pre_allocated = constructor_initial_map->GetInObjectProperties() -
constructor_initial_map->UnusedPropertyFields(); constructor_initial_map->UnusedPropertyFields();
...@@ -1038,13 +1039,8 @@ void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type, ...@@ -1038,13 +1039,8 @@ void JSFunction::CalculateInstanceSizeHelper(InstanceType instance_type,
DCHECK_LE(static_cast<unsigned>(requested_embedder_fields), DCHECK_LE(static_cast<unsigned>(requested_embedder_fields),
JSObject::kMaxEmbedderFields); JSObject::kMaxEmbedderFields);
int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot); int header_size = JSObject::GetHeaderSize(instance_type, has_prototype_slot);
if (requested_embedder_fields) { requested_embedder_fields *= kEmbedderDataSlotSizeInTaggedSlots;
// 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;
}
int max_nof_fields = int max_nof_fields =
(JSObject::kMaxInstanceSize - header_size) >> kTaggedSizeLog2; (JSObject::kMaxInstanceSize - header_size) >> kTaggedSizeLog2;
CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties); CHECK_LE(max_nof_fields, JSObject::kMaxInObjectProperties);
......
...@@ -1751,9 +1751,8 @@ static void TestReconfigureElementsKind_GeneralizeFieldInPlace( ...@@ -1751,9 +1751,8 @@ static void TestReconfigureElementsKind_GeneralizeFieldInPlace(
Expectations expectations(isolate, PACKED_SMI_ELEMENTS); Expectations expectations(isolate, PACKED_SMI_ELEMENTS);
// Create a map, add required properties to it and initialize expectations. // Create a map, add required properties to it and initialize expectations.
Handle<Map> initial_map = Map::Create(isolate, 0); Handle<Map> initial_map = isolate->factory()->NewMap(
initial_map->set_instance_type(JS_ARRAY_TYPE); JS_ARRAY_TYPE, JSArray::kHeaderSize, PACKED_SMI_ELEMENTS);
initial_map->set_elements_kind(PACKED_SMI_ELEMENTS);
Handle<Map> map = initial_map; Handle<Map> map = initial_map;
map = expectations.AsElementsKind(map, PACKED_ELEMENTS); 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