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_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 // Note on Mips implementation: | 7 // Note on Mips implementation: |
8 // | 8 // |
9 // The result_register() for mips is the 'v0' register, which is defined | 9 // The result_register() for mips is the 'v0' register, which is defined |
10 // by the ABI to contain function return values. However, the first | 10 // by the ABI to contain function return values. However, the first |
(...skipping 740 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
751 | 751 |
752 | 752 |
753 void FullCodeGenerator::VisitVariableDeclaration( | 753 void FullCodeGenerator::VisitVariableDeclaration( |
754 VariableDeclaration* declaration) { | 754 VariableDeclaration* declaration) { |
755 // If it was not possible to allocate the variable at compile time, we | 755 // If it was not possible to allocate the variable at compile time, we |
756 // need to "declare" it at runtime to make sure it actually exists in the | 756 // need to "declare" it at runtime to make sure it actually exists in the |
757 // local context. | 757 // local context. |
758 VariableProxy* proxy = declaration->proxy(); | 758 VariableProxy* proxy = declaration->proxy(); |
759 VariableMode mode = declaration->mode(); | 759 VariableMode mode = declaration->mode(); |
760 Variable* variable = proxy->var(); | 760 Variable* variable = proxy->var(); |
761 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; | 761 bool hole_init = mode == LET || mode == CONST; |
762 switch (variable->location()) { | 762 switch (variable->location()) { |
763 case VariableLocation::GLOBAL: | 763 case VariableLocation::GLOBAL: |
764 case VariableLocation::UNALLOCATED: | 764 case VariableLocation::UNALLOCATED: |
765 globals_->Add(variable->name(), zone()); | 765 globals_->Add(variable->name(), zone()); |
766 globals_->Add(variable->binding_needs_init() | 766 globals_->Add(variable->binding_needs_init() |
767 ? isolate()->factory()->the_hole_value() | 767 ? isolate()->factory()->the_hole_value() |
768 : isolate()->factory()->undefined_value(), | 768 : isolate()->factory()->undefined_value(), |
769 zone()); | 769 zone()); |
770 break; | 770 break; |
771 | 771 |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 // introducing variables. In those cases, we do not want to | 1271 // introducing variables. In those cases, we do not want to |
1272 // perform a runtime call for all variables in the scope | 1272 // perform a runtime call for all variables in the scope |
1273 // containing the eval. | 1273 // containing the eval. |
1274 Variable* var = proxy->var(); | 1274 Variable* var = proxy->var(); |
1275 if (var->mode() == DYNAMIC_GLOBAL) { | 1275 if (var->mode() == DYNAMIC_GLOBAL) { |
1276 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | 1276 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); |
1277 __ Branch(done); | 1277 __ Branch(done); |
1278 } else if (var->mode() == DYNAMIC_LOCAL) { | 1278 } else if (var->mode() == DYNAMIC_LOCAL) { |
1279 Variable* local = var->local_if_not_shadowed(); | 1279 Variable* local = var->local_if_not_shadowed(); |
1280 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); | 1280 __ lw(v0, ContextSlotOperandCheckExtensions(local, slow)); |
1281 if (local->mode() == LET || local->mode() == CONST || | 1281 if (local->mode() == LET || local->mode() == CONST) { |
1282 local->mode() == CONST_LEGACY) { | |
1283 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 1282 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
1284 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | 1283 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. |
1285 if (local->mode() == CONST_LEGACY) { | 1284 __ Branch(done, ne, at, Operand(zero_reg)); |
1286 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | 1285 __ li(a0, Operand(var->name())); |
1287 __ Movz(v0, a0, at); // Conditional move: return Undefined if TheHole. | 1286 __ push(a0); |
1288 } else { // LET || CONST | 1287 __ CallRuntime(Runtime::kThrowReferenceError); |
1289 __ Branch(done, ne, at, Operand(zero_reg)); | |
1290 __ li(a0, Operand(var->name())); | |
1291 __ push(a0); | |
1292 __ CallRuntime(Runtime::kThrowReferenceError); | |
1293 } | |
1294 } | 1288 } |
1295 __ Branch(done); | 1289 __ Branch(done); |
1296 } | 1290 } |
1297 } | 1291 } |
1298 | 1292 |
1299 | 1293 |
1300 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1294 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1301 TypeofMode typeof_mode) { | 1295 TypeofMode typeof_mode) { |
1302 Variable* var = proxy->var(); | 1296 Variable* var = proxy->var(); |
1303 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1297 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1341 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. | 1335 __ subu(at, v0, at); // Sub as compare: at == 0 on eq. |
1342 if (var->mode() == LET || var->mode() == CONST) { | 1336 if (var->mode() == LET || var->mode() == CONST) { |
1343 // Throw a reference error when using an uninitialized let/const | 1337 // Throw a reference error when using an uninitialized let/const |
1344 // binding in harmony mode. | 1338 // binding in harmony mode. |
1345 Label done; | 1339 Label done; |
1346 __ Branch(&done, ne, at, Operand(zero_reg)); | 1340 __ Branch(&done, ne, at, Operand(zero_reg)); |
1347 __ li(a0, Operand(var->name())); | 1341 __ li(a0, Operand(var->name())); |
1348 __ push(a0); | 1342 __ push(a0); |
1349 __ CallRuntime(Runtime::kThrowReferenceError); | 1343 __ CallRuntime(Runtime::kThrowReferenceError); |
1350 __ bind(&done); | 1344 __ bind(&done); |
1351 } else { | |
1352 // Uninitialized legacy const bindings are unholed. | |
1353 DCHECK(var->mode() == CONST_LEGACY); | |
1354 __ LoadRoot(a0, Heap::kUndefinedValueRootIndex); | |
1355 __ Movz(v0, a0, at); // Conditional move: Undefined if TheHole. | |
1356 } | 1345 } |
1357 context()->Plug(v0); | 1346 context()->Plug(v0); |
1358 break; | 1347 break; |
1359 } | 1348 } |
1360 context()->Plug(var); | 1349 context()->Plug(var); |
1361 break; | 1350 break; |
1362 } | 1351 } |
1363 | 1352 |
1364 case VariableLocation::LOOKUP: { | 1353 case VariableLocation::LOOKUP: { |
1365 Comment cmnt(masm_, "[ Lookup variable"); | 1354 Comment cmnt(masm_, "[ Lookup variable"); |
(...skipping 868 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2234 MemOperand location = VarOperand(var, a1); | 2223 MemOperand location = VarOperand(var, a1); |
2235 __ lw(a3, location); | 2224 __ lw(a3, location); |
2236 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2225 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
2237 __ Branch(&uninitialized_this, eq, a3, Operand(at)); | 2226 __ Branch(&uninitialized_this, eq, a3, Operand(at)); |
2238 __ li(a0, Operand(var->name())); | 2227 __ li(a0, Operand(var->name())); |
2239 __ Push(a0); | 2228 __ Push(a0); |
2240 __ CallRuntime(Runtime::kThrowReferenceError); | 2229 __ CallRuntime(Runtime::kThrowReferenceError); |
2241 __ bind(&uninitialized_this); | 2230 __ bind(&uninitialized_this); |
2242 EmitStoreToStackLocalOrContextSlot(var, location); | 2231 EmitStoreToStackLocalOrContextSlot(var, location); |
2243 | 2232 |
2244 } else if (!var->is_const_mode() || | 2233 } else if (!var->is_const_mode() || op == Token::INIT) { |
2245 (var->mode() == CONST && op == Token::INIT)) { | |
2246 if (var->IsLookupSlot()) { | 2234 if (var->IsLookupSlot()) { |
2247 // Assignment to var. | 2235 // Assignment to var. |
2248 __ Push(var->name()); | 2236 __ Push(var->name()); |
2249 __ Push(v0); | 2237 __ Push(v0); |
2250 __ CallRuntime(is_strict(language_mode()) | 2238 __ CallRuntime(is_strict(language_mode()) |
2251 ? Runtime::kStoreLookupSlot_Strict | 2239 ? Runtime::kStoreLookupSlot_Strict |
2252 : Runtime::kStoreLookupSlot_Sloppy); | 2240 : Runtime::kStoreLookupSlot_Sloppy); |
2253 } else { | 2241 } else { |
2254 // Assignment to var or initializing assignment to let/const in harmony | 2242 // Assignment to var or initializing assignment to let/const in harmony |
2255 // mode. | 2243 // mode. |
2256 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); | 2244 DCHECK((var->IsStackAllocated() || var->IsContextSlot())); |
2257 MemOperand location = VarOperand(var, a1); | 2245 MemOperand location = VarOperand(var, a1); |
2258 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | 2246 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
2259 // Check for an uninitialized let binding. | 2247 // Check for an uninitialized let binding. |
2260 __ lw(a2, location); | 2248 __ lw(a2, location); |
2261 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); | 2249 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
2262 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); | 2250 __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); |
2263 } | 2251 } |
2264 EmitStoreToStackLocalOrContextSlot(var, location); | 2252 EmitStoreToStackLocalOrContextSlot(var, location); |
2265 } | 2253 } |
2266 | 2254 |
2267 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | |
2268 // Const initializers need a write barrier. | |
2269 DCHECK(!var->IsParameter()); // No const parameters. | |
2270 if (var->IsLookupSlot()) { | |
2271 __ li(a0, Operand(var->name())); | |
2272 __ Push(v0, cp, a0); // Context and name. | |
2273 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); | |
2274 } else { | |
2275 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | |
2276 Label skip; | |
2277 MemOperand location = VarOperand(var, a1); | |
2278 __ lw(a2, location); | |
2279 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | |
2280 __ Branch(&skip, ne, a2, Operand(at)); | |
2281 EmitStoreToStackLocalOrContextSlot(var, location); | |
2282 __ bind(&skip); | |
2283 } | |
2284 | |
2285 } else { | 2255 } else { |
2286 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2256 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
2287 if (is_strict(language_mode())) { | 2257 if (is_strict(language_mode())) { |
2288 __ CallRuntime(Runtime::kThrowConstAssignError); | 2258 __ CallRuntime(Runtime::kThrowConstAssignError); |
2289 } | 2259 } |
2290 // Silently ignore store in sloppy mode. | 2260 // Silently ignore store in sloppy mode. |
2291 } | 2261 } |
2292 } | 2262 } |
2293 | 2263 |
2294 | 2264 |
(...skipping 1718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4013 reinterpret_cast<uint32_t>( | 3983 reinterpret_cast<uint32_t>( |
4014 isolate->builtins()->OnStackReplacement()->entry())); | 3984 isolate->builtins()->OnStackReplacement()->entry())); |
4015 return ON_STACK_REPLACEMENT; | 3985 return ON_STACK_REPLACEMENT; |
4016 } | 3986 } |
4017 | 3987 |
4018 | 3988 |
4019 } // namespace internal | 3989 } // namespace internal |
4020 } // namespace v8 | 3990 } // namespace v8 |
4021 | 3991 |
4022 #endif // V8_TARGET_ARCH_MIPS | 3992 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |