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 |