Commit 3251a03e authored by bmeurer's avatar bmeurer Committed by Commit bot

[crankshaft] Make the for-in slow path compatible with the other compilers.

So far the for-in slow path in Crankshaft unconditionally called
%ForInFilter for every iteration of the for-in loop, without paying
attention to the possible enum cache equipped receiver map. So even
though we iterate the enum cache FixedArray associated with the map
we don't check the map, but always go to %ForInFilter. This would be
perfectly fine if the enum cache FixedArray would be immutable, but
due to some funny GC/runtime interaction kicking in, the enum cache
can be right trimmed while we are iterating it, and the only way to
detect this is to ensure that we check the map when accessing the
enum cache.

BUG=v8:3650,v8:4715
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#33599}
parent 7467bb18
......@@ -5377,9 +5377,11 @@ void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
// Reload the values to ensure we have up-to-date values inside of the loop.
// This is relevant especially for OSR where the values don't come from the
// computation above, but from the OSR entry block.
enumerable = environment()->ExpressionStackAt(4);
HValue* index = environment()->ExpressionStackAt(0);
HValue* limit = environment()->ExpressionStackAt(1);
HValue* array = environment()->ExpressionStackAt(2);
HValue* type = environment()->ExpressionStackAt(3);
enumerable = environment()->ExpressionStackAt(4);
// Check that we still have more keys.
HCompareNumericAndBranch* compare_index =
......@@ -5399,21 +5401,31 @@ void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
set_current_block(loop_body);
HValue* key =
Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache.
index, index, nullptr, FAST_ELEMENTS);
HValue* key = Add<HLoadKeyed>(array, index, index, nullptr, FAST_ELEMENTS);
if (fast) {
// Check if the expected map still matches that of the enumerable.
// If not just deoptimize.
Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3));
Add<HCheckMapValue>(enumerable, type);
Bind(each_var, key);
} else {
Add<HPushArguments>(enumerable, key);
Runtime::FunctionId function_id = Runtime::kForInFilter;
key = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
Push(key);
Add<HSimulate>(stmt->FilterId());
HValue* enumerable_map =
Add<HLoadNamedField>(enumerable, nullptr, HObjectAccess::ForMap());
IfBuilder if_fast(this);
if_fast.If<HCompareObjectEqAndBranch>(enumerable_map, type);
if_fast.Then();
{
Push(key);
Add<HSimulate>(stmt->FilterId());
}
if_fast.Else();
{
Add<HPushArguments>(enumerable, key);
Runtime::FunctionId function_id = Runtime::kForInFilter;
Push(Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2));
Add<HSimulate>(stmt->FilterId());
}
if_fast.End();
key = Pop();
Bind(each_var, key);
IfBuilder if_undefined(this);
......
// 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 --dead-code-elimination --expose-gc
var training = {};
training.a = "nop";
training.slow = "nop";
delete training.slow; // Dictionary-mode properties => slow-mode for-in.
var keepalive = {};
keepalive.a = "nop"; // Keep a map early in the transition chain alive.
function GetReal() {
var r = {};
r.a = "nop";
r.b = "nop";
r.c = "dictionarize",
r.d = "gc";
r.e = "result";
return r;
};
function SideEffect(object, action) {
if (action === "dictionarize") {
delete object.a;
} else if (action === "gc") {
gc();
}
}
function foo(object) {
for (var key in object) {
SideEffect(object, object[key]);
}
return key;
}
// Collect type feedback for slow-mode for-in.
foo(training);
SideEffect({a: 0}, "dictionarize");
SideEffect({}, "gc");
// Compile for slow-mode objects...
%OptimizeFunctionOnNextCall(foo);
// ...and pass in a fast-mode object.
assertEquals("e", foo(GetReal()));
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