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 |