Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Unified Diff: src/hydrogen.cc

Issue 1086333002: Reland "Add basic crankshaft support for slow-mode for-in to avoid disabling optimizations" (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Just give up if null or undefined. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/hydrogen.cc
diff --git a/src/hydrogen.cc b/src/hydrogen.cc
index 393e02c9f97ba6381ad0697aa220dfe2df319d63..46f0bfe04370879dd148a56b9071d27640d6ea67 100644
--- a/src/hydrogen.cc
+++ b/src/hydrogen.cc
@@ -5051,10 +5051,6 @@ 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);
@@ -5065,13 +5061,57 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
CHECK_ALIVE(VisitForValue(stmt->enumerable()));
HValue* enumerable = Top(); // Leave enumerable at the top.
- HInstruction* map = Add<HForInPrepareMap>(enumerable);
- Add<HSimulate>(stmt->PrepareId());
-
- HInstruction* array = Add<HForInCacheArray>(
- enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
+ IfBuilder if_undefined_or_null(this);
+ if_undefined_or_null.If<HCompareObjectEqAndBranch>(
+ enumerable, graph()->GetConstantUndefined());
+ if_undefined_or_null.Or();
+ if_undefined_or_null.If<HCompareObjectEqAndBranch>(
+ enumerable, graph()->GetConstantNull());
+ if_undefined_or_null.ThenDeopt(Deoptimizer::kUndefinedOrNullInForIn);
+ if_undefined_or_null.End();
+ BuildForInBody(stmt, each_var, enumerable);
+}
+
+
+void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
+ Variable* each_var,
+ HValue* enumerable) {
+ 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* enum_length = Add<HMapEnumLength>(map);
+ 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);
@@ -5080,13 +5120,12 @@ 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);
@@ -5110,15 +5149,21 @@ void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
HValue* key =
Add<HLoadKeyed>(environment()->ExpressionStackAt(2), // Enum cache.
- environment()->ExpressionStackAt(0), // Iteration index.
- environment()->ExpressionStackAt(0), FAST_ELEMENTS);
+ index, index, FAST_ELEMENTS);
- // 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);
+ 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);
+ }
BreakAndContinueInfo break_info(stmt, scope(), 5);
{
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/lithium-codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698