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/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
8 #include "src/compiler.h" | 8 #include "src/compiler.h" |
9 #include "src/compiler/ast-loop-assignment-analyzer.h" | 9 #include "src/compiler/ast-loop-assignment-analyzer.h" |
10 #include "src/compiler/control-builders.h" | 10 #include "src/compiler/control-builders.h" |
(...skipping 2799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2810 Node* right = environment()->Pop(); | 2810 Node* right = environment()->Pop(); |
2811 Node* left = environment()->Pop(); | 2811 Node* left = environment()->Pop(); |
2812 Node* value = BuildBinaryOp(left, right, expr->op(), | 2812 Node* value = BuildBinaryOp(left, right, expr->op(), |
2813 expr->BinaryOperationFeedbackId()); | 2813 expr->BinaryOperationFeedbackId()); |
2814 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); | 2814 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
2815 ast_context()->ProduceValue(value); | 2815 ast_context()->ProduceValue(value); |
2816 } | 2816 } |
2817 } | 2817 } |
2818 } | 2818 } |
2819 | 2819 |
| 2820 void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr, |
| 2821 Expression* sub_expr, |
| 2822 Node* nil_value) { |
| 2823 const Operator* op = nullptr; |
| 2824 switch (expr->op()) { |
| 2825 case Token::EQ: |
| 2826 op = javascript()->Equal(); |
| 2827 break; |
| 2828 case Token::EQ_STRICT: |
| 2829 op = javascript()->StrictEqual(); |
| 2830 break; |
| 2831 default: |
| 2832 UNREACHABLE(); |
| 2833 } |
| 2834 VisitForValue(sub_expr); |
| 2835 FrameStateBeforeAndAfter states(this, sub_expr->id()); |
| 2836 Node* value_to_compare = environment()->Pop(); |
| 2837 Node* value = NewNode(op, value_to_compare, nil_value); |
| 2838 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
| 2839 return ast_context()->ProduceValue(value); |
| 2840 } |
| 2841 |
| 2842 void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr, |
| 2843 Expression* sub_expr, |
| 2844 Handle<String> check) { |
| 2845 VisitTypeofExpression(sub_expr); |
| 2846 FrameStateBeforeAndAfter states(this, sub_expr->id()); |
| 2847 Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop()); |
| 2848 Node* value = NewNode(javascript()->StrictEqual(), typeof_arg, |
| 2849 jsgraph()->Constant(check)); |
| 2850 states.AddToNode(value, expr->id(), ast_context()->GetStateCombine()); |
| 2851 return ast_context()->ProduceValue(value); |
| 2852 } |
2820 | 2853 |
2821 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 2854 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 2855 // Check for a few fast cases. The AST visiting behavior must be in sync |
| 2856 // with the full codegen: We don't push both left and right values onto |
| 2857 // the expression stack when one side is a special-case literal. |
| 2858 Expression* sub_expr = nullptr; |
| 2859 Handle<String> check; |
| 2860 if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) { |
| 2861 return VisitLiteralCompareTypeof(expr, sub_expr, check); |
| 2862 } |
| 2863 if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) { |
| 2864 return VisitLiteralCompareNil(expr, sub_expr, |
| 2865 jsgraph()->UndefinedConstant()); |
| 2866 } |
| 2867 if (expr->IsLiteralCompareNull(&sub_expr)) { |
| 2868 return VisitLiteralCompareNil(expr, sub_expr, jsgraph()->NullConstant()); |
| 2869 } |
| 2870 |
2822 const Operator* op; | 2871 const Operator* op; |
2823 switch (expr->op()) { | 2872 switch (expr->op()) { |
2824 case Token::EQ: | 2873 case Token::EQ: |
2825 op = javascript()->Equal(); | 2874 op = javascript()->Equal(); |
2826 break; | 2875 break; |
2827 case Token::NE: | 2876 case Token::NE: |
2828 op = javascript()->NotEqual(); | 2877 op = javascript()->NotEqual(); |
2829 break; | 2878 break; |
2830 case Token::EQ_STRICT: | 2879 case Token::EQ_STRICT: |
2831 op = javascript()->StrictEqual(); | 2880 op = javascript()->StrictEqual(); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2973 ast_context()->ProduceValue(value); | 3022 ast_context()->ProduceValue(value); |
2974 } | 3023 } |
2975 | 3024 |
2976 | 3025 |
2977 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) { | 3026 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) { |
2978 VisitForEffect(expr->expression()); | 3027 VisitForEffect(expr->expression()); |
2979 Node* value = jsgraph()->UndefinedConstant(); | 3028 Node* value = jsgraph()->UndefinedConstant(); |
2980 ast_context()->ProduceValue(value); | 3029 ast_context()->ProduceValue(value); |
2981 } | 3030 } |
2982 | 3031 |
| 3032 void AstGraphBuilder::VisitTypeofExpression(Expression* expr) { |
| 3033 if (expr->IsVariableProxy()) { |
| 3034 // Typeof does not throw a reference error on global variables, hence we |
| 3035 // perform a non-contextual load in case the operand is a variable proxy. |
| 3036 VariableProxy* proxy = expr->AsVariableProxy(); |
| 3037 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
| 3038 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
| 3039 Node* load = |
| 3040 BuildVariableLoad(proxy->var(), expr->id(), states, pair, |
| 3041 OutputFrameStateCombine::Push(), INSIDE_TYPEOF); |
| 3042 environment()->Push(load); |
| 3043 } else { |
| 3044 VisitForValue(expr); |
| 3045 } |
| 3046 } |
2983 | 3047 |
2984 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 3048 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
2985 Node* operand; | 3049 VisitTypeofExpression(expr->expression()); |
2986 if (expr->expression()->IsVariableProxy()) { | 3050 Node* value = NewNode(javascript()->TypeOf(), environment()->Pop()); |
2987 // Typeof does not throw a reference error on global variables, hence we | |
2988 // perform a non-contextual load in case the operand is a variable proxy. | |
2989 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | |
2990 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | |
2991 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); | |
2992 operand = | |
2993 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, pair, | |
2994 OutputFrameStateCombine::Push(), INSIDE_TYPEOF); | |
2995 } else { | |
2996 VisitForValue(expr->expression()); | |
2997 operand = environment()->Pop(); | |
2998 } | |
2999 Node* value = NewNode(javascript()->TypeOf(), operand); | |
3000 ast_context()->ProduceValue(value); | 3051 ast_context()->ProduceValue(value); |
3001 } | 3052 } |
3002 | 3053 |
3003 | 3054 |
3004 void AstGraphBuilder::VisitNot(UnaryOperation* expr) { | 3055 void AstGraphBuilder::VisitNot(UnaryOperation* expr) { |
3005 VisitForValue(expr->expression()); | 3056 VisitForValue(expr->expression()); |
3006 Node* operand = environment()->Pop(); | 3057 Node* operand = environment()->Pop(); |
3007 Node* input = BuildToBoolean(operand, expr->expression()->test_id()); | 3058 Node* input = BuildToBoolean(operand, expr->expression()->test_id()); |
3008 Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input, | 3059 Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input, |
3009 jsgraph()->FalseConstant(), jsgraph()->TrueConstant()); | 3060 jsgraph()->FalseConstant(), jsgraph()->TrueConstant()); |
(...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4339 // Phi does not exist yet, introduce one. | 4390 // Phi does not exist yet, introduce one. |
4340 value = NewPhi(inputs, value, control); | 4391 value = NewPhi(inputs, value, control); |
4341 value->ReplaceInput(inputs - 1, other); | 4392 value->ReplaceInput(inputs - 1, other); |
4342 } | 4393 } |
4343 return value; | 4394 return value; |
4344 } | 4395 } |
4345 | 4396 |
4346 } // namespace compiler | 4397 } // namespace compiler |
4347 } // namespace internal | 4398 } // namespace internal |
4348 } // namespace v8 | 4399 } // namespace v8 |
OLD | NEW |