[turbofan] Properly guard keyed stores wrt. setters in the prototype chain.
For holey/growing keyed stores, we need to check that there are no setters in the prototype chain and protect against changes to that via code dependencies. R=verwaest@chromium.org BUG=v8:5275,v8:5276 Review-Url: https://codereview.chromium.org/2231683002 Cr-Commit-Position: refs/heads/master@{#38514}
This commit is contained in:
parent
93809055aa
commit
7060bab81c
@ -472,6 +472,43 @@ Reduction JSNativeContextSpecialization::ReduceElementAccess(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
|
||||
}
|
||||
|
||||
// For holey stores or growing stores, we need to check that the prototype
|
||||
// chain contains no setters for elements, and we need to guard those checks
|
||||
// via code dependencies on the relevant prototype maps.
|
||||
if (access_mode == AccessMode::kStore) {
|
||||
// TODO(turbofan): We could have a fast path here, that checks for the
|
||||
// common case of Array or Object prototype only and therefore avoids
|
||||
// the zone allocation of this vector.
|
||||
ZoneVector<Handle<Map>> prototype_maps(zone());
|
||||
for (ElementAccessInfo const& access_info : access_infos) {
|
||||
for (Handle<Map> receiver_map : access_info.receiver_maps()) {
|
||||
// If the {receiver_map} has a prototype and it's elements backing
|
||||
// store is either holey, or we have a potentially growing store,
|
||||
// then we need to check that all prototypes have stable maps with
|
||||
// fast elements (and we need to guard against changes to that below).
|
||||
if (IsHoleyElementsKind(receiver_map->elements_kind()) ||
|
||||
IsGrowStoreMode(store_mode)) {
|
||||
// Make sure all prototypes are stable and have fast elements.
|
||||
for (Handle<Map> map = receiver_map;;) {
|
||||
Handle<Object> map_prototype(map->prototype(), isolate());
|
||||
if (map_prototype->IsNull(isolate())) break;
|
||||
if (!map_prototype->IsJSObject()) return NoChange();
|
||||
map = handle(Handle<JSObject>::cast(map_prototype)->map(),
|
||||
isolate());
|
||||
if (!map->is_stable()) return NoChange();
|
||||
if (!IsFastElementsKind(map->elements_kind())) return NoChange();
|
||||
prototype_maps.push_back(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Install dependencies on the relevant prototype maps.
|
||||
for (Handle<Map> prototype_map : prototype_maps) {
|
||||
dependencies()->AssumeMapStable(prototype_map);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that {receiver} is a heap object.
|
||||
effect = BuildCheckTaggedPointer(receiver, effect, control);
|
||||
|
||||
|
18
test/mjsunit/regress/regress-5275-1.js
Normal file
18
test/mjsunit/regress/regress-5275-1.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2016 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(x) {
|
||||
var a = new Array(1);
|
||||
a[0] = x;
|
||||
return a;
|
||||
}
|
||||
|
||||
assertEquals([1], foo(1));
|
||||
assertEquals([1], foo(1));
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
assertEquals([1], foo(1));
|
||||
Array.prototype.__defineSetter__("0", function() {});
|
||||
assertEquals([undefined], foo(1));
|
18
test/mjsunit/regress/regress-5275-2.js
Normal file
18
test/mjsunit/regress/regress-5275-2.js
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2016 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(x) {
|
||||
var a = new Array(1);
|
||||
a[0] = x;
|
||||
return a;
|
||||
}
|
||||
|
||||
assertEquals([1], foo(1));
|
||||
assertEquals([1], foo(1));
|
||||
%OptimizeFunctionOnNextCall(foo);
|
||||
assertEquals([1], foo(1));
|
||||
Object.prototype.__defineSetter__("0", function() {});
|
||||
assertEquals([undefined], foo(1));
|
@ -111,12 +111,6 @@
|
||||
'dfg-int-overflow-in-loop': [SKIP],
|
||||
}], # variant == ignition and msan
|
||||
|
||||
##############################################################################
|
||||
['variant == turbofan', {
|
||||
# BUG(v8:5276): Flaky with turbofan.
|
||||
'fast/js/array-bad-time': [SKIP],
|
||||
}], # variant == turbofan
|
||||
|
||||
##############################################################################
|
||||
['variant == ignition_turbofan and msan', {
|
||||
# TODO(mythria,4680): Too slow and timeout on ignition.
|
||||
|
Loading…
Reference in New Issue
Block a user