[shared-struct] Fix in/out-of-object property storage

In a few places, shared structs currently incorrectly assume all storage
is in-object. This CL fixes those and rename
CSA::StoreJSSharedStructInObjectField to CSA::StoreSharedObjectField to
reflect the genericity.

Bug: v8:12547
Change-Id: I7c155b6bc584fbdcdbd484fda38f9f8a1940953d
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3997700
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Shu-yu Guo <syg@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84022}
This commit is contained in:
Shu-yu Guo 2022-11-01 14:41:28 -07:00 committed by V8 LUCI CQ
parent 103c34991b
commit 381b8f55e9
7 changed files with 51 additions and 16 deletions

View File

@ -85,7 +85,12 @@ BUILTIN(SharedStructTypeConstructor) {
instance_map->InitializeDescriptors(isolate, *descriptors);
// Structs have fixed layout ahead of time, so there's no slack.
instance_map->SetInObjectUnusedPropertyFields(0);
int out_of_object_properties = num_properties - in_object_properties;
if (out_of_object_properties == 0) {
instance_map->SetInObjectUnusedPropertyFields(0);
} else {
instance_map->SetOutOfObjectUnusedPropertyFields(0);
}
instance_map->set_is_extensible(false);
JSFunction::SetInitialMap(isolate, constructor, instance_map,
factory->null_value());

View File

@ -3104,9 +3104,14 @@ void CodeStubAssembler::UnsafeStoreObjectFieldNoWriteBarrier(
object, offset, value);
}
void CodeStubAssembler::StoreJSSharedStructInObjectField(
TNode<HeapObject> object, TNode<IntPtrT> offset, TNode<Object> value) {
CSA_DCHECK(this, IsJSSharedStruct(object));
void CodeStubAssembler::StoreSharedObjectField(TNode<HeapObject> object,
TNode<IntPtrT> offset,
TNode<Object> value) {
CSA_DCHECK(
this,
WordNotEqual(WordAnd(LoadBasicMemoryChunkFlags(object),
IntPtrConstant(BasicMemoryChunk::IN_SHARED_HEAP)),
IntPtrConstant(0)));
// JSSharedStructs are allocated in the shared old space, which is currently
// collected by stopping the world, so the incremental write barrier is not
// needed. They can only store Smis and other HeapObjects in the shared old

View File

@ -1860,9 +1860,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
WriteBarrierMode barrier_mode = UPDATE_WRITE_BARRIER,
int additional_offset = 0);
void StoreJSSharedStructInObjectField(TNode<HeapObject> object,
TNode<IntPtrT> offset,
TNode<Object> value);
void StoreSharedObjectField(TNode<HeapObject> object, TNode<IntPtrT> offset,
TNode<Object> value);
void StoreJSSharedStructPropertyArrayElement(TNode<PropertyArray> array,
TNode<IntPtrT> index,

View File

@ -561,6 +561,7 @@ void Map::MapVerify(Isolate* isolate) {
if (maybe_cell.IsCell()) CHECK(maybe_cell.InSharedHeap());
CHECK(!is_extensible());
CHECK(!is_prototype_map());
CHECK(OnlyHasSimpleProperties());
CHECK(instance_descriptors(isolate).InSharedHeap());
if (IsJSSharedArrayMap()) {
CHECK(has_shared_array_elements());
@ -1268,7 +1269,6 @@ void JSSharedStruct::JSSharedStructVerify(Isolate* isolate) {
CHECK(details.representation().IsTagged());
FieldIndex field_index = FieldIndex::ForDescriptor(struct_map, i);
CHECK(RawFastPropertyAt(field_index).IsShared());
CHECK(field_index.is_inobject());
}
}

View File

@ -1231,8 +1231,7 @@ void AccessorAssembler::HandleStoreICSmiHandlerJSSharedStructFieldCase(
DecodeWordFromWord32<StoreHandler::FieldIndexBits>(handler_word);
TNode<IntPtrT> offset = Signed(TimesTaggedSize(index));
StoreJSSharedStructInObjectField(property_storage, offset,
shared_value.value());
StoreSharedObjectField(property_storage, offset, shared_value.value());
// Return the original value.
Return(value);
@ -1758,8 +1757,7 @@ void AccessorAssembler::StoreJSSharedStructField(
BIND(&inobject);
{
TNode<IntPtrT> field_offset = Signed(TimesTaggedSize(field_index));
StoreJSSharedStructInObjectField(shared_struct, field_offset,
shared_value.value());
StoreSharedObjectField(shared_struct, field_offset, shared_value.value());
Goto(&done);
}
@ -1768,7 +1766,10 @@ void AccessorAssembler::StoreJSSharedStructField(
TNode<IntPtrT> backing_store_index =
Signed(IntPtrSub(field_index, instance_size_in_words));
Label tagged_rep(this), double_rep(this);
CSA_DCHECK(
this,
Word32Equal(DecodeWord32<PropertyDetails::RepresentationField>(details),
Int32Constant(Representation::kTagged)));
TNode<PropertyArray> properties =
CAST(LoadFastProperties(CAST(shared_struct)));
StoreJSSharedStructPropertyArrayElement(properties, backing_store_index,

View File

@ -0,0 +1,23 @@
// Copyright 2022 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Flags: --shared-string-table --harmony-struct
'use strict';
let fieldNames = [];
for (let i = 0; i < 999; i++) {
fieldNames.push('field' + i);
}
let s = new (new SharedStructType(fieldNames));
// Write to an out-of-object field.
(function storeOutOfObject() {
for (let i = 0; i < 100; i++) s.field998 = i;
})();
// Write to an in-object field.
(function storeInObject() {
for (let i = 0; i < 100; i++) s.field0 = i;
})();

View File

@ -49,11 +49,13 @@ let S = new SharedStructType(['field']);
})();
(function TestTooManyFields() {
let field_names = [];
let fieldNames = [];
for (let i = 0; i < 1000; i++) {
field_names.push('field' + i);
fieldNames.push('field' + i);
}
assertThrows(() => { new SharedStructType(field_names); });
assertThrows(() => {
new SharedStructType(fieldNames);
});
})();
(function TestOwnPropertyEnumeration() {