| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_X87 | 5 #if V8_TARGET_ARCH_X87 |
| 6 | 6 |
| 7 #include "src/ast/scopes.h" | 7 #include "src/ast/scopes.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
| (...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 | 698 |
| 699 | 699 |
| 700 void FullCodeGenerator::VisitVariableDeclaration( | 700 void FullCodeGenerator::VisitVariableDeclaration( |
| 701 VariableDeclaration* declaration) { | 701 VariableDeclaration* declaration) { |
| 702 // If it was not possible to allocate the variable at compile time, we | 702 // If it was not possible to allocate the variable at compile time, we |
| 703 // need to "declare" it at runtime to make sure it actually exists in the | 703 // need to "declare" it at runtime to make sure it actually exists in the |
| 704 // local context. | 704 // local context. |
| 705 VariableProxy* proxy = declaration->proxy(); | 705 VariableProxy* proxy = declaration->proxy(); |
| 706 VariableMode mode = declaration->mode(); | 706 VariableMode mode = declaration->mode(); |
| 707 Variable* variable = proxy->var(); | 707 Variable* variable = proxy->var(); |
| 708 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; | 708 bool hole_init = mode == LET || mode == CONST; |
| 709 switch (variable->location()) { | 709 switch (variable->location()) { |
| 710 case VariableLocation::GLOBAL: | 710 case VariableLocation::GLOBAL: |
| 711 case VariableLocation::UNALLOCATED: | 711 case VariableLocation::UNALLOCATED: |
| 712 globals_->Add(variable->name(), zone()); | 712 globals_->Add(variable->name(), zone()); |
| 713 globals_->Add(variable->binding_needs_init() | 713 globals_->Add(variable->binding_needs_init() |
| 714 ? isolate()->factory()->the_hole_value() | 714 ? isolate()->factory()->the_hole_value() |
| 715 : isolate()->factory()->undefined_value(), zone()); | 715 : isolate()->factory()->undefined_value(), zone()); |
| 716 break; | 716 break; |
| 717 | 717 |
| 718 case VariableLocation::PARAMETER: | 718 case VariableLocation::PARAMETER: |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1192 // introducing variables. In those cases, we do not want to | 1192 // introducing variables. In those cases, we do not want to |
| 1193 // perform a runtime call for all variables in the scope | 1193 // perform a runtime call for all variables in the scope |
| 1194 // containing the eval. | 1194 // containing the eval. |
| 1195 Variable* var = proxy->var(); | 1195 Variable* var = proxy->var(); |
| 1196 if (var->mode() == DYNAMIC_GLOBAL) { | 1196 if (var->mode() == DYNAMIC_GLOBAL) { |
| 1197 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | 1197 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); |
| 1198 __ jmp(done); | 1198 __ jmp(done); |
| 1199 } else if (var->mode() == DYNAMIC_LOCAL) { | 1199 } else if (var->mode() == DYNAMIC_LOCAL) { |
| 1200 Variable* local = var->local_if_not_shadowed(); | 1200 Variable* local = var->local_if_not_shadowed(); |
| 1201 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); | 1201 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); |
| 1202 if (local->mode() == LET || local->mode() == CONST || | 1202 if (local->mode() == LET || local->mode() == CONST) { |
| 1203 local->mode() == CONST_LEGACY) { | |
| 1204 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1203 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1205 __ j(not_equal, done); | 1204 __ j(not_equal, done); |
| 1206 if (local->mode() == CONST_LEGACY) { | 1205 __ push(Immediate(var->name())); |
| 1207 __ mov(eax, isolate()->factory()->undefined_value()); | 1206 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1208 } else { // LET || CONST | |
| 1209 __ push(Immediate(var->name())); | |
| 1210 __ CallRuntime(Runtime::kThrowReferenceError); | |
| 1211 } | |
| 1212 } | 1207 } |
| 1213 __ jmp(done); | 1208 __ jmp(done); |
| 1214 } | 1209 } |
| 1215 } | 1210 } |
| 1216 | 1211 |
| 1217 | 1212 |
| 1218 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1213 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1219 TypeofMode typeof_mode) { | 1214 TypeofMode typeof_mode) { |
| 1220 Variable* var = proxy->var(); | 1215 Variable* var = proxy->var(); |
| 1221 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1216 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 // Let and const need a read barrier. | 1254 // Let and const need a read barrier. |
| 1260 Label done; | 1255 Label done; |
| 1261 GetVar(eax, var); | 1256 GetVar(eax, var); |
| 1262 __ cmp(eax, isolate()->factory()->the_hole_value()); | 1257 __ cmp(eax, isolate()->factory()->the_hole_value()); |
| 1263 __ j(not_equal, &done, Label::kNear); | 1258 __ j(not_equal, &done, Label::kNear); |
| 1264 if (var->mode() == LET || var->mode() == CONST) { | 1259 if (var->mode() == LET || var->mode() == CONST) { |
| 1265 // Throw a reference error when using an uninitialized let/const | 1260 // Throw a reference error when using an uninitialized let/const |
| 1266 // binding in harmony mode. | 1261 // binding in harmony mode. |
| 1267 __ push(Immediate(var->name())); | 1262 __ push(Immediate(var->name())); |
| 1268 __ CallRuntime(Runtime::kThrowReferenceError); | 1263 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1269 } else { | |
| 1270 // Uninitialized legacy const bindings are unholed. | |
| 1271 DCHECK(var->mode() == CONST_LEGACY); | |
| 1272 __ mov(eax, isolate()->factory()->undefined_value()); | |
| 1273 } | 1264 } |
| 1274 __ bind(&done); | 1265 __ bind(&done); |
| 1275 context()->Plug(eax); | 1266 context()->Plug(eax); |
| 1276 break; | 1267 break; |
| 1277 } | 1268 } |
| 1278 context()->Plug(var); | 1269 context()->Plug(var); |
| 1279 break; | 1270 break; |
| 1280 } | 1271 } |
| 1281 | 1272 |
| 1282 case VariableLocation::LOOKUP: { | 1273 case VariableLocation::LOOKUP: { |
| (...skipping 845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2128 Label uninitialized_this; | 2119 Label uninitialized_this; |
| 2129 MemOperand location = VarOperand(var, ecx); | 2120 MemOperand location = VarOperand(var, ecx); |
| 2130 __ mov(edx, location); | 2121 __ mov(edx, location); |
| 2131 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2122 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2132 __ j(equal, &uninitialized_this); | 2123 __ j(equal, &uninitialized_this); |
| 2133 __ push(Immediate(var->name())); | 2124 __ push(Immediate(var->name())); |
| 2134 __ CallRuntime(Runtime::kThrowReferenceError); | 2125 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2135 __ bind(&uninitialized_this); | 2126 __ bind(&uninitialized_this); |
| 2136 EmitStoreToStackLocalOrContextSlot(var, location); | 2127 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2137 | 2128 |
| 2138 } else if (!var->is_const_mode() || | 2129 } else if (!var->is_const_mode() || op == Token::INIT) { |
| 2139 (var->mode() == CONST && op == Token::INIT)) { | |
| 2140 if (var->IsLookupSlot()) { | 2130 if (var->IsLookupSlot()) { |
| 2141 // Assignment to var. | 2131 // Assignment to var. |
| 2142 __ Push(Immediate(var->name())); | 2132 __ Push(Immediate(var->name())); |
| 2143 __ Push(eax); | 2133 __ Push(eax); |
| 2144 __ CallRuntime(is_strict(language_mode()) | 2134 __ CallRuntime(is_strict(language_mode()) |
| 2145 ? Runtime::kStoreLookupSlot_Strict | 2135 ? Runtime::kStoreLookupSlot_Strict |
| 2146 : Runtime::kStoreLookupSlot_Sloppy); | 2136 : Runtime::kStoreLookupSlot_Sloppy); |
| 2147 } else { | 2137 } else { |
| 2148 // Assignment to var or initializing assignment to let/const in harmony | 2138 // Assignment to var or initializing assignment to let/const in harmony |
| 2149 // mode. | 2139 // mode. |
| 2150 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2140 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2151 MemOperand location = VarOperand(var, ecx); | 2141 MemOperand location = VarOperand(var, ecx); |
| 2152 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | 2142 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
| 2153 // Check for an uninitialized let binding. | 2143 // Check for an uninitialized let binding. |
| 2154 __ mov(edx, location); | 2144 __ mov(edx, location); |
| 2155 __ cmp(edx, isolate()->factory()->the_hole_value()); | 2145 __ cmp(edx, isolate()->factory()->the_hole_value()); |
| 2156 __ Check(equal, kLetBindingReInitialization); | 2146 __ Check(equal, kLetBindingReInitialization); |
| 2157 } | 2147 } |
| 2158 EmitStoreToStackLocalOrContextSlot(var, location); | 2148 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2159 } | 2149 } |
| 2160 | 2150 |
| 2161 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | |
| 2162 // Const initializers need a write barrier. | |
| 2163 DCHECK(!var->IsParameter()); // No const parameters. | |
| 2164 if (var->IsLookupSlot()) { | |
| 2165 __ push(eax); | |
| 2166 __ push(esi); | |
| 2167 __ push(Immediate(var->name())); | |
| 2168 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); | |
| 2169 } else { | |
| 2170 DCHECK(var->IsStackLocal() || var->IsContextSlot()); | |
| 2171 Label skip; | |
| 2172 MemOperand location = VarOperand(var, ecx); | |
| 2173 __ mov(edx, location); | |
| 2174 __ cmp(edx, isolate()->factory()->the_hole_value()); | |
| 2175 __ j(not_equal, &skip, Label::kNear); | |
| 2176 EmitStoreToStackLocalOrContextSlot(var, location); | |
| 2177 __ bind(&skip); | |
| 2178 } | |
| 2179 | |
| 2180 } else { | 2151 } else { |
| 2181 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2152 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
| 2182 if (is_strict(language_mode())) { | 2153 if (is_strict(language_mode())) { |
| 2183 __ CallRuntime(Runtime::kThrowConstAssignError); | 2154 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2184 } | 2155 } |
| 2185 // Silently ignore store in sloppy mode. | 2156 // Silently ignore store in sloppy mode. |
| 2186 } | 2157 } |
| 2187 } | 2158 } |
| 2188 | 2159 |
| 2189 | 2160 |
| (...skipping 1701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3891 isolate->builtins()->OnStackReplacement()->entry(), | 3862 isolate->builtins()->OnStackReplacement()->entry(), |
| 3892 Assembler::target_address_at(call_target_address, unoptimized_code)); | 3863 Assembler::target_address_at(call_target_address, unoptimized_code)); |
| 3893 return ON_STACK_REPLACEMENT; | 3864 return ON_STACK_REPLACEMENT; |
| 3894 } | 3865 } |
| 3895 | 3866 |
| 3896 | 3867 |
| 3897 } // namespace internal | 3868 } // namespace internal |
| 3898 } // namespace v8 | 3869 } // namespace v8 |
| 3899 | 3870 |
| 3900 #endif // V8_TARGET_ARCH_X87 | 3871 #endif // V8_TARGET_ARCH_X87 |
| OLD | NEW |