| 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/js-type-feedback.h" | 10 #include "src/compiler/js-type-feedback.h" |
| (...skipping 1694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1705 // Transform both the class literal and the prototype to fast properties. | 1705 // Transform both the class literal and the prototype to fast properties. |
| 1706 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); | 1706 const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1); |
| 1707 NewNode(op, environment()->Pop()); // prototype | 1707 NewNode(op, environment()->Pop()); // prototype |
| 1708 NewNode(op, environment()->Pop()); // literal | 1708 NewNode(op, environment()->Pop()); // literal |
| 1709 | 1709 |
| 1710 // Assign to class variable. | 1710 // Assign to class variable. |
| 1711 if (expr->scope() != NULL) { | 1711 if (expr->scope() != NULL) { |
| 1712 DCHECK_NOT_NULL(expr->class_variable_proxy()); | 1712 DCHECK_NOT_NULL(expr->class_variable_proxy()); |
| 1713 Variable* var = expr->class_variable_proxy()->var(); | 1713 Variable* var = expr->class_variable_proxy()->var(); |
| 1714 FrameStateBeforeAndAfter states(this, BailoutId::None()); | 1714 FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| 1715 BuildVariableAssignment(states, var, literal, Token::INIT_CONST, | 1715 BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None(), |
| 1716 BailoutId::None()); | 1716 states); |
| 1717 } | 1717 } |
| 1718 | 1718 |
| 1719 ast_context()->ProduceValue(literal); | 1719 ast_context()->ProduceValue(literal); |
| 1720 } | 1720 } |
| 1721 | 1721 |
| 1722 | 1722 |
| 1723 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { | 1723 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) { |
| 1724 UNREACHABLE(); | 1724 UNREACHABLE(); |
| 1725 } | 1725 } |
| 1726 | 1726 |
| 1727 | 1727 |
| 1728 void AstGraphBuilder::VisitConditional(Conditional* expr) { | 1728 void AstGraphBuilder::VisitConditional(Conditional* expr) { |
| 1729 IfBuilder compare_if(this); | 1729 IfBuilder compare_if(this); |
| 1730 VisitForTest(expr->condition()); | 1730 VisitForTest(expr->condition()); |
| 1731 Node* condition = environment()->Pop(); | 1731 Node* condition = environment()->Pop(); |
| 1732 compare_if.If(condition); | 1732 compare_if.If(condition); |
| 1733 compare_if.Then(); | 1733 compare_if.Then(); |
| 1734 Visit(expr->then_expression()); | 1734 Visit(expr->then_expression()); |
| 1735 compare_if.Else(); | 1735 compare_if.Else(); |
| 1736 Visit(expr->else_expression()); | 1736 Visit(expr->else_expression()); |
| 1737 compare_if.End(); | 1737 compare_if.End(); |
| 1738 ast_context()->ReplaceValue(); | 1738 ast_context()->ReplaceValue(); |
| 1739 } | 1739 } |
| 1740 | 1740 |
| 1741 | 1741 |
| 1742 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 1742 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 1743 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot()); | 1743 VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot()); |
| 1744 FrameStateBeforeAndAfter states(this, BeforeId(expr)); | 1744 FrameStateBeforeAndAfter states(this, BeforeId(expr)); |
| 1745 Node* value = BuildVariableLoad(states, expr->var(), expr->id(), pair, | 1745 Node* value = BuildVariableLoad(expr->var(), expr->id(), states, pair, |
| 1746 ast_context()->GetStateCombine()); | 1746 ast_context()->GetStateCombine()); |
| 1747 ast_context()->ProduceValue(value); | 1747 ast_context()->ProduceValue(value); |
| 1748 } | 1748 } |
| 1749 | 1749 |
| 1750 | 1750 |
| 1751 void AstGraphBuilder::VisitLiteral(Literal* expr) { | 1751 void AstGraphBuilder::VisitLiteral(Literal* expr) { |
| 1752 Node* value = jsgraph()->Constant(expr->value()); | 1752 Node* value = jsgraph()->Constant(expr->value()); |
| 1753 ast_context()->ProduceValue(value); | 1753 ast_context()->ProduceValue(value); |
| 1754 } | 1754 } |
| 1755 | 1755 |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2047 | 2047 |
| 2048 // Left-hand side can only be a property, a global or a variable slot. | 2048 // Left-hand side can only be a property, a global or a variable slot. |
| 2049 Property* property = expr->AsProperty(); | 2049 Property* property = expr->AsProperty(); |
| 2050 LhsKind assign_type = DetermineLhsKind(expr); | 2050 LhsKind assign_type = DetermineLhsKind(expr); |
| 2051 | 2051 |
| 2052 // Evaluate LHS expression and store the value. | 2052 // Evaluate LHS expression and store the value. |
| 2053 switch (assign_type) { | 2053 switch (assign_type) { |
| 2054 case VARIABLE: { | 2054 case VARIABLE: { |
| 2055 Variable* var = expr->AsVariableProxy()->var(); | 2055 Variable* var = expr->AsVariableProxy()->var(); |
| 2056 FrameStateBeforeAndAfter states(this, BailoutId::None()); | 2056 FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| 2057 BuildVariableAssignment(states, var, value, Token::ASSIGN, bailout_id); | 2057 BuildVariableAssignment(var, value, Token::ASSIGN, bailout_id, states); |
| 2058 break; | 2058 break; |
| 2059 } | 2059 } |
| 2060 case NAMED_PROPERTY: { | 2060 case NAMED_PROPERTY: { |
| 2061 environment()->Push(value); | 2061 environment()->Push(value); |
| 2062 VisitForValue(property->obj()); | 2062 VisitForValue(property->obj()); |
| 2063 FrameStateBeforeAndAfter states(this, property->obj()->id()); | 2063 FrameStateBeforeAndAfter states(this, property->obj()->id()); |
| 2064 Node* object = environment()->Pop(); | 2064 Node* object = environment()->Pop(); |
| 2065 value = environment()->Pop(); | 2065 value = environment()->Pop(); |
| 2066 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | 2066 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2067 Node* store = | 2067 Node* store = |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2119 // the left-hand side value and performing a binary operation. | 2119 // the left-hand side value and performing a binary operation. |
| 2120 if (expr->is_compound()) { | 2120 if (expr->is_compound()) { |
| 2121 Node* old_value = NULL; | 2121 Node* old_value = NULL; |
| 2122 switch (assign_type) { | 2122 switch (assign_type) { |
| 2123 case VARIABLE: { | 2123 case VARIABLE: { |
| 2124 VariableProxy* proxy = expr->target()->AsVariableProxy(); | 2124 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 2125 VectorSlotPair pair = | 2125 VectorSlotPair pair = |
| 2126 CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | 2126 CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
| 2127 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); | 2127 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
| 2128 old_value = | 2128 old_value = |
| 2129 BuildVariableLoad(states, proxy->var(), expr->target()->id(), pair, | 2129 BuildVariableLoad(proxy->var(), expr->target()->id(), states, pair, |
| 2130 OutputFrameStateCombine::Push()); | 2130 OutputFrameStateCombine::Push()); |
| 2131 break; | 2131 break; |
| 2132 } | 2132 } |
| 2133 case NAMED_PROPERTY: { | 2133 case NAMED_PROPERTY: { |
| 2134 Node* object = environment()->Top(); | 2134 Node* object = environment()->Top(); |
| 2135 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | 2135 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2136 VectorSlotPair pair = | 2136 VectorSlotPair pair = |
| 2137 CreateVectorSlotPair(property->PropertyFeedbackSlot()); | 2137 CreateVectorSlotPair(property->PropertyFeedbackSlot()); |
| 2138 FrameStateBeforeAndAfter states(this, property->obj()->id()); | 2138 FrameStateBeforeAndAfter states(this, property->obj()->id()); |
| 2139 old_value = BuildNamedLoad(object, name, pair); | 2139 old_value = BuildNamedLoad(object, name, pair); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2174 before_store_id = expr->value()->id(); | 2174 before_store_id = expr->value()->id(); |
| 2175 } | 2175 } |
| 2176 } | 2176 } |
| 2177 | 2177 |
| 2178 FrameStateBeforeAndAfter store_states(this, before_store_id); | 2178 FrameStateBeforeAndAfter store_states(this, before_store_id); |
| 2179 // Store the value. | 2179 // Store the value. |
| 2180 Node* value = environment()->Pop(); | 2180 Node* value = environment()->Pop(); |
| 2181 switch (assign_type) { | 2181 switch (assign_type) { |
| 2182 case VARIABLE: { | 2182 case VARIABLE: { |
| 2183 Variable* variable = expr->target()->AsVariableProxy()->var(); | 2183 Variable* variable = expr->target()->AsVariableProxy()->var(); |
| 2184 BuildVariableAssignment(store_states, variable, value, expr->op(), | 2184 BuildVariableAssignment(variable, value, expr->op(), expr->id(), |
| 2185 expr->id(), ast_context()->GetStateCombine()); | 2185 store_states, ast_context()->GetStateCombine()); |
| 2186 break; | 2186 break; |
| 2187 } | 2187 } |
| 2188 case NAMED_PROPERTY: { | 2188 case NAMED_PROPERTY: { |
| 2189 Node* object = environment()->Pop(); | 2189 Node* object = environment()->Pop(); |
| 2190 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | 2190 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2191 Node* store = | 2191 Node* store = |
| 2192 BuildNamedStore(object, name, value, expr->AssignmentFeedbackId()); | 2192 BuildNamedStore(object, name, value, expr->AssignmentFeedbackId()); |
| 2193 store_states.AddToNode(store, expr->id(), | 2193 store_states.AddToNode(store, expr->id(), |
| 2194 ast_context()->GetStateCombine()); | 2194 ast_context()->GetStateCombine()); |
| 2195 break; | 2195 break; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2263 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; | 2263 CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS; |
| 2264 Node* receiver_value = NULL; | 2264 Node* receiver_value = NULL; |
| 2265 Node* callee_value = NULL; | 2265 Node* callee_value = NULL; |
| 2266 bool possibly_eval = false; | 2266 bool possibly_eval = false; |
| 2267 switch (call_type) { | 2267 switch (call_type) { |
| 2268 case Call::GLOBAL_CALL: { | 2268 case Call::GLOBAL_CALL: { |
| 2269 VariableProxy* proxy = callee->AsVariableProxy(); | 2269 VariableProxy* proxy = callee->AsVariableProxy(); |
| 2270 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | 2270 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
| 2271 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); | 2271 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
| 2272 callee_value = | 2272 callee_value = |
| 2273 BuildVariableLoad(states, proxy->var(), expr->expression()->id(), | 2273 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, |
| 2274 pair, OutputFrameStateCombine::Push()); | 2274 pair, OutputFrameStateCombine::Push()); |
| 2275 receiver_value = jsgraph()->UndefinedConstant(); | 2275 receiver_value = jsgraph()->UndefinedConstant(); |
| 2276 break; | 2276 break; |
| 2277 } | 2277 } |
| 2278 case Call::LOOKUP_SLOT_CALL: { | 2278 case Call::LOOKUP_SLOT_CALL: { |
| 2279 Variable* variable = callee->AsVariableProxy()->var(); | 2279 Variable* variable = callee->AsVariableProxy()->var(); |
| 2280 DCHECK(variable->location() == Variable::LOOKUP); | 2280 DCHECK(variable->location() == Variable::LOOKUP); |
| 2281 Node* name = jsgraph()->Constant(variable->name()); | 2281 Node* name = jsgraph()->Constant(variable->name()); |
| 2282 const Operator* op = | 2282 const Operator* op = |
| 2283 javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2); | 2283 javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2); |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2491 | 2491 |
| 2492 // Evaluate LHS expression and get old value. | 2492 // Evaluate LHS expression and get old value. |
| 2493 Node* old_value = NULL; | 2493 Node* old_value = NULL; |
| 2494 int stack_depth = -1; | 2494 int stack_depth = -1; |
| 2495 switch (assign_type) { | 2495 switch (assign_type) { |
| 2496 case VARIABLE: { | 2496 case VARIABLE: { |
| 2497 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2497 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2498 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | 2498 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
| 2499 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); | 2499 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
| 2500 old_value = | 2500 old_value = |
| 2501 BuildVariableLoad(states, proxy->var(), expr->expression()->id(), | 2501 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, |
| 2502 pair, OutputFrameStateCombine::Push()); | 2502 pair, OutputFrameStateCombine::Push()); |
| 2503 stack_depth = 0; | 2503 stack_depth = 0; |
| 2504 break; | 2504 break; |
| 2505 } | 2505 } |
| 2506 case NAMED_PROPERTY: { | 2506 case NAMED_PROPERTY: { |
| 2507 VisitForValue(property->obj()); | 2507 VisitForValue(property->obj()); |
| 2508 FrameStateBeforeAndAfter states(this, property->obj()->id()); | 2508 FrameStateBeforeAndAfter states(this, property->obj()->id()); |
| 2509 Node* object = environment()->Top(); | 2509 Node* object = environment()->Top(); |
| 2510 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | 2510 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2511 VectorSlotPair pair = | 2511 VectorSlotPair pair = |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2555 // before. | 2555 // before. |
| 2556 states.AddToNode(value, BailoutId::None(), | 2556 states.AddToNode(value, BailoutId::None(), |
| 2557 OutputFrameStateCombine::Ignore()); | 2557 OutputFrameStateCombine::Ignore()); |
| 2558 } | 2558 } |
| 2559 | 2559 |
| 2560 // Store the value. | 2560 // Store the value. |
| 2561 switch (assign_type) { | 2561 switch (assign_type) { |
| 2562 case VARIABLE: { | 2562 case VARIABLE: { |
| 2563 Variable* variable = expr->expression()->AsVariableProxy()->var(); | 2563 Variable* variable = expr->expression()->AsVariableProxy()->var(); |
| 2564 environment()->Push(value); | 2564 environment()->Push(value); |
| 2565 BuildVariableAssignment(store_states, variable, value, expr->op(), | 2565 BuildVariableAssignment(variable, value, expr->op(), expr->AssignmentId(), |
| 2566 expr->AssignmentId()); | 2566 store_states); |
| 2567 environment()->Pop(); | 2567 environment()->Pop(); |
| 2568 break; | 2568 break; |
| 2569 } | 2569 } |
| 2570 case NAMED_PROPERTY: { | 2570 case NAMED_PROPERTY: { |
| 2571 Node* object = environment()->Pop(); | 2571 Node* object = environment()->Pop(); |
| 2572 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); | 2572 Handle<Name> name = property->key()->AsLiteral()->AsPropertyName(); |
| 2573 Node* store = | 2573 Node* store = |
| 2574 BuildNamedStore(object, name, value, expr->CountStoreFeedbackId()); | 2574 BuildNamedStore(object, name, value, expr->CountStoreFeedbackId()); |
| 2575 environment()->Push(value); | 2575 environment()->Push(value); |
| 2576 store_states.AddToNode(store, expr->AssignmentId(), | 2576 store_states.AddToNode(store, expr->AssignmentId(), |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2759 | 2759 |
| 2760 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { | 2760 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) { |
| 2761 Node* operand; | 2761 Node* operand; |
| 2762 if (expr->expression()->IsVariableProxy()) { | 2762 if (expr->expression()->IsVariableProxy()) { |
| 2763 // Typeof does not throw a reference error on global variables, hence we | 2763 // Typeof does not throw a reference error on global variables, hence we |
| 2764 // perform a non-contextual load in case the operand is a variable proxy. | 2764 // perform a non-contextual load in case the operand is a variable proxy. |
| 2765 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 2765 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 2766 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); | 2766 VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot()); |
| 2767 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); | 2767 FrameStateBeforeAndAfter states(this, BeforeId(proxy)); |
| 2768 operand = | 2768 operand = |
| 2769 BuildVariableLoad(states, proxy->var(), expr->expression()->id(), pair, | 2769 BuildVariableLoad(proxy->var(), expr->expression()->id(), states, pair, |
| 2770 OutputFrameStateCombine::Push(), NOT_CONTEXTUAL); | 2770 OutputFrameStateCombine::Push(), NOT_CONTEXTUAL); |
| 2771 } else { | 2771 } else { |
| 2772 VisitForValue(expr->expression()); | 2772 VisitForValue(expr->expression()); |
| 2773 operand = environment()->Pop(); | 2773 operand = environment()->Pop(); |
| 2774 } | 2774 } |
| 2775 Node* value = NewNode(javascript()->TypeOf(), operand); | 2775 Node* value = NewNode(javascript()->TypeOf(), operand); |
| 2776 ast_context()->ProduceValue(value); | 2776 ast_context()->ProduceValue(value); |
| 2777 } | 2777 } |
| 2778 | 2778 |
| 2779 | 2779 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2935 | 2935 |
| 2936 // Allocate and initialize a new arguments object. | 2936 // Allocate and initialize a new arguments object. |
| 2937 Node* callee = GetFunctionClosure(); | 2937 Node* callee = GetFunctionClosure(); |
| 2938 const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1); | 2938 const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1); |
| 2939 Node* object = NewNode(op, callee); | 2939 Node* object = NewNode(op, callee); |
| 2940 | 2940 |
| 2941 // Assign the object to the arguments variable. | 2941 // Assign the object to the arguments variable. |
| 2942 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); | 2942 DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated()); |
| 2943 // This should never lazy deopt, so it is fine to send invalid bailout id. | 2943 // This should never lazy deopt, so it is fine to send invalid bailout id. |
| 2944 FrameStateBeforeAndAfter states(this, BailoutId::None()); | 2944 FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| 2945 BuildVariableAssignment(states, arguments, object, Token::ASSIGN, | 2945 BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None(), |
| 2946 BailoutId::None()); | 2946 states); |
| 2947 | 2947 |
| 2948 return object; | 2948 return object; |
| 2949 } | 2949 } |
| 2950 | 2950 |
| 2951 | 2951 |
| 2952 Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) { | 2952 Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) { |
| 2953 if (rest == NULL) return NULL; | 2953 if (rest == NULL) return NULL; |
| 2954 | 2954 |
| 2955 DCHECK(index >= 0); | 2955 DCHECK(index >= 0); |
| 2956 const Operator* op = javascript()->CallRuntime(Runtime::kNewRestParamSlow, 1); | 2956 const Operator* op = javascript()->CallRuntime(Runtime::kNewRestParamSlow, 1); |
| 2957 Node* object = NewNode(op, jsgraph()->SmiConstant(index)); | 2957 Node* object = NewNode(op, jsgraph()->SmiConstant(index)); |
| 2958 | 2958 |
| 2959 // Assign the object to the rest array | 2959 // Assign the object to the rest array |
| 2960 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); | 2960 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated()); |
| 2961 // This should never lazy deopt, so it is fine to send invalid bailout id. | 2961 // This should never lazy deopt, so it is fine to send invalid bailout id. |
| 2962 FrameStateBeforeAndAfter states(this, BailoutId::None()); | 2962 FrameStateBeforeAndAfter states(this, BailoutId::None()); |
| 2963 BuildVariableAssignment(states, rest, object, Token::ASSIGN, | 2963 BuildVariableAssignment(rest, object, Token::ASSIGN, BailoutId::None(), |
| 2964 BailoutId::None()); | 2964 states); |
| 2965 | 2965 |
| 2966 return object; | 2966 return object; |
| 2967 } | 2967 } |
| 2968 | 2968 |
| 2969 | 2969 |
| 2970 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, | 2970 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole, |
| 2971 Node* not_hole) { | 2971 Node* not_hole) { |
| 2972 Node* the_hole = jsgraph()->TheHoleConstant(); | 2972 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 2973 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); | 2973 Node* check = NewNode(javascript()->StrictEqual(), value, the_hole); |
| 2974 return NewNode(common()->Select(kMachAnyTagged, BranchHint::kFalse), check, | 2974 return NewNode(common()->Select(kMachAnyTagged, BranchHint::kFalse), check, |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3003 prototype_check.Then(); | 3003 prototype_check.Then(); |
| 3004 Node* error = BuildThrowStaticPrototypeError(bailout_id); | 3004 Node* error = BuildThrowStaticPrototypeError(bailout_id); |
| 3005 environment()->Push(error); | 3005 environment()->Push(error); |
| 3006 prototype_check.Else(); | 3006 prototype_check.Else(); |
| 3007 environment()->Push(name); | 3007 environment()->Push(name); |
| 3008 prototype_check.End(); | 3008 prototype_check.End(); |
| 3009 return environment()->Pop(); | 3009 return environment()->Pop(); |
| 3010 } | 3010 } |
| 3011 | 3011 |
| 3012 | 3012 |
| 3013 Node* AstGraphBuilder::BuildVariableLoad(FrameStateBeforeAndAfter& states, | 3013 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, |
| 3014 Variable* variable, | |
| 3015 BailoutId bailout_id, | 3014 BailoutId bailout_id, |
| 3015 FrameStateBeforeAndAfter& states, |
| 3016 const VectorSlotPair& feedback, | 3016 const VectorSlotPair& feedback, |
| 3017 OutputFrameStateCombine combine, | 3017 OutputFrameStateCombine combine, |
| 3018 ContextualMode contextual_mode) { | 3018 ContextualMode contextual_mode) { |
| 3019 Node* the_hole = jsgraph()->TheHoleConstant(); | 3019 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 3020 VariableMode mode = variable->mode(); | 3020 VariableMode mode = variable->mode(); |
| 3021 switch (variable->location()) { | 3021 switch (variable->location()) { |
| 3022 case Variable::UNALLOCATED: { | 3022 case Variable::UNALLOCATED: { |
| 3023 // Global var, const, or let variable. | 3023 // Global var, const, or let variable. |
| 3024 Node* global = BuildLoadGlobalObject(); | 3024 return BuildGlobalVariableLoad(variable, bailout_id, states, feedback, |
| 3025 Handle<Name> name = variable->name(); | 3025 combine, contextual_mode); |
| 3026 Node* node = BuildNamedLoad(global, name, feedback, contextual_mode); | |
| 3027 states.AddToNode(node, bailout_id, combine); | |
| 3028 return node; | |
| 3029 } | 3026 } |
| 3030 case Variable::PARAMETER: | 3027 case Variable::PARAMETER: |
| 3031 case Variable::LOCAL: { | 3028 case Variable::LOCAL: { |
| 3032 // Local var, const, or let variable. | 3029 // Local var, const, or let variable. |
| 3033 Node* value = environment()->Lookup(variable); | 3030 Node* value = environment()->Lookup(variable); |
| 3034 if (mode == CONST_LEGACY) { | 3031 if (mode == CONST_LEGACY) { |
| 3035 // Perform check for uninitialized legacy const variables. | 3032 // Perform check for uninitialized legacy const variables. |
| 3036 if (value->op() == the_hole->op()) { | 3033 if (value->op() == the_hole->op()) { |
| 3037 value = jsgraph()->UndefinedConstant(); | 3034 value = jsgraph()->UndefinedConstant(); |
| 3038 } else if (value->opcode() == IrOpcode::kPhi) { | 3035 } else if (value->opcode() == IrOpcode::kPhi) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 3064 Node* undefined = jsgraph()->UndefinedConstant(); | 3061 Node* undefined = jsgraph()->UndefinedConstant(); |
| 3065 value = BuildHoleCheckSilent(value, undefined, value); | 3062 value = BuildHoleCheckSilent(value, undefined, value); |
| 3066 } else if (mode == LET || mode == CONST) { | 3063 } else if (mode == LET || mode == CONST) { |
| 3067 // Perform check for uninitialized let/const variables. | 3064 // Perform check for uninitialized let/const variables. |
| 3068 value = BuildHoleCheckThrow(value, variable, value, bailout_id); | 3065 value = BuildHoleCheckThrow(value, variable, value, bailout_id); |
| 3069 } | 3066 } |
| 3070 return value; | 3067 return value; |
| 3071 } | 3068 } |
| 3072 case Variable::LOOKUP: { | 3069 case Variable::LOOKUP: { |
| 3073 // Dynamic lookup of context variable (anywhere in the chain). | 3070 // Dynamic lookup of context variable (anywhere in the chain). |
| 3074 Node* name = jsgraph()->Constant(variable->name()); | 3071 if (mode == DYNAMIC_GLOBAL) { |
| 3075 Runtime::FunctionId function_id = | 3072 // Try to optimize known global when not shadowed. |
| 3076 (contextual_mode == CONTEXTUAL) | 3073 if (Node* fast_value = TryDynamicGlobalVariableLoad( |
| 3077 ? Runtime::kLoadLookupSlot | 3074 variable, bailout_id, states, feedback, combine, |
| 3078 : Runtime::kLoadLookupSlotNoReferenceError; | 3075 contextual_mode)) { |
| 3079 const Operator* op = javascript()->CallRuntime(function_id, 2); | 3076 return fast_value; |
| 3080 Node* pair = NewNode(op, current_context(), name); | 3077 } |
| 3081 PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1)); | 3078 } else if (mode == DYNAMIC_LOCAL) { |
| 3082 return NewNode(common()->Projection(0), pair); | 3079 // Try to optimize known local when not shadowed. |
| 3080 // TODO(mstarzinger): Implement TryVariableLoadDynamicLocal(). |
| 3081 } |
| 3082 return BuildDynamicVariableLoad(variable, bailout_id, contextual_mode); |
| 3083 } | 3083 } |
| 3084 } | 3084 } |
| 3085 UNREACHABLE(); | 3085 UNREACHABLE(); |
| 3086 return NULL; | 3086 return NULL; |
| 3087 } | 3087 } |
| 3088 | 3088 |
| 3089 | 3089 |
| 3090 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, | 3090 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, |
| 3091 BailoutId bailout_id, | 3091 BailoutId bailout_id, |
| 3092 OutputFrameStateCombine combine) { | 3092 OutputFrameStateCombine combine) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 3114 PrepareFrameState(result, bailout_id, combine); | 3114 PrepareFrameState(result, bailout_id, combine); |
| 3115 return result; | 3115 return result; |
| 3116 } | 3116 } |
| 3117 } | 3117 } |
| 3118 UNREACHABLE(); | 3118 UNREACHABLE(); |
| 3119 return NULL; | 3119 return NULL; |
| 3120 } | 3120 } |
| 3121 | 3121 |
| 3122 | 3122 |
| 3123 Node* AstGraphBuilder::BuildVariableAssignment( | 3123 Node* AstGraphBuilder::BuildVariableAssignment( |
| 3124 FrameStateBeforeAndAfter& states, Variable* variable, Node* value, | 3124 Variable* variable, Node* value, Token::Value op, BailoutId bailout_id, |
| 3125 Token::Value op, BailoutId bailout_id, OutputFrameStateCombine combine) { | 3125 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) { |
| 3126 Node* the_hole = jsgraph()->TheHoleConstant(); | 3126 Node* the_hole = jsgraph()->TheHoleConstant(); |
| 3127 VariableMode mode = variable->mode(); | 3127 VariableMode mode = variable->mode(); |
| 3128 switch (variable->location()) { | 3128 switch (variable->location()) { |
| 3129 case Variable::UNALLOCATED: { | 3129 case Variable::UNALLOCATED: { |
| 3130 // Global var, const, or let variable. | 3130 // Global var, const, or let variable. |
| 3131 Node* global = BuildLoadGlobalObject(); | 3131 Node* global = BuildLoadGlobalObject(); |
| 3132 Handle<Name> name = variable->name(); | 3132 Handle<Name> name = variable->name(); |
| 3133 Node* store = | 3133 Node* store = |
| 3134 BuildNamedStore(global, name, value, TypeFeedbackId::None()); | 3134 BuildNamedStore(global, name, value, TypeFeedbackId::None()); |
| 3135 states.AddToNode(store, bailout_id, combine); | 3135 states.AddToNode(store, bailout_id, combine); |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3220 Node* store = NewNode(op, value, current_context(), name, language); | 3220 Node* store = NewNode(op, value, current_context(), name, language); |
| 3221 PrepareFrameState(store, bailout_id, combine); | 3221 PrepareFrameState(store, bailout_id, combine); |
| 3222 return store; | 3222 return store; |
| 3223 } | 3223 } |
| 3224 } | 3224 } |
| 3225 UNREACHABLE(); | 3225 UNREACHABLE(); |
| 3226 return NULL; | 3226 return NULL; |
| 3227 } | 3227 } |
| 3228 | 3228 |
| 3229 | 3229 |
| 3230 Node* AstGraphBuilder::TryDynamicGlobalVariableLoad( |
| 3231 Variable* variable, BailoutId bailout_id, FrameStateBeforeAndAfter& states, |
| 3232 const VectorSlotPair& feedback, OutputFrameStateCombine combine, |
| 3233 ContextualMode contextual_mode) { |
| 3234 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode()); |
| 3235 |
| 3236 // Determine which contexts need to be checked for extension objects that |
| 3237 // might shadow the optimistic declaration. |
| 3238 int current_depth = 0; |
| 3239 ZoneVector<int> check_depths(local_zone()); |
| 3240 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) { |
| 3241 if (s->num_heap_slots() <= 0) continue; |
| 3242 check_depths.push_back(current_depth++); |
| 3243 } |
| 3244 |
| 3245 // Impose artificial upper bound on the number of checks. |
| 3246 const int kMaxContextExtensionObjectChecks = 6; |
| 3247 if (check_depths.size() > kMaxContextExtensionObjectChecks) return nullptr; |
| 3248 |
| 3249 // We are using two blocks to model fast and slow cases. |
| 3250 BlockBuilder fast_block(this); |
| 3251 BlockBuilder slow_block(this); |
| 3252 environment()->Push(jsgraph()->TheHoleConstant()); |
| 3253 slow_block.BeginBlock(); |
| 3254 environment()->Pop(); |
| 3255 fast_block.BeginBlock(); |
| 3256 |
| 3257 // Perform checks whether the fast mode applies, by looking for any extension |
| 3258 // object which might shadow the optimistic declaration. |
| 3259 for (int depth : check_depths) { |
| 3260 Node* load = NewNode( |
| 3261 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false), |
| 3262 current_context()); |
| 3263 Node* check = |
| 3264 NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1), load); |
| 3265 fast_block.BreakUnless(check, BranchHint::kTrue); |
| 3266 } |
| 3267 |
| 3268 // Fast case, because variable is not shadowed. Perform global object load. |
| 3269 Node* fast = BuildGlobalVariableLoad(variable, bailout_id, states, feedback, |
| 3270 combine, contextual_mode); |
| 3271 environment()->Push(fast); |
| 3272 slow_block.Break(); |
| 3273 environment()->Pop(); |
| 3274 fast_block.EndBlock(); |
| 3275 |
| 3276 // Slow case, because variable potentially shadowed. Perform dynamic lookup. |
| 3277 Node* slow = BuildDynamicVariableLoad(variable, bailout_id, contextual_mode); |
| 3278 environment()->Push(slow); |
| 3279 slow_block.EndBlock(); |
| 3280 |
| 3281 return environment()->Pop(); |
| 3282 } |
| 3283 |
| 3284 |
| 3285 Node* AstGraphBuilder::BuildGlobalVariableLoad(Variable* variable, |
| 3286 BailoutId bailout_id, |
| 3287 FrameStateBeforeAndAfter& states, |
| 3288 const VectorSlotPair& feedback, |
| 3289 OutputFrameStateCombine combine, |
| 3290 ContextualMode contextual_mode) { |
| 3291 Node* global = BuildLoadGlobalObject(); |
| 3292 Handle<Name> name = variable->name(); |
| 3293 Node* node = BuildNamedLoad(global, name, feedback, contextual_mode); |
| 3294 states.AddToNode(node, bailout_id, combine); |
| 3295 return node; |
| 3296 } |
| 3297 |
| 3298 |
| 3299 Node* AstGraphBuilder::BuildDynamicVariableLoad( |
| 3300 Variable* variable, BailoutId bailout_id, ContextualMode contextual_mode) { |
| 3301 Node* name = jsgraph()->Constant(variable->name()); |
| 3302 Runtime::FunctionId function_id = |
| 3303 (contextual_mode == CONTEXTUAL) |
| 3304 ? Runtime::kLoadLookupSlot |
| 3305 : Runtime::kLoadLookupSlotNoReferenceError; |
| 3306 const Operator* op = javascript()->CallRuntime(function_id, 2); |
| 3307 Node* pair = NewNode(op, current_context(), name); |
| 3308 PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1)); |
| 3309 return NewNode(common()->Projection(0), pair); |
| 3310 } |
| 3311 |
| 3312 |
| 3230 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node, | 3313 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node, |
| 3231 FeedbackVectorICSlot slot) { | 3314 FeedbackVectorICSlot slot) { |
| 3232 if (js_type_feedback) { | 3315 if (js_type_feedback) { |
| 3233 js_type_feedback->Record(node, slot); | 3316 js_type_feedback->Record(node, slot); |
| 3234 } | 3317 } |
| 3235 return node; | 3318 return node; |
| 3236 } | 3319 } |
| 3237 | 3320 |
| 3238 | 3321 |
| 3239 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node, | 3322 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node, |
| (...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3797 // Phi does not exist yet, introduce one. | 3880 // Phi does not exist yet, introduce one. |
| 3798 value = NewPhi(inputs, value, control); | 3881 value = NewPhi(inputs, value, control); |
| 3799 value->ReplaceInput(inputs - 1, other); | 3882 value->ReplaceInput(inputs - 1, other); |
| 3800 } | 3883 } |
| 3801 return value; | 3884 return value; |
| 3802 } | 3885 } |
| 3803 | 3886 |
| 3804 } // namespace compiler | 3887 } // namespace compiler |
| 3805 } // namespace internal | 3888 } // namespace internal |
| 3806 } // namespace v8 | 3889 } // namespace v8 |
| OLD | NEW |