Commit bd17f12a authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[ic] Disallow growing stores with TypedArrays in the prototype chain.

For keyed stores to JSArrays we can generally allow the receiver to grow
to the necessary size by bumping the magical length property. This works
for regular Arrays, but not in the case the prototype chain contains a
TypedArray, as that is going to swallow all stores that are considered
out-of-bounds for it.

We don't wanna deal with that kind of complexity in the IC handlers, so
we just refuse to handle that case (also giving TurboFan the signal that
it shouldn't attempt to handle growing stores in that case).

Bug: chromium:960134, chromium:961709
Change-Id: Ia886de590c32ae51ed4ebe38fc237ed975a635aa
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1609790Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61465}
parent 4ef714a6
......@@ -2034,13 +2034,29 @@ void KeyedStoreIC::StoreElementPolymorphicHandlers(
}
}
static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
uint32_t index, Handle<Object> value) {
namespace {
bool MayHaveTypedArrayInPrototypeChain(Handle<JSObject> object) {
for (PrototypeIterator iter(object->GetIsolate(), *object); !iter.IsAtEnd();
iter.Advance()) {
// Be conservative, don't walk into proxies.
if (iter.GetCurrent()->IsJSProxy()) return true;
if (iter.GetCurrent()->IsJSTypedArray()) return true;
}
return false;
}
KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver, uint32_t index,
Handle<Object> value) {
bool oob_access = IsOutOfBoundsAccess(receiver, index);
// Don't consider this a growing store if the store would send the receiver to
// dictionary mode.
// dictionary mode. Also make sure we don't consider this a growing store if
// there's any JSTypedArray in the {receiver}'s prototype chain, since that
// prototype is going to swallow all stores that are out-of-bounds for said
// prototype, and we just let the runtime deal with the complexity of this.
bool allow_growth = receiver->IsJSArray() && oob_access &&
!receiver->WouldConvertToSlowElements(index);
!receiver->WouldConvertToSlowElements(index) &&
!MayHaveTypedArrayInPrototypeChain(receiver);
if (allow_growth) {
// Handle growing array in stub if necessary.
if (receiver->HasSmiElements()) {
......@@ -2078,6 +2094,8 @@ static KeyedAccessStoreMode GetStoreMode(Handle<JSObject> receiver,
}
}
} // namespace
MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object,
Handle<Object> key,
Handle<Object> value) {
......
// Copyright 2019 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: --allow-natives-syntax
function foo() {
const a = [];
a[0] = 1;
return a[0];
}
Object.setPrototypeOf(Array.prototype, new Int8Array());
assertEquals(undefined, foo());
assertEquals(undefined, foo());
// Copyright 2019 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: --allow-natives-syntax --opt
function foo() {
const a = [];
a[0] = 1;
return a[0];
}
Object.setPrototypeOf(Array.prototype, new Int8Array());
assertEquals(undefined, foo());
assertEquals(undefined, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals(undefined, foo());
assertOptimized(foo);
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