Increase length for packed sealed object will transition to dictionary mode
Increase length of packed sealed array will create holes in packed array so transition to dictionary elements for now. Later we can consider transitioning to holey sealed array. Bug: chromium:952382 Change-Id: Ibe26ce56918859a114fccc1933f9c966c47c4112 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1566968 Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com> Reviewed-by: Toon Verwaest <verwaest@chromium.org> Cr-Commit-Position: refs/heads/master@{#60884}
This commit is contained in:
parent
5af26d8a2e
commit
3f88ea39b2
@ -2799,13 +2799,43 @@ class FastPackedSealedObjectElementsAccessor
|
||||
static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
|
||||
uint32_t length,
|
||||
Handle<FixedArrayBase> backing_store) {
|
||||
#ifdef DEBUG
|
||||
// Can only go here if length equals old_length.
|
||||
uint32_t old_length = 0;
|
||||
CHECK(array->length()->ToArrayIndex(&old_length));
|
||||
DCHECK_EQ(length, old_length);
|
||||
#endif
|
||||
return;
|
||||
if (length <= old_length) {
|
||||
// Cannot delete entries so do nothing.
|
||||
return;
|
||||
}
|
||||
|
||||
// Transition to DICTIONARY_ELEMENTS.
|
||||
// Convert to dictionary mode
|
||||
Handle<NumberDictionary> new_element_dictionary =
|
||||
old_length == 0 ? isolate->factory()->empty_slow_element_dictionary()
|
||||
: array->GetElementsAccessor()->Normalize(array);
|
||||
|
||||
// Migrate map.
|
||||
Handle<Map> new_map = Map::Copy(isolate, handle(array->map(), isolate),
|
||||
"SlowCopyForSetLengthImpl");
|
||||
new_map->set_is_extensible(false);
|
||||
new_map->set_elements_kind(DICTIONARY_ELEMENTS);
|
||||
JSObject::MigrateToMap(array, new_map);
|
||||
|
||||
if (!new_element_dictionary.is_null()) {
|
||||
array->set_elements(*new_element_dictionary);
|
||||
}
|
||||
|
||||
if (array->elements() !=
|
||||
ReadOnlyRoots(isolate).empty_slow_element_dictionary()) {
|
||||
Handle<NumberDictionary> dictionary(array->element_dictionary(), isolate);
|
||||
// Make sure we never go back to the fast case
|
||||
array->RequireSlowElements(*dictionary);
|
||||
JSObject::ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate),
|
||||
dictionary,
|
||||
PropertyAttributes::SEALED);
|
||||
}
|
||||
|
||||
// Set length
|
||||
Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length);
|
||||
array->set_length(*length_obj);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3771,12 +3771,10 @@ bool JSObject::IsExtensible(Handle<JSObject> object) {
|
||||
return object->map()->is_extensible();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename Dictionary>
|
||||
void ApplyAttributesToDictionary(Isolate* isolate, ReadOnlyRoots roots,
|
||||
Handle<Dictionary> dictionary,
|
||||
const PropertyAttributes attributes) {
|
||||
void JSObject::ApplyAttributesToDictionary(
|
||||
Isolate* isolate, ReadOnlyRoots roots, Handle<Dictionary> dictionary,
|
||||
const PropertyAttributes attributes) {
|
||||
int capacity = dictionary->Capacity();
|
||||
for (int i = 0; i < capacity; i++) {
|
||||
Object k;
|
||||
@ -3794,8 +3792,6 @@ void ApplyAttributesToDictionary(Isolate* isolate, ReadOnlyRoots roots,
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <PropertyAttributes attrs>
|
||||
Maybe<bool> JSObject::PreventExtensionsWithTransition(
|
||||
Handle<JSObject> object, ShouldThrow should_throw) {
|
||||
@ -3911,11 +3907,13 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
|
||||
if (object->IsJSGlobalObject()) {
|
||||
Handle<GlobalDictionary> dictionary(
|
||||
JSGlobalObject::cast(*object)->global_dictionary(), isolate);
|
||||
ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
|
||||
JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
|
||||
attrs);
|
||||
} else {
|
||||
Handle<NameDictionary> dictionary(object->property_dictionary(),
|
||||
isolate);
|
||||
ApplyAttributesToDictionary(isolate, roots, dictionary, attrs);
|
||||
JSObject::ApplyAttributesToDictionary(isolate, roots, dictionary,
|
||||
attrs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3948,8 +3946,8 @@ Maybe<bool> JSObject::PreventExtensionsWithTransition(
|
||||
// Make sure we never go back to the fast case
|
||||
object->RequireSlowElements(*dictionary);
|
||||
if (attrs != NONE) {
|
||||
ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate), dictionary,
|
||||
attrs);
|
||||
JSObject::ApplyAttributesToDictionary(isolate, ReadOnlyRoots(isolate),
|
||||
dictionary, attrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -797,6 +797,11 @@ class JSObject : public JSReceiver {
|
||||
static bool AllCanRead(LookupIterator* it);
|
||||
static bool AllCanWrite(LookupIterator* it);
|
||||
|
||||
template <typename Dictionary>
|
||||
static void ApplyAttributesToDictionary(Isolate* isolate, ReadOnlyRoots roots,
|
||||
Handle<Dictionary> dictionary,
|
||||
const PropertyAttributes attributes);
|
||||
|
||||
private:
|
||||
friend class JSReceiver;
|
||||
friend class Object;
|
||||
|
@ -561,3 +561,14 @@ assertEquals(arr, ['a', 0.5]);
|
||||
Object.freeze(arr);
|
||||
arr = arr.concat([1.5, 'b']);
|
||||
assertEquals(arr, ['a', 0.5, 1.5, 'b']);
|
||||
|
||||
// Regression test with change length
|
||||
var arr = ['a', 'b'];
|
||||
Object.freeze(arr);
|
||||
assertEquals(arr.length, 2);
|
||||
arr.length = 3;
|
||||
assertEquals(arr.length, 2);
|
||||
arr[2] = 'c';
|
||||
assertEquals(arr[2], undefined);
|
||||
arr.length = 1;
|
||||
assertEquals(arr.length, 2);
|
||||
|
@ -266,3 +266,15 @@ assertEquals(arr, ['a', 0.5]);
|
||||
Object.preventExtensions(arr);
|
||||
arr = arr.concat([1.5, 'b']);
|
||||
assertEquals(arr, ['a', 0.5, 1.5, 'b']);
|
||||
|
||||
// Regression test with change length
|
||||
var arr = ['a', 'b'];
|
||||
Object.preventExtensions(arr);
|
||||
assertEquals(arr.length, 2);
|
||||
arr.length = 3;
|
||||
assertEquals(arr.length, 3);
|
||||
arr[2] = 'c';
|
||||
assertEquals(arr[2], undefined);
|
||||
arr.length = 1;
|
||||
assertEquals(arr.length, 1);
|
||||
assertEquals(arr[1], undefined);
|
||||
|
@ -537,3 +537,14 @@ assertEquals(arr, ['a', 0.5]);
|
||||
Object.seal(arr);
|
||||
arr = arr.concat([1.5, 'b']);
|
||||
assertEquals(arr, ['a', 0.5, 1.5, 'b']);
|
||||
|
||||
// Regression test with change length
|
||||
var arr = ['a', 'b'];
|
||||
Object.seal(arr);
|
||||
assertEquals(arr.length, 2);
|
||||
arr.length = 3;
|
||||
assertEquals(arr.length, 3);
|
||||
arr[2] = 'c';
|
||||
assertEquals(arr[2], undefined);
|
||||
arr.length = 1;
|
||||
assertEquals(arr.length, 2);
|
||||
|
Loading…
Reference in New Issue
Block a user