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

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: Created 5 years, 6 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 Node* global = BuildLoadGlobalObject();
3025 Handle<Name> name = variable->name(); 3025 Handle<Name> name = variable->name();
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3064 Node* undefined = jsgraph()->UndefinedConstant(); 3064 Node* undefined = jsgraph()->UndefinedConstant();
3065 value = BuildHoleCheckSilent(value, undefined, value); 3065 value = BuildHoleCheckSilent(value, undefined, value);
3066 } else if (mode == LET || mode == CONST) { 3066 } else if (mode == LET || mode == CONST) {
3067 // Perform check for uninitialized let/const variables. 3067 // Perform check for uninitialized let/const variables.
3068 value = BuildHoleCheckThrow(value, variable, value, bailout_id); 3068 value = BuildHoleCheckThrow(value, variable, value, bailout_id);
3069 } 3069 }
3070 return value; 3070 return value;
3071 } 3071 }
3072 case Variable::LOOKUP: { 3072 case Variable::LOOKUP: {
3073 // Dynamic lookup of context variable (anywhere in the chain). 3073 // Dynamic lookup of context variable (anywhere in the chain).
3074 Node* name = jsgraph()->Constant(variable->name()); 3074 if (mode == DYNAMIC_GLOBAL) {
3075 Runtime::FunctionId function_id = 3075 // Try to optimize known global when not shadowed.
3076 (contextual_mode == CONTEXTUAL) 3076 if (Node* fast_value = TryVariableLoadDynamicGlobal(
3077 ? Runtime::kLoadLookupSlot 3077 variable, bailout_id, states, feedback, combine,
3078 : Runtime::kLoadLookupSlotNoReferenceError; 3078 contextual_mode)) {
3079 const Operator* op = javascript()->CallRuntime(function_id, 2); 3079 return fast_value;
3080 Node* pair = NewNode(op, current_context(), name); 3080 }
3081 PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1)); 3081 } else if (mode == DYNAMIC_LOCAL) {
3082 return NewNode(common()->Projection(0), pair); 3082 // Try to optimize known local when not shadowed.
3083 // TODO(mstarzinger): Implement TryVariableLoadDynamicLocal().
3084 }
3085 return BuildDynamicVariableLoad(variable, bailout_id, contextual_mode);
3083 } 3086 }
3084 } 3087 }
3085 UNREACHABLE(); 3088 UNREACHABLE();
3086 return NULL; 3089 return NULL;
3087 } 3090 }
3088 3091
3089 3092
3090 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable, 3093 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3091 BailoutId bailout_id, 3094 BailoutId bailout_id,
3092 OutputFrameStateCombine combine) { 3095 OutputFrameStateCombine combine) {
(...skipping 21 matching lines...) Expand all
3114 PrepareFrameState(result, bailout_id, combine); 3117 PrepareFrameState(result, bailout_id, combine);
3115 return result; 3118 return result;
3116 } 3119 }
3117 } 3120 }
3118 UNREACHABLE(); 3121 UNREACHABLE();
3119 return NULL; 3122 return NULL;
3120 } 3123 }
3121 3124
3122 3125
3123 Node* AstGraphBuilder::BuildVariableAssignment( 3126 Node* AstGraphBuilder::BuildVariableAssignment(
3124 FrameStateBeforeAndAfter& states, Variable* variable, Node* value, 3127 Variable* variable, Node* value, Token::Value op, BailoutId bailout_id,
3125 Token::Value op, BailoutId bailout_id, OutputFrameStateCombine combine) { 3128 FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
3126 Node* the_hole = jsgraph()->TheHoleConstant(); 3129 Node* the_hole = jsgraph()->TheHoleConstant();
3127 VariableMode mode = variable->mode(); 3130 VariableMode mode = variable->mode();
3128 switch (variable->location()) { 3131 switch (variable->location()) {
3129 case Variable::UNALLOCATED: { 3132 case Variable::UNALLOCATED: {
3130 // Global var, const, or let variable. 3133 // Global var, const, or let variable.
3131 Node* global = BuildLoadGlobalObject(); 3134 Node* global = BuildLoadGlobalObject();
3132 Handle<Name> name = variable->name(); 3135 Handle<Name> name = variable->name();
3133 Node* store = 3136 Node* store =
3134 BuildNamedStore(global, name, value, TypeFeedbackId::None()); 3137 BuildNamedStore(global, name, value, TypeFeedbackId::None());
3135 states.AddToNode(store, bailout_id, combine); 3138 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); 3223 Node* store = NewNode(op, value, current_context(), name, language);
3221 PrepareFrameState(store, bailout_id, combine); 3224 PrepareFrameState(store, bailout_id, combine);
3222 return store; 3225 return store;
3223 } 3226 }
3224 } 3227 }
3225 UNREACHABLE(); 3228 UNREACHABLE();
3226 return NULL; 3229 return NULL;
3227 } 3230 }
3228 3231
3229 3232
3233 Node* AstGraphBuilder::TryVariableLoadDynamicGlobal(
titzer 2015/05/27 14:06:21 The ordering of the words is kind of mixed up here
Michael Starzinger 2015/05/27 14:10:28 Done. True, the name is confusing, changed it to T
3234 Variable* variable, BailoutId bailout_id, FrameStateBeforeAndAfter& states,
3235 const VectorSlotPair& feedback, OutputFrameStateCombine combine,
3236 ContextualMode contextual_mode) {
3237 DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3238
3239 // Determine which contexts need to be checked for extension objects that
3240 // might shadow the optimistic declaration.
3241 int current_depth = 0;
3242 ZoneVector<int> check_depths(local_zone());
3243 for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3244 if (s->num_heap_slots() <= 0) continue;
3245 check_depths.push_back(current_depth++);
3246 }
3247
3248 // Impose artificial upper bound on the number of checks.
3249 const int kMaxContextExtensionObjectChecks = 6;
3250 if (check_depths.size() > kMaxContextExtensionObjectChecks) return nullptr;
3251
3252 // We are using two blocks to model fast and slow cases.
3253 BlockBuilder fast_block(this);
3254 BlockBuilder slow_block(this);
3255 environment()->Push(jsgraph()->TheHoleConstant());
3256 slow_block.BeginBlock();
3257 environment()->Pop();
3258 fast_block.BeginBlock();
3259
3260 // Perform checks whether the fast mode applies, by looking whether for any
3261 // extension object which might shadow the optimistic declaration.
3262 for (int depth : check_depths) {
3263 Node* load = NewNode(
3264 javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false),
3265 current_context());
3266 Node* check =
3267 NewNode(javascript()->CallRuntime(Runtime::kInlineIsSmi, 1), load);
3268 fast_block.BreakUnless(check, BranchHint::kTrue);
3269 }
3270
3271 // Fast case, because variable is not shadowed. Perform global object load.
3272 Node* fast = BuildGlobalVariableLoad(variable, bailout_id, states, feedback,
3273 combine, contextual_mode);
3274 environment()->Push(fast);
3275 slow_block.Break();
3276 environment()->Pop();
3277 fast_block.EndBlock();
3278
3279 // Slow case, because variable potentially shadowed. Perform dynamic lookup.
3280 Node* slow = BuildDynamicVariableLoad(variable, bailout_id, contextual_mode);
3281 environment()->Push(slow);
3282 slow_block.EndBlock();
3283
3284 return environment()->Pop();
3285 }
3286
3287
3288 Node* AstGraphBuilder::BuildGlobalVariableLoad(Variable* variable,
3289 BailoutId bailout_id,
3290 FrameStateBeforeAndAfter& states,
3291 const VectorSlotPair& feedback,
3292 OutputFrameStateCombine combine,
3293 ContextualMode contextual_mode) {
3294 Node* global = BuildLoadGlobalObject();
3295 Handle<Name> name = variable->name();
3296 Node* node = BuildNamedLoad(global, name, feedback, contextual_mode);
3297 states.AddToNode(node, bailout_id, combine);
3298 return node;
3299 }
3300
3301
3302 Node* AstGraphBuilder::BuildDynamicVariableLoad(
3303 Variable* variable, BailoutId bailout_id, ContextualMode contextual_mode) {
3304 Node* name = jsgraph()->Constant(variable->name());
3305 Runtime::FunctionId function_id =
3306 (contextual_mode == CONTEXTUAL)
3307 ? Runtime::kLoadLookupSlot
3308 : Runtime::kLoadLookupSlotNoReferenceError;
3309 const Operator* op = javascript()->CallRuntime(function_id, 2);
3310 Node* pair = NewNode(op, current_context(), name);
3311 PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1));
3312 return NewNode(common()->Projection(0), pair);
3313 }
3314
3315
3230 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node, 3316 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node,
3231 FeedbackVectorICSlot slot) { 3317 FeedbackVectorICSlot slot) {
3232 if (js_type_feedback) { 3318 if (js_type_feedback) {
3233 js_type_feedback->Record(node, slot); 3319 js_type_feedback->Record(node, slot);
3234 } 3320 }
3235 return node; 3321 return node;
3236 } 3322 }
3237 3323
3238 3324
3239 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node, 3325 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. 3883 // Phi does not exist yet, introduce one.
3798 value = NewPhi(inputs, value, control); 3884 value = NewPhi(inputs, value, control);
3799 value->ReplaceInput(inputs - 1, other); 3885 value->ReplaceInput(inputs - 1, other);
3800 } 3886 }
3801 return value; 3887 return value;
3802 } 3888 }
3803 3889
3804 } // namespace compiler 3890 } // namespace compiler
3805 } // namespace internal 3891 } // namespace internal
3806 } // namespace v8 3892 } // 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