Commit b054ff46 authored by adamk's avatar adamk Committed by Commit bot

Revert "Add basic crankshaft support for slow-mode for-in to avoid disabling optimizations"

This reverts commit 8c98cc07
because it causes flaky failures in the dromaeo.jslibeventprototype
benchmark on Linux/Windows and consistent failures on Android.

Also reverts the followup "Remove kForInStatementIsNotFastCase bailout reason"
(commit ba24e676) to avoid breaking the build.

BUG=chromium:476592
TBR=verwaest@chromium.org
LOG=y

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

Cr-Commit-Position: refs/heads/master@{#27859}
parent 53ddccfc
......@@ -94,6 +94,7 @@ namespace internal {
V(kExternalStringExpectedButNotFound, \
"External string expected, but not found") \
V(kFailedBailedOutLastTime, "Failed/bailed out last time") \
V(kForInStatementIsNotFastCase, "ForInStatement is not fast case") \
V(kForInStatementOptimizationIsDisabled, \
"ForInStatement optimization is disabled") \
V(kForInStatementWithNonLocalEachVariable, \
......
......@@ -5051,6 +5051,10 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
return Bailout(kForInStatementOptimizationIsDisabled);
}
if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
return Bailout(kForInStatementIsNotFastCase);
}
if (!stmt->each()->IsVariableProxy() ||
!stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
return Bailout(kForInStatementWithNonLocalEachVariable);
......@@ -5061,42 +5065,13 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
CHECK_ALIVE(VisitForValue(stmt->enumerable()));
HValue* enumerable = Top(); // Leave enumerable at the top.
HInstruction* map;
HInstruction* array;
HInstruction* enum_length;
bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
if (fast) {
map = Add<HForInPrepareMap>(enumerable);
Add<HSimulate>(stmt->PrepareId());
array = Add<HForInCacheArray>(enumerable, map,
DescriptorArray::kEnumCacheBridgeCacheIndex);
enum_length = Add<HMapEnumLength>(map);
HInstruction* index_cache = Add<HForInCacheArray>(
enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
HForInCacheArray::cast(array)
->set_index_cache(HForInCacheArray::cast(index_cache));
} else {
Add<HSimulate>(stmt->PrepareId());
{
NoObservableSideEffectsScope no_effects(this);
BuildJSObjectCheck(enumerable, 0);
}
Add<HSimulate>(stmt->ToObjectId());
HInstruction* map = Add<HForInPrepareMap>(enumerable);
Add<HSimulate>(stmt->PrepareId());
map = graph()->GetConstant1();
Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast;
Add<HPushArguments>(enumerable);
array = Add<HCallRuntime>(isolate()->factory()->empty_string(),
Runtime::FunctionForId(function_id), 1);
Push(array);
Add<HSimulate>(stmt->EnumId());
Drop(1);
Handle<Map> array_map = isolate()->factory()->fixed_array_map();
HValue* check = Add<HCheckMaps>(array, array_map);
enum_length = AddLoadFixedArrayLength(array, check);
}
HInstruction* array = Add<HForInCacheArray>(
enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
HInstruction* enum_length = Add<HMapEnumLength>(map);
HInstruction* start_index = Add<HConstant>(0);
......@@ -5105,12 +5080,13 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
Push(enum_length);
Push(start_index);
HInstruction* index_cache = Add<HForInCacheArray>(
enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
HForInCacheArray::cast(array)
->set_index_cache(HForInCacheArray::cast(index_cache));
HBasicBlock* loop_entry = BuildLoopEntry(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);
......@@ -5134,21 +5110,15 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
HValue* key =
Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache.
index, index, FAST_ELEMENTS);
environment()->ExpressionStackAt(0), // Iteration index.
environment()->ExpressionStackAt(0), 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));
Bind(each_var, key);
} else {
HValue* function = AddLoadJSBuiltin(Builtins::FILTER_KEY);
Add<HPushArguments>(enumerable, key);
key = Add<HInvokeFunction>(function, 2);
Bind(each_var, key);
Add<HSimulate>(stmt->AssignmentId());
Add<HCheckHeapObject>(key);
}
// Check if the expected map still matches that of the enumerable.
// If not just deoptimize.
Add<HCheckMapValue>(environment()->ExpressionStackAt(4),
environment()->ExpressionStackAt(3));
Bind(each_var, key);
BreakAndContinueInfo break_info(stmt, scope(), 5);
{
......
// Copyright 2015 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: --harmony-proxies --allow-natives-syntax
"use strict";
// Test non-JSObject receiver.
function f(o) {
var result = [];
for (var i in o) {
result.push(i);
}
return result;
}
assertEquals(["0"], f("a"));
assertEquals(["0"], f("a"));
%OptimizeFunctionOnNextCall(f);
assertEquals(["0","1","2"], f("bla"));
// Test the lazy deopt points.
var keys = ["a", "b", "c", "d"];
var has_keys = [];
var deopt_has = false;
var deopt_enum = false;
var handler = {
enumerate: function(target) {
if (deopt_enum) {
%DeoptimizeFunction(f2);
deopt_enum = false;
}
return keys;
},
getPropertyDescriptor: function(k) {
if (deopt_has) {
%DeoptimizeFunction(f2);
deopt_has = false;
}
has_keys.push(k);
return {value: 10, configurable: true, writable: false, enumerable: true};
}
};
var proxy = Proxy.create(handler);
var o = {__proto__: proxy};
function f2(o) {
var result = [];
for (var i in o) {
result.push(i);
}
return result;
}
function check_f2() {
assertEquals(keys, f2(o));
assertEquals(keys, has_keys);
has_keys.length = 0;
}
check_f2();
check_f2();
// Test lazy deopt after GetPropertyNamesFast
%OptimizeFunctionOnNextCall(f2);
deopt_enum = true;
check_f2();
// Test lazy deopt after FILTER_KEY
%OptimizeFunctionOnNextCall(f2);
deopt_has = true;
check_f2();
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