OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/allocation-site-scopes.h" | 10 #include "src/allocation-site-scopes.h" |
(...skipping 6938 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6949 | 6949 |
6950 switch (var->location()) { | 6950 switch (var->location()) { |
6951 case VariableLocation::GLOBAL: | 6951 case VariableLocation::GLOBAL: |
6952 case VariableLocation::UNALLOCATED: | 6952 case VariableLocation::UNALLOCATED: |
6953 HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(), | 6953 HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(), |
6954 expr->AssignmentId()); | 6954 expr->AssignmentId()); |
6955 break; | 6955 break; |
6956 | 6956 |
6957 case VariableLocation::PARAMETER: | 6957 case VariableLocation::PARAMETER: |
6958 case VariableLocation::LOCAL: | 6958 case VariableLocation::LOCAL: |
6959 if (var->mode() == CONST_LEGACY) { | |
6960 return Bailout(kUnsupportedConstCompoundAssignment); | |
6961 } | |
6962 if (var->mode() == CONST) { | 6959 if (var->mode() == CONST) { |
6963 return Bailout(kNonInitializerAssignmentToConst); | 6960 return Bailout(kNonInitializerAssignmentToConst); |
6964 } | 6961 } |
6965 BindIfLive(var, Top()); | 6962 BindIfLive(var, Top()); |
6966 break; | 6963 break; |
6967 | 6964 |
6968 case VariableLocation::CONTEXT: { | 6965 case VariableLocation::CONTEXT: { |
6969 // Bail out if we try to mutate a parameter value in a function | 6966 // Bail out if we try to mutate a parameter value in a function |
6970 // using the arguments object. We do not (yet) correctly handle the | 6967 // using the arguments object. We do not (yet) correctly handle the |
6971 // arguments property of the function. | 6968 // arguments property of the function. |
6972 if (current_info()->scope()->arguments() != NULL) { | 6969 if (current_info()->scope()->arguments() != NULL) { |
6973 // Parameters will be allocated to context slots. We have no | 6970 // Parameters will be allocated to context slots. We have no |
6974 // direct way to detect that the variable is a parameter so we do | 6971 // direct way to detect that the variable is a parameter so we do |
6975 // a linear search of the parameter variables. | 6972 // a linear search of the parameter variables. |
6976 int count = current_info()->scope()->num_parameters(); | 6973 int count = current_info()->scope()->num_parameters(); |
6977 for (int i = 0; i < count; ++i) { | 6974 for (int i = 0; i < count; ++i) { |
6978 if (var == current_info()->scope()->parameter(i)) { | 6975 if (var == current_info()->scope()->parameter(i)) { |
6979 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject); | 6976 Bailout(kAssignmentToParameterFunctionUsesArgumentsObject); |
6980 } | 6977 } |
6981 } | 6978 } |
6982 } | 6979 } |
6983 | 6980 |
6984 HStoreContextSlot::Mode mode; | 6981 HStoreContextSlot::Mode mode; |
6985 | 6982 |
6986 switch (var->mode()) { | 6983 switch (var->mode()) { |
6987 case LET: | 6984 case LET: |
6988 mode = HStoreContextSlot::kCheckDeoptimize; | 6985 mode = HStoreContextSlot::kCheckDeoptimize; |
6989 break; | 6986 break; |
6990 case CONST: | 6987 case CONST: |
6991 return Bailout(kNonInitializerAssignmentToConst); | 6988 if (var->throw_on_const_assignment(function_language_mode())) { |
6992 case CONST_LEGACY: | |
6993 if (is_strict(function_language_mode())) { | |
6994 return Bailout(kNonInitializerAssignmentToConst); | 6989 return Bailout(kNonInitializerAssignmentToConst); |
6995 } else { | 6990 } else { |
6996 return ast_context()->ReturnValue(Pop()); | 6991 return ast_context()->ReturnValue(Pop()); |
6997 } | 6992 } |
6998 default: | 6993 default: |
6999 mode = HStoreContextSlot::kNoCheck; | 6994 mode = HStoreContextSlot::kNoCheck; |
7000 } | 6995 } |
7001 | 6996 |
7002 HValue* context = BuildContextChainWalk(var); | 6997 HValue* context = BuildContextChainWalk(var); |
7003 HStoreContextSlot* instr = Add<HStoreContextSlot>( | 6998 HStoreContextSlot* instr = Add<HStoreContextSlot>( |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7055 return; | 7050 return; |
7056 } | 7051 } |
7057 | 7052 |
7058 if (prop != NULL) { | 7053 if (prop != NULL) { |
7059 HandlePropertyAssignment(expr); | 7054 HandlePropertyAssignment(expr); |
7060 } else if (proxy != NULL) { | 7055 } else if (proxy != NULL) { |
7061 Variable* var = proxy->var(); | 7056 Variable* var = proxy->var(); |
7062 | 7057 |
7063 if (var->mode() == CONST) { | 7058 if (var->mode() == CONST) { |
7064 if (expr->op() != Token::INIT) { | 7059 if (expr->op() != Token::INIT) { |
7065 return Bailout(kNonInitializerAssignmentToConst); | 7060 if (var->throw_on_const_assignment(function_language_mode())) { |
7066 } | |
7067 } else if (var->mode() == CONST_LEGACY) { | |
7068 if (expr->op() != Token::INIT) { | |
7069 if (is_strict(function_language_mode())) { | |
7070 return Bailout(kNonInitializerAssignmentToConst); | 7061 return Bailout(kNonInitializerAssignmentToConst); |
7071 } else { | 7062 } else { |
7072 CHECK_ALIVE(VisitForValue(expr->value())); | 7063 CHECK_ALIVE(VisitForValue(expr->value())); |
7073 return ast_context()->ReturnValue(Pop()); | 7064 return ast_context()->ReturnValue(Pop()); |
7074 } | 7065 } |
7075 } | 7066 } |
7076 | |
7077 // TODO(adamk): Is this required? Legacy const variables are always | |
7078 // initialized before use. | |
7079 if (var->IsStackAllocated()) { | |
7080 // We insert a use of the old value to detect unsupported uses of const | |
7081 // variables (e.g. initialization inside a loop). | |
7082 HValue* old_value = environment()->Lookup(var); | |
7083 Add<HUseConst>(old_value); | |
7084 } | |
7085 } | 7067 } |
7086 | 7068 |
7087 if (var->is_arguments()) return Bailout(kAssignmentToArguments); | 7069 if (var->is_arguments()) return Bailout(kAssignmentToArguments); |
7088 | 7070 |
7089 // Handle the assignment. | 7071 // Handle the assignment. |
7090 switch (var->location()) { | 7072 switch (var->location()) { |
7091 case VariableLocation::GLOBAL: | 7073 case VariableLocation::GLOBAL: |
7092 case VariableLocation::UNALLOCATED: | 7074 case VariableLocation::UNALLOCATED: |
7093 CHECK_ALIVE(VisitForValue(expr->value())); | 7075 CHECK_ALIVE(VisitForValue(expr->value())); |
7094 HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(), | 7076 HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7130 } | 7112 } |
7131 | 7113 |
7132 CHECK_ALIVE(VisitForValue(expr->value())); | 7114 CHECK_ALIVE(VisitForValue(expr->value())); |
7133 HStoreContextSlot::Mode mode; | 7115 HStoreContextSlot::Mode mode; |
7134 if (expr->op() == Token::ASSIGN) { | 7116 if (expr->op() == Token::ASSIGN) { |
7135 switch (var->mode()) { | 7117 switch (var->mode()) { |
7136 case LET: | 7118 case LET: |
7137 mode = HStoreContextSlot::kCheckDeoptimize; | 7119 mode = HStoreContextSlot::kCheckDeoptimize; |
7138 break; | 7120 break; |
7139 case CONST: | 7121 case CONST: |
7140 // This case is checked statically so no need to | 7122 // If we reached this point, the only possibility |
7141 // perform checks here | 7123 // is a sloppy assignment to a function name. |
7142 UNREACHABLE(); | 7124 DCHECK(function_language_mode() == SLOPPY && |
7143 case CONST_LEGACY: | 7125 !var->throw_on_const_assignment(SLOPPY)); |
7144 return ast_context()->ReturnValue(Pop()); | 7126 return ast_context()->ReturnValue(Pop()); |
7145 default: | 7127 default: |
7146 mode = HStoreContextSlot::kNoCheck; | 7128 mode = HStoreContextSlot::kNoCheck; |
7147 } | 7129 } |
7148 } else { | 7130 } else { |
7149 DCHECK_EQ(Token::INIT, expr->op()); | 7131 DCHECK_EQ(Token::INIT, expr->op()); |
7150 mode = HStoreContextSlot::kNoCheck; | 7132 mode = HStoreContextSlot::kNoCheck; |
7151 } | 7133 } |
7152 | 7134 |
7153 HValue* context = BuildContextChainWalk(var); | 7135 HValue* context = BuildContextChainWalk(var); |
(...skipping 3590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10744 // Match the full code generator stack by simulating an extra stack | 10726 // Match the full code generator stack by simulating an extra stack |
10745 // element for postfix operations in a non-effect context. The return | 10727 // element for postfix operations in a non-effect context. The return |
10746 // value is ToNumber(input). | 10728 // value is ToNumber(input). |
10747 bool returns_original_input = | 10729 bool returns_original_input = |
10748 expr->is_postfix() && !ast_context()->IsEffect(); | 10730 expr->is_postfix() && !ast_context()->IsEffect(); |
10749 HValue* input = NULL; // ToNumber(original_input). | 10731 HValue* input = NULL; // ToNumber(original_input). |
10750 HValue* after = NULL; // The result after incrementing or decrementing. | 10732 HValue* after = NULL; // The result after incrementing or decrementing. |
10751 | 10733 |
10752 if (proxy != NULL) { | 10734 if (proxy != NULL) { |
10753 Variable* var = proxy->var(); | 10735 Variable* var = proxy->var(); |
10754 if (var->mode() == CONST_LEGACY) { | |
10755 return Bailout(kUnsupportedCountOperationWithConst); | |
10756 } | |
10757 if (var->mode() == CONST) { | 10736 if (var->mode() == CONST) { |
10758 return Bailout(kNonInitializerAssignmentToConst); | 10737 return Bailout(kNonInitializerAssignmentToConst); |
10759 } | 10738 } |
10760 // Argument of the count operation is a variable, not a property. | 10739 // Argument of the count operation is a variable, not a property. |
10761 DCHECK(prop == NULL); | 10740 DCHECK(prop == NULL); |
10762 CHECK_ALIVE(VisitForValue(target)); | 10741 CHECK_ALIVE(VisitForValue(target)); |
10763 | 10742 |
10764 after = BuildIncrement(returns_original_input, expr); | 10743 after = BuildIncrement(returns_original_input, expr); |
10765 input = returns_original_input ? Top() : Pop(); | 10744 input = returns_original_input ? Top() : Pop(); |
10766 Push(after); | 10745 Push(after); |
(...skipping 2662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13429 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13408 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13430 } | 13409 } |
13431 | 13410 |
13432 #ifdef DEBUG | 13411 #ifdef DEBUG |
13433 graph_->Verify(false); // No full verify. | 13412 graph_->Verify(false); // No full verify. |
13434 #endif | 13413 #endif |
13435 } | 13414 } |
13436 | 13415 |
13437 } // namespace internal | 13416 } // namespace internal |
13438 } // namespace v8 | 13417 } // namespace v8 |
OLD | NEW |