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 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
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 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 | 750 |
751 | 751 |
752 void FullCodeGenerator::VisitVariableDeclaration( | 752 void FullCodeGenerator::VisitVariableDeclaration( |
753 VariableDeclaration* declaration) { | 753 VariableDeclaration* declaration) { |
754 // If it was not possible to allocate the variable at compile time, we | 754 // If it was not possible to allocate the variable at compile time, we |
755 // need to "declare" it at runtime to make sure it actually exists in the | 755 // need to "declare" it at runtime to make sure it actually exists in the |
756 // local context. | 756 // local context. |
757 VariableProxy* proxy = declaration->proxy(); | 757 VariableProxy* proxy = declaration->proxy(); |
758 VariableMode mode = declaration->mode(); | 758 VariableMode mode = declaration->mode(); |
759 Variable* variable = proxy->var(); | 759 Variable* variable = proxy->var(); |
760 bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY; | 760 bool hole_init = mode == LET || mode == CONST; |
761 | 761 |
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; |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1263 // introducing variables. In those cases, we do not want to | 1263 // introducing variables. In those cases, we do not want to |
1264 // perform a runtime call for all variables in the scope | 1264 // perform a runtime call for all variables in the scope |
1265 // containing the eval. | 1265 // containing the eval. |
1266 Variable* var = proxy->var(); | 1266 Variable* var = proxy->var(); |
1267 if (var->mode() == DYNAMIC_GLOBAL) { | 1267 if (var->mode() == DYNAMIC_GLOBAL) { |
1268 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | 1268 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); |
1269 __ B(done); | 1269 __ B(done); |
1270 } else if (var->mode() == DYNAMIC_LOCAL) { | 1270 } else if (var->mode() == DYNAMIC_LOCAL) { |
1271 Variable* local = var->local_if_not_shadowed(); | 1271 Variable* local = var->local_if_not_shadowed(); |
1272 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); | 1272 __ Ldr(x0, ContextSlotOperandCheckExtensions(local, slow)); |
1273 if (local->mode() == LET || local->mode() == CONST || | 1273 if (local->mode() == LET || local->mode() == CONST) { |
1274 local->mode() == CONST_LEGACY) { | |
1275 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); | 1274 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, done); |
1276 if (local->mode() == CONST_LEGACY) { | 1275 __ Mov(x0, Operand(var->name())); |
1277 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | 1276 __ Push(x0); |
1278 } else { // LET || CONST | 1277 __ CallRuntime(Runtime::kThrowReferenceError); |
1279 __ Mov(x0, Operand(var->name())); | |
1280 __ Push(x0); | |
1281 __ CallRuntime(Runtime::kThrowReferenceError); | |
1282 } | |
1283 } | 1278 } |
1284 __ B(done); | 1279 __ B(done); |
1285 } | 1280 } |
1286 } | 1281 } |
1287 | 1282 |
1288 | 1283 |
1289 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1284 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1290 TypeofMode typeof_mode) { | 1285 TypeofMode typeof_mode) { |
1291 Variable* var = proxy->var(); | 1286 Variable* var = proxy->var(); |
1292 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1287 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1329 GetVar(x0, var); | 1324 GetVar(x0, var); |
1330 Label done; | 1325 Label done; |
1331 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); | 1326 __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); |
1332 if (var->mode() == LET || var->mode() == CONST) { | 1327 if (var->mode() == LET || var->mode() == CONST) { |
1333 // Throw a reference error when using an uninitialized let/const | 1328 // Throw a reference error when using an uninitialized let/const |
1334 // binding in harmony mode. | 1329 // binding in harmony mode. |
1335 __ Mov(x0, Operand(var->name())); | 1330 __ Mov(x0, Operand(var->name())); |
1336 __ Push(x0); | 1331 __ Push(x0); |
1337 __ CallRuntime(Runtime::kThrowReferenceError); | 1332 __ CallRuntime(Runtime::kThrowReferenceError); |
1338 __ Bind(&done); | 1333 __ Bind(&done); |
1339 } else { | |
1340 // Uninitialized legacy const bindings are unholed. | |
1341 DCHECK(var->mode() == CONST_LEGACY); | |
1342 __ LoadRoot(x0, Heap::kUndefinedValueRootIndex); | |
1343 __ Bind(&done); | |
1344 } | 1334 } |
1345 context()->Plug(x0); | 1335 context()->Plug(x0); |
1346 break; | 1336 break; |
1347 } | 1337 } |
1348 context()->Plug(var); | 1338 context()->Plug(var); |
1349 break; | 1339 break; |
1350 } | 1340 } |
1351 | 1341 |
1352 case VariableLocation::LOOKUP: { | 1342 case VariableLocation::LOOKUP: { |
1353 Label done, slow; | 1343 Label done, slow; |
(...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2121 Label uninitialized_this; | 2111 Label uninitialized_this; |
2122 MemOperand location = VarOperand(var, x1); | 2112 MemOperand location = VarOperand(var, x1); |
2123 __ Ldr(x10, location); | 2113 __ Ldr(x10, location); |
2124 __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this); | 2114 __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this); |
2125 __ Mov(x0, Operand(var->name())); | 2115 __ Mov(x0, Operand(var->name())); |
2126 __ Push(x0); | 2116 __ Push(x0); |
2127 __ CallRuntime(Runtime::kThrowReferenceError); | 2117 __ CallRuntime(Runtime::kThrowReferenceError); |
2128 __ bind(&uninitialized_this); | 2118 __ bind(&uninitialized_this); |
2129 EmitStoreToStackLocalOrContextSlot(var, location); | 2119 EmitStoreToStackLocalOrContextSlot(var, location); |
2130 | 2120 |
2131 } else if (!var->is_const_mode() || | 2121 } else if (!var->is_const_mode() || op == Token::INIT) { |
2132 (var->mode() == CONST && op == Token::INIT)) { | |
2133 if (var->IsLookupSlot()) { | 2122 if (var->IsLookupSlot()) { |
2134 // Assignment to var. | 2123 // Assignment to var. |
2135 __ Push(var->name()); | 2124 __ Push(var->name()); |
2136 __ Push(x0); | 2125 __ Push(x0); |
2137 __ CallRuntime(is_strict(language_mode()) | 2126 __ CallRuntime(is_strict(language_mode()) |
2138 ? Runtime::kStoreLookupSlot_Strict | 2127 ? Runtime::kStoreLookupSlot_Strict |
2139 : Runtime::kStoreLookupSlot_Sloppy); | 2128 : Runtime::kStoreLookupSlot_Sloppy); |
2140 } else { | 2129 } else { |
2141 // Assignment to var or initializing assignment to let/const in harmony | 2130 // Assignment to var or initializing assignment to let/const in harmony |
2142 // mode. | 2131 // mode. |
2143 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2132 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2144 MemOperand location = VarOperand(var, x1); | 2133 MemOperand location = VarOperand(var, x1); |
2145 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { | 2134 if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { |
2146 __ Ldr(x10, location); | 2135 __ Ldr(x10, location); |
2147 __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); | 2136 __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); |
2148 __ Check(eq, kLetBindingReInitialization); | 2137 __ Check(eq, kLetBindingReInitialization); |
2149 } | 2138 } |
2150 EmitStoreToStackLocalOrContextSlot(var, location); | 2139 EmitStoreToStackLocalOrContextSlot(var, location); |
2151 } | 2140 } |
2152 | 2141 |
2153 } else if (var->mode() == CONST_LEGACY && op == Token::INIT) { | |
2154 // Const initializers need a write barrier. | |
2155 DCHECK(!var->IsParameter()); // No const parameters. | |
2156 if (var->IsLookupSlot()) { | |
2157 __ Mov(x1, Operand(var->name())); | |
2158 __ Push(x0, cp, x1); | |
2159 __ CallRuntime(Runtime::kInitializeLegacyConstLookupSlot); | |
2160 } else { | |
2161 DCHECK(var->IsStackLocal() || var->IsContextSlot()); | |
2162 Label skip; | |
2163 MemOperand location = VarOperand(var, x1); | |
2164 __ Ldr(x10, location); | |
2165 __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &skip); | |
2166 EmitStoreToStackLocalOrContextSlot(var, location); | |
2167 __ Bind(&skip); | |
2168 } | |
2169 | |
2170 } else { | 2142 } else { |
2171 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); | 2143 DCHECK(var->mode() == CONST_LEGACY && op != Token::INIT); |
2172 if (is_strict(language_mode())) { | 2144 if (is_strict(language_mode())) { |
2173 __ CallRuntime(Runtime::kThrowConstAssignError); | 2145 __ CallRuntime(Runtime::kThrowConstAssignError); |
2174 } | 2146 } |
2175 // Silently ignore store in sloppy mode. | 2147 // Silently ignore store in sloppy mode. |
2176 } | 2148 } |
2177 } | 2149 } |
2178 | 2150 |
2179 | 2151 |
(...skipping 1877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4057 } | 4029 } |
4058 | 4030 |
4059 return INTERRUPT; | 4031 return INTERRUPT; |
4060 } | 4032 } |
4061 | 4033 |
4062 | 4034 |
4063 } // namespace internal | 4035 } // namespace internal |
4064 } // namespace v8 | 4036 } // namespace v8 |
4065 | 4037 |
4066 #endif // V8_TARGET_ARCH_ARM64 | 4038 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |