Commit 3f88ea39 authored by Z Duong Nguyen-Huu's avatar Z Duong Nguyen-Huu Committed by Commit Bot

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: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60884}
parent 5af26d8a
......@@ -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);
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