Commit df7e09da authored by mvstanton's avatar mvstanton Committed by Commit bot

Empty Array prototype elements protection needs to alert on length change.

If the length of the array prototype is changed, be sure to turn off the
guarantee that it's elements are empty.

This case was missed in https://codereview.chromium.org/1092043002
("Protect the emptiness of Array prototype elements with a PropertyCell")

R=jkummerow@chromium.org
BUG=479781
LOG=N

Review URL: https://codereview.chromium.org/1099453007

Cr-Commit-Position: refs/heads/master@{#28033}
parent ddd3f318
......@@ -2374,16 +2374,18 @@ bool Isolate::use_crankshaft() const {
bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
Handle<PropertyCell> no_elements_cell =
handle(heap()->array_protector(), this);
PropertyCell* no_elements_cell = heap()->array_protector();
bool cell_reports_intact = no_elements_cell->value()->IsSmi() &&
Smi::cast(no_elements_cell->value())->value() == 1;
#ifdef DEBUG
Map* root_array_map =
get_initial_js_array_map(GetInitialFastElementsKind());
JSObject* initial_array_proto = JSObject::cast(*initial_array_prototype());
JSObject* initial_object_proto = JSObject::cast(*initial_object_prototype());
Context* native_context = context()->native_context();
JSObject* initial_array_proto = JSObject::cast(
native_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
JSObject* initial_object_proto = JSObject::cast(
native_context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX));
if (root_array_map == NULL || initial_array_proto == initial_object_proto) {
// We are in the bootstrapping process, and the entire check sequence
......@@ -2426,7 +2428,6 @@ bool Isolate::IsFastArrayConstructorPrototypeChainIntact() {
void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
Handle<PropertyCell> array_protector = factory()->array_protector();
if (IsFastArrayConstructorPrototypeChainIntact() &&
object->map()->is_prototype_map()) {
Object* context = heap()->native_contexts_list();
......@@ -2436,7 +2437,7 @@ void Isolate::UpdateArrayProtectorOnSetElement(Handle<JSObject> object) {
*object ||
current_context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ==
*object) {
PropertyCell::SetValueWithInvalidation(array_protector,
PropertyCell::SetValueWithInvalidation(factory()->array_protector(),
handle(Smi::FromInt(0), this));
break;
}
......
......@@ -1021,6 +1021,9 @@ class Isolate {
// object prototype. Also ensure that changes to prototype chain between
// Array and Object fire notifications.
void UpdateArrayProtectorOnSetElement(Handle<JSObject> object);
void UpdateArrayProtectorOnSetLength(Handle<JSObject> object) {
UpdateArrayProtectorOnSetElement(object);
}
void UpdateArrayProtectorOnSetPrototype(Handle<JSObject> object) {
UpdateArrayProtectorOnSetElement(object);
}
......
......@@ -11911,8 +11911,11 @@ Handle<FixedArray> JSObject::SetFastElementsCapacityAndLength(
DCHECK(!object->HasExternalArrayElements());
// Allocate a new fast elements backing store.
Isolate* isolate = object->GetIsolate();
Handle<FixedArray> new_elements =
object->GetIsolate()->factory()->NewUninitializedFixedArray(capacity);
isolate->factory()->NewUninitializedFixedArray(capacity);
isolate->UpdateArrayProtectorOnSetLength(object);
ElementsKind elements_kind = object->GetElementsKind();
ElementsKind new_elements_kind;
......
......@@ -16682,6 +16682,8 @@ TEST(VerifyArrayPrototypeGuarantees) {
BreakArrayGuarantees("Object.prototype[3] = 'three';");
BreakArrayGuarantees("Array.prototype.push(1);");
BreakArrayGuarantees("Array.prototype.unshift(1);");
// Break fast array hole handling by changing length.
BreakArrayGuarantees("Array.prototype.length = 30;");
// Break fast array hole handling by prototype structure changes.
BreakArrayGuarantees("[].__proto__.__proto__ = { funny: true };");
// By sending elements to dictionary mode.
......
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