Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: src/compiler/ast-graph-builder.cc

Issue 1158183002: [turbofan] Optimize variable loads in DYNAMIC_GLOBAL mode. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Addressed comments and small cleanup. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/ast-graph-builder.h ('k') | src/compiler/control-builders.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698