Index: src/compiler/ast-graph-builder.cc |
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
index 7b62443ca1ecd0a59a450abef8371450bbd07683..ce9accc0432af3c69ed472c7502cc4b2fbe193a7 100644 |
--- a/src/compiler/ast-graph-builder.cc |
+++ b/src/compiler/ast-graph-builder.cc |
@@ -702,90 +702,9 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
environment()->Push(cache_array); |
environment()->Push(cache_length); |
environment()->Push(jsgraph()->ZeroConstant()); |
- // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); |
- LoopBuilder for_loop(this); |
- for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), |
- IsOsrLoopEntry(stmt)); |
- // Check loop termination condition. |
- Node* index = environment()->Peek(0); |
- Node* exit_cond = |
- NewNode(javascript()->LessThan(), index, cache_length); |
- // TODO(jarin): provide real bailout id. |
- PrepareFrameState(exit_cond, BailoutId::None()); |
- for_loop.BreakUnless(exit_cond); |
- // TODO(dcarney): this runtime call should be a handful of |
- // simplified instructions that |
- // basically produce |
- // value = array[index] |
- environment()->Push(obj); |
- environment()->Push(cache_array); |
- environment()->Push(cache_type); |
- environment()->Push(index); |
- Node* pair = ProcessArguments( |
- javascript()->CallRuntime(Runtime::kForInNext, 4), 4); |
- Node* value = NewNode(common()->Projection(0), pair); |
- Node* should_filter = NewNode(common()->Projection(1), pair); |
- environment()->Push(value); |
- { |
- // Test if FILTER_KEY needs to be called. |
- IfBuilder test_should_filter(this); |
- Node* should_filter_cond = |
- NewNode(javascript()->StrictEqual(), should_filter, |
- jsgraph()->TrueConstant()); |
- test_should_filter.If(should_filter_cond); |
- test_should_filter.Then(); |
- value = environment()->Pop(); |
- Node* builtins = BuildLoadBuiltinsObject(); |
- Node* function = BuildLoadObjectField( |
- builtins, |
- JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY)); |
- // Callee. |
- environment()->Push(function); |
- // Receiver. |
- environment()->Push(obj); |
- // Args. |
- environment()->Push(value); |
- // result is either the string key or Smi(0) indicating the property |
- // is gone. |
- Node* res = ProcessArguments( |
- javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), 3); |
- // TODO(jarin): provide real bailout id. |
- PrepareFrameState(res, BailoutId::None()); |
- Node* property_missing = NewNode(javascript()->StrictEqual(), res, |
- jsgraph()->ZeroConstant()); |
- { |
- IfBuilder is_property_missing(this); |
- is_property_missing.If(property_missing); |
- is_property_missing.Then(); |
- // Inc counter and continue. |
- Node* index_inc = |
- NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
- // TODO(jarin): provide real bailout id. |
- PrepareFrameState(index_inc, BailoutId::None()); |
- environment()->Poke(0, index_inc); |
- for_loop.Continue(); |
- is_property_missing.Else(); |
- is_property_missing.End(); |
- } |
- // Replace 'value' in environment. |
- environment()->Push(res); |
- test_should_filter.Else(); |
- test_should_filter.End(); |
- } |
- value = environment()->Pop(); |
- // Bind value and do loop body. |
- VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); |
- VisitIterationBody(stmt, &for_loop, 5); |
- for_loop.EndBody(); |
- // Inc counter and continue. |
- Node* index_inc = |
- NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
- // TODO(jarin): provide real bailout id. |
- PrepareFrameState(index_inc, BailoutId::None()); |
- environment()->Poke(0, index_inc); |
- for_loop.EndLoop(); |
- environment()->Drop(5); |
- // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
+ |
+ // Build the actual loop body. |
+ VisitForInBody(stmt); |
} |
have_no_properties.End(); |
} |
@@ -795,6 +714,91 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) { |
} |
+// TODO(dcarney): this is a big function. Try to clean up some. |
+void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) { |
+ LoopBuilder for_loop(this); |
+ for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), IsOsrLoopEntry(stmt)); |
+ |
+ // These stack values are renamed in the case of OSR, so reload them |
+ // from the environment. |
+ Node* index = environment()->Peek(0); |
+ Node* cache_length = environment()->Peek(1); |
+ Node* cache_array = environment()->Peek(2); |
+ Node* cache_type = environment()->Peek(3); |
+ Node* obj = environment()->Peek(4); |
+ |
+ // Check loop termination condition. |
+ Node* exit_cond = NewNode(javascript()->LessThan(), index, cache_length); |
+ // TODO(jarin): provide real bailout id. |
+ PrepareFrameState(exit_cond, BailoutId::None()); |
+ for_loop.BreakUnless(exit_cond); |
+ Node* pair = NewNode(javascript()->CallRuntime(Runtime::kForInNext, 4), obj, |
+ cache_array, cache_type, index); |
+ Node* value = NewNode(common()->Projection(0), pair); |
+ Node* should_filter = NewNode(common()->Projection(1), pair); |
+ environment()->Push(value); |
+ { |
+ // Test if FILTER_KEY needs to be called. |
+ IfBuilder test_should_filter(this); |
+ Node* should_filter_cond = NewNode( |
+ javascript()->StrictEqual(), should_filter, jsgraph()->TrueConstant()); |
+ test_should_filter.If(should_filter_cond); |
+ test_should_filter.Then(); |
+ value = environment()->Pop(); |
+ Node* builtins = BuildLoadBuiltinsObject(); |
+ Node* function = BuildLoadObjectField( |
+ builtins, |
+ JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY)); |
+ // Callee. |
+ environment()->Push(function); |
+ // Receiver. |
+ environment()->Push(obj); |
+ // Args. |
+ environment()->Push(value); |
+ // result is either the string key or Smi(0) indicating the property |
+ // is gone. |
+ Node* res = ProcessArguments( |
+ javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), 3); |
+ // TODO(jarin): provide real bailout id. |
+ PrepareFrameState(res, BailoutId::None()); |
+ Node* property_missing = |
+ NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant()); |
+ { |
+ IfBuilder is_property_missing(this); |
+ is_property_missing.If(property_missing); |
+ is_property_missing.Then(); |
+ // Inc counter and continue. |
+ Node* index_inc = |
+ NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
+ // TODO(jarin): provide real bailout id. |
+ PrepareFrameState(index_inc, BailoutId::None()); |
+ environment()->Poke(0, index_inc); |
+ for_loop.Continue(); |
+ is_property_missing.Else(); |
+ is_property_missing.End(); |
+ } |
+ // Replace 'value' in environment. |
+ environment()->Push(res); |
+ test_should_filter.Else(); |
+ test_should_filter.End(); |
+ } |
+ value = environment()->Pop(); |
+ // Bind value and do loop body. |
+ VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); |
+ VisitIterationBody(stmt, &for_loop, 5); |
+ for_loop.EndBody(); |
+ // Inc counter and continue. |
+ Node* index_inc = |
+ NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
+ // TODO(jarin): provide real bailout id. |
+ PrepareFrameState(index_inc, BailoutId::None()); |
+ environment()->Poke(0, index_inc); |
+ for_loop.EndLoop(); |
+ environment()->Drop(5); |
+ // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
+} |
+ |
+ |
void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
LoopBuilder for_loop(this); |
VisitForEffect(stmt->assign_iterator()); |