Revert "Add basic crankshaft support for slow-mode for-in to avoid disabling optimizations"
This reverts commit8c98cc074e
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" (commitba24e67696
) 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}
This commit is contained in:
parent
53ddccfc33
commit
b054ff4620
@ -94,6 +94,7 @@ namespace internal {
|
|||||||
V(kExternalStringExpectedButNotFound, \
|
V(kExternalStringExpectedButNotFound, \
|
||||||
"External string expected, but not found") \
|
"External string expected, but not found") \
|
||||||
V(kFailedBailedOutLastTime, "Failed/bailed out last time") \
|
V(kFailedBailedOutLastTime, "Failed/bailed out last time") \
|
||||||
|
V(kForInStatementIsNotFastCase, "ForInStatement is not fast case") \
|
||||||
V(kForInStatementOptimizationIsDisabled, \
|
V(kForInStatementOptimizationIsDisabled, \
|
||||||
"ForInStatement optimization is disabled") \
|
"ForInStatement optimization is disabled") \
|
||||||
V(kForInStatementWithNonLocalEachVariable, \
|
V(kForInStatementWithNonLocalEachVariable, \
|
||||||
|
@ -5051,6 +5051,10 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
return Bailout(kForInStatementOptimizationIsDisabled);
|
return Bailout(kForInStatementOptimizationIsDisabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
|
||||||
|
return Bailout(kForInStatementIsNotFastCase);
|
||||||
|
}
|
||||||
|
|
||||||
if (!stmt->each()->IsVariableProxy() ||
|
if (!stmt->each()->IsVariableProxy() ||
|
||||||
!stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
|
!stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
|
||||||
return Bailout(kForInStatementWithNonLocalEachVariable);
|
return Bailout(kForInStatementWithNonLocalEachVariable);
|
||||||
@ -5061,42 +5065,13 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
CHECK_ALIVE(VisitForValue(stmt->enumerable()));
|
CHECK_ALIVE(VisitForValue(stmt->enumerable()));
|
||||||
HValue* enumerable = Top(); // Leave enumerable at the top.
|
HValue* enumerable = Top(); // Leave enumerable at the top.
|
||||||
|
|
||||||
HInstruction* map;
|
HInstruction* map = Add<HForInPrepareMap>(enumerable);
|
||||||
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());
|
Add<HSimulate>(stmt->PrepareId());
|
||||||
|
|
||||||
array = Add<HForInCacheArray>(enumerable, map,
|
HInstruction* array = Add<HForInCacheArray>(
|
||||||
DescriptorArray::kEnumCacheBridgeCacheIndex);
|
enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
|
||||||
enum_length = Add<HMapEnumLength>(map);
|
|
||||||
|
|
||||||
HInstruction* index_cache = Add<HForInCacheArray>(
|
HInstruction* enum_length = Add<HMapEnumLength>(map);
|
||||||
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());
|
|
||||||
|
|
||||||
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* start_index = Add<HConstant>(0);
|
HInstruction* start_index = Add<HConstant>(0);
|
||||||
|
|
||||||
@ -5105,12 +5080,13 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
Push(enum_length);
|
Push(enum_length);
|
||||||
Push(start_index);
|
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);
|
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* index = environment()->ExpressionStackAt(0);
|
||||||
HValue* limit = environment()->ExpressionStackAt(1);
|
HValue* limit = environment()->ExpressionStackAt(1);
|
||||||
|
|
||||||
@ -5134,21 +5110,15 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
|||||||
|
|
||||||
HValue* key =
|
HValue* key =
|
||||||
Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache.
|
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.
|
// Check if the expected map still matches that of the enumerable.
|
||||||
// If not just deoptimize.
|
// If not just deoptimize.
|
||||||
Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3));
|
Add<HCheckMapValue>(environment()->ExpressionStackAt(4),
|
||||||
|
environment()->ExpressionStackAt(3));
|
||||||
|
|
||||||
Bind(each_var, key);
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
BreakAndContinueInfo break_info(stmt, scope(), 5);
|
BreakAndContinueInfo break_info(stmt, scope(), 5);
|
||||||
{
|
{
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
// 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();
|
|
Loading…
Reference in New Issue
Block a user