| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/ast-graph-builder.h" | 5 #include "src/compiler/ast-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
| 8 #include "src/compiler/ast-loop-assignment-analyzer.h" | 8 #include "src/compiler/ast-loop-assignment-analyzer.h" |
| 9 #include "src/compiler/control-builders.h" | 9 #include "src/compiler/control-builders.h" |
| 10 #include "src/compiler/machine-operator.h" | 10 #include "src/compiler/machine-operator.h" |
| (...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 695 have_no_properties.Then(); | 695 have_no_properties.Then(); |
| 696 // Pop obj and skip loop. | 696 // Pop obj and skip loop. |
| 697 environment()->Pop(); | 697 environment()->Pop(); |
| 698 have_no_properties.Else(); | 698 have_no_properties.Else(); |
| 699 { | 699 { |
| 700 // Construct the rest of the environment. | 700 // Construct the rest of the environment. |
| 701 environment()->Push(cache_type); | 701 environment()->Push(cache_type); |
| 702 environment()->Push(cache_array); | 702 environment()->Push(cache_array); |
| 703 environment()->Push(cache_length); | 703 environment()->Push(cache_length); |
| 704 environment()->Push(jsgraph()->ZeroConstant()); | 704 environment()->Push(jsgraph()->ZeroConstant()); |
| 705 // PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS); | 705 |
| 706 LoopBuilder for_loop(this); | 706 // Build the actual loop body. |
| 707 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), | 707 VisitForInBody(stmt); |
| 708 IsOsrLoopEntry(stmt)); | |
| 709 // Check loop termination condition. | |
| 710 Node* index = environment()->Peek(0); | |
| 711 Node* exit_cond = | |
| 712 NewNode(javascript()->LessThan(), index, cache_length); | |
| 713 // TODO(jarin): provide real bailout id. | |
| 714 PrepareFrameState(exit_cond, BailoutId::None()); | |
| 715 for_loop.BreakUnless(exit_cond); | |
| 716 // TODO(dcarney): this runtime call should be a handful of | |
| 717 // simplified instructions that | |
| 718 // basically produce | |
| 719 // value = array[index] | |
| 720 environment()->Push(obj); | |
| 721 environment()->Push(cache_array); | |
| 722 environment()->Push(cache_type); | |
| 723 environment()->Push(index); | |
| 724 Node* pair = ProcessArguments( | |
| 725 javascript()->CallRuntime(Runtime::kForInNext, 4), 4); | |
| 726 Node* value = NewNode(common()->Projection(0), pair); | |
| 727 Node* should_filter = NewNode(common()->Projection(1), pair); | |
| 728 environment()->Push(value); | |
| 729 { | |
| 730 // Test if FILTER_KEY needs to be called. | |
| 731 IfBuilder test_should_filter(this); | |
| 732 Node* should_filter_cond = | |
| 733 NewNode(javascript()->StrictEqual(), should_filter, | |
| 734 jsgraph()->TrueConstant()); | |
| 735 test_should_filter.If(should_filter_cond); | |
| 736 test_should_filter.Then(); | |
| 737 value = environment()->Pop(); | |
| 738 Node* builtins = BuildLoadBuiltinsObject(); | |
| 739 Node* function = BuildLoadObjectField( | |
| 740 builtins, | |
| 741 JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY)); | |
| 742 // Callee. | |
| 743 environment()->Push(function); | |
| 744 // Receiver. | |
| 745 environment()->Push(obj); | |
| 746 // Args. | |
| 747 environment()->Push(value); | |
| 748 // result is either the string key or Smi(0) indicating the property | |
| 749 // is gone. | |
| 750 Node* res = ProcessArguments( | |
| 751 javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), 3); | |
| 752 // TODO(jarin): provide real bailout id. | |
| 753 PrepareFrameState(res, BailoutId::None()); | |
| 754 Node* property_missing = NewNode(javascript()->StrictEqual(), res, | |
| 755 jsgraph()->ZeroConstant()); | |
| 756 { | |
| 757 IfBuilder is_property_missing(this); | |
| 758 is_property_missing.If(property_missing); | |
| 759 is_property_missing.Then(); | |
| 760 // Inc counter and continue. | |
| 761 Node* index_inc = | |
| 762 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | |
| 763 // TODO(jarin): provide real bailout id. | |
| 764 PrepareFrameState(index_inc, BailoutId::None()); | |
| 765 environment()->Poke(0, index_inc); | |
| 766 for_loop.Continue(); | |
| 767 is_property_missing.Else(); | |
| 768 is_property_missing.End(); | |
| 769 } | |
| 770 // Replace 'value' in environment. | |
| 771 environment()->Push(res); | |
| 772 test_should_filter.Else(); | |
| 773 test_should_filter.End(); | |
| 774 } | |
| 775 value = environment()->Pop(); | |
| 776 // Bind value and do loop body. | |
| 777 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); | |
| 778 VisitIterationBody(stmt, &for_loop, 5); | |
| 779 for_loop.EndBody(); | |
| 780 // Inc counter and continue. | |
| 781 Node* index_inc = | |
| 782 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); | |
| 783 // TODO(jarin): provide real bailout id. | |
| 784 PrepareFrameState(index_inc, BailoutId::None()); | |
| 785 environment()->Poke(0, index_inc); | |
| 786 for_loop.EndLoop(); | |
| 787 environment()->Drop(5); | |
| 788 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); | |
| 789 } | 708 } |
| 790 have_no_properties.End(); | 709 have_no_properties.End(); |
| 791 } | 710 } |
| 792 is_null.End(); | 711 is_null.End(); |
| 793 } | 712 } |
| 794 is_undefined.End(); | 713 is_undefined.End(); |
| 795 } | 714 } |
| 796 | 715 |
| 797 | 716 |
| 717 // TODO(dcarney): this is a big function. Try to clean up some. |
| 718 void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) { |
| 719 LoopBuilder for_loop(this); |
| 720 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), IsOsrLoopEntry(stmt)); |
| 721 |
| 722 // These stack values are renamed in the case of OSR, so reload them |
| 723 // from the environment. |
| 724 Node* index = environment()->Peek(0); |
| 725 Node* cache_length = environment()->Peek(1); |
| 726 Node* cache_array = environment()->Peek(2); |
| 727 Node* cache_type = environment()->Peek(3); |
| 728 Node* obj = environment()->Peek(4); |
| 729 |
| 730 // Check loop termination condition. |
| 731 Node* exit_cond = NewNode(javascript()->LessThan(), index, cache_length); |
| 732 // TODO(jarin): provide real bailout id. |
| 733 PrepareFrameState(exit_cond, BailoutId::None()); |
| 734 for_loop.BreakUnless(exit_cond); |
| 735 Node* pair = NewNode(javascript()->CallRuntime(Runtime::kForInNext, 4), obj, |
| 736 cache_array, cache_type, index); |
| 737 Node* value = NewNode(common()->Projection(0), pair); |
| 738 Node* should_filter = NewNode(common()->Projection(1), pair); |
| 739 environment()->Push(value); |
| 740 { |
| 741 // Test if FILTER_KEY needs to be called. |
| 742 IfBuilder test_should_filter(this); |
| 743 Node* should_filter_cond = NewNode( |
| 744 javascript()->StrictEqual(), should_filter, jsgraph()->TrueConstant()); |
| 745 test_should_filter.If(should_filter_cond); |
| 746 test_should_filter.Then(); |
| 747 value = environment()->Pop(); |
| 748 Node* builtins = BuildLoadBuiltinsObject(); |
| 749 Node* function = BuildLoadObjectField( |
| 750 builtins, |
| 751 JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY)); |
| 752 // Callee. |
| 753 environment()->Push(function); |
| 754 // Receiver. |
| 755 environment()->Push(obj); |
| 756 // Args. |
| 757 environment()->Push(value); |
| 758 // result is either the string key or Smi(0) indicating the property |
| 759 // is gone. |
| 760 Node* res = ProcessArguments( |
| 761 javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS), 3); |
| 762 // TODO(jarin): provide real bailout id. |
| 763 PrepareFrameState(res, BailoutId::None()); |
| 764 Node* property_missing = |
| 765 NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant()); |
| 766 { |
| 767 IfBuilder is_property_missing(this); |
| 768 is_property_missing.If(property_missing); |
| 769 is_property_missing.Then(); |
| 770 // Inc counter and continue. |
| 771 Node* index_inc = |
| 772 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
| 773 // TODO(jarin): provide real bailout id. |
| 774 PrepareFrameState(index_inc, BailoutId::None()); |
| 775 environment()->Poke(0, index_inc); |
| 776 for_loop.Continue(); |
| 777 is_property_missing.Else(); |
| 778 is_property_missing.End(); |
| 779 } |
| 780 // Replace 'value' in environment. |
| 781 environment()->Push(res); |
| 782 test_should_filter.Else(); |
| 783 test_should_filter.End(); |
| 784 } |
| 785 value = environment()->Pop(); |
| 786 // Bind value and do loop body. |
| 787 VisitForInAssignment(stmt->each(), value, stmt->AssignmentId()); |
| 788 VisitIterationBody(stmt, &for_loop, 5); |
| 789 for_loop.EndBody(); |
| 790 // Inc counter and continue. |
| 791 Node* index_inc = |
| 792 NewNode(javascript()->Add(), index, jsgraph()->OneConstant()); |
| 793 // TODO(jarin): provide real bailout id. |
| 794 PrepareFrameState(index_inc, BailoutId::None()); |
| 795 environment()->Poke(0, index_inc); |
| 796 for_loop.EndLoop(); |
| 797 environment()->Drop(5); |
| 798 // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS); |
| 799 } |
| 800 |
| 801 |
| 798 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { | 802 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) { |
| 799 LoopBuilder for_loop(this); | 803 LoopBuilder for_loop(this); |
| 800 VisitForEffect(stmt->assign_iterator()); | 804 VisitForEffect(stmt->assign_iterator()); |
| 801 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), IsOsrLoopEntry(stmt)); | 805 for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), IsOsrLoopEntry(stmt)); |
| 802 VisitForEffect(stmt->next_result()); | 806 VisitForEffect(stmt->next_result()); |
| 803 VisitForTest(stmt->result_done()); | 807 VisitForTest(stmt->result_done()); |
| 804 Node* condition = environment()->Pop(); | 808 Node* condition = environment()->Pop(); |
| 805 for_loop.BreakWhen(condition); | 809 for_loop.BreakWhen(condition); |
| 806 VisitForEffect(stmt->assign_each()); | 810 VisitForEffect(stmt->assign_each()); |
| 807 VisitIterationBody(stmt, &for_loop, 0); | 811 VisitIterationBody(stmt, &for_loop, 0); |
| (...skipping 1628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2436 | 2440 |
| 2437 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( | 2441 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop( |
| 2438 IterationStatement* stmt) { | 2442 IterationStatement* stmt) { |
| 2439 if (loop_assignment_analysis_ == NULL) return NULL; | 2443 if (loop_assignment_analysis_ == NULL) return NULL; |
| 2440 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); | 2444 return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt); |
| 2441 } | 2445 } |
| 2442 | 2446 |
| 2443 } // namespace compiler | 2447 } // namespace compiler |
| 2444 } // namespace internal | 2448 } // namespace internal |
| 2445 } // namespace v8 | 2449 } // namespace v8 |
| OLD | NEW |