| 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_ARM | 5 #if V8_TARGET_ARCH_ARM |
| 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 742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 __ CompareRoot(r1, Heap::kWithContextMapRootIndex); | 753 __ CompareRoot(r1, Heap::kWithContextMapRootIndex); |
| 754 __ Check(ne, kDeclarationInWithContext); | 754 __ Check(ne, kDeclarationInWithContext); |
| 755 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); | 755 __ CompareRoot(r1, Heap::kCatchContextMapRootIndex); |
| 756 __ Check(ne, kDeclarationInCatchContext); | 756 __ Check(ne, kDeclarationInCatchContext); |
| 757 } | 757 } |
| 758 } | 758 } |
| 759 | 759 |
| 760 | 760 |
| 761 void FullCodeGenerator::VisitVariableDeclaration( | 761 void FullCodeGenerator::VisitVariableDeclaration( |
| 762 VariableDeclaration* declaration) { | 762 VariableDeclaration* declaration) { |
| 763 // If it was not possible to allocate the variable at compile time, we | |
| 764 // need to "declare" it at runtime to make sure it actually exists in the | |
| 765 // local context. | |
| 766 VariableProxy* proxy = declaration->proxy(); | 763 VariableProxy* proxy = declaration->proxy(); |
| 767 VariableMode mode = declaration->mode(); | |
| 768 Variable* variable = proxy->var(); | 764 Variable* variable = proxy->var(); |
| 769 bool hole_init = mode == LET || mode == CONST; | |
| 770 switch (variable->location()) { | 765 switch (variable->location()) { |
| 771 case VariableLocation::GLOBAL: | 766 case VariableLocation::GLOBAL: |
| 772 case VariableLocation::UNALLOCATED: { | 767 case VariableLocation::UNALLOCATED: { |
| 773 DCHECK(!variable->binding_needs_init()); | 768 DCHECK(!variable->binding_needs_init()); |
| 774 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 769 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
| 775 DCHECK(!slot.IsInvalid()); | 770 DCHECK(!slot.IsInvalid()); |
| 776 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 771 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); |
| 777 globals_->Add(isolate()->factory()->undefined_value(), zone()); | 772 globals_->Add(isolate()->factory()->undefined_value(), zone()); |
| 778 break; | 773 break; |
| 779 } | 774 } |
| 780 case VariableLocation::PARAMETER: | 775 case VariableLocation::PARAMETER: |
| 781 case VariableLocation::LOCAL: | 776 case VariableLocation::LOCAL: |
| 782 if (hole_init) { | 777 if (variable->binding_needs_init()) { |
| 783 Comment cmnt(masm_, "[ VariableDeclaration"); | 778 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 784 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 779 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 785 __ str(r0, StackOperand(variable)); | 780 __ str(r0, StackOperand(variable)); |
| 786 } | 781 } |
| 787 break; | 782 break; |
| 788 | 783 |
| 789 case VariableLocation::CONTEXT: | 784 case VariableLocation::CONTEXT: |
| 790 if (hole_init) { | 785 if (variable->binding_needs_init()) { |
| 791 Comment cmnt(masm_, "[ VariableDeclaration"); | 786 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 792 EmitDebugCheckDeclarationContext(variable); | 787 EmitDebugCheckDeclarationContext(variable); |
| 793 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); | 788 __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); |
| 794 __ str(r0, ContextMemOperand(cp, variable->index())); | 789 __ str(r0, ContextMemOperand(cp, variable->index())); |
| 795 // No write barrier since the_hole_value is in old space. | 790 // No write barrier since the_hole_value is in old space. |
| 796 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 791 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 797 } | 792 } |
| 798 break; | 793 break; |
| 799 | 794 |
| 800 case VariableLocation::LOOKUP: { | 795 case VariableLocation::LOOKUP: { |
| 801 Comment cmnt(masm_, "[ VariableDeclaration"); | 796 Comment cmnt(masm_, "[ VariableDeclaration"); |
| 802 DCHECK_EQ(VAR, mode); | 797 DCHECK_EQ(VAR, variable->mode()); |
| 803 DCHECK(!hole_init); | 798 DCHECK(!variable->binding_needs_init()); |
| 804 __ mov(r2, Operand(variable->name())); | 799 __ mov(r2, Operand(variable->name())); |
| 805 __ Push(r2); | 800 __ Push(r2); |
| 806 __ CallRuntime(Runtime::kDeclareEvalVar); | 801 __ CallRuntime(Runtime::kDeclareEvalVar); |
| 807 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 802 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
| 808 break; | 803 break; |
| 809 } | 804 } |
| 810 } | 805 } |
| 811 } | 806 } |
| 812 | 807 |
| 813 | 808 |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 // introducing variables. In those cases, we do not want to | 1259 // introducing variables. In those cases, we do not want to |
| 1265 // perform a runtime call for all variables in the scope | 1260 // perform a runtime call for all variables in the scope |
| 1266 // containing the eval. | 1261 // containing the eval. |
| 1267 Variable* var = proxy->var(); | 1262 Variable* var = proxy->var(); |
| 1268 if (var->mode() == DYNAMIC_GLOBAL) { | 1263 if (var->mode() == DYNAMIC_GLOBAL) { |
| 1269 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | 1264 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); |
| 1270 __ jmp(done); | 1265 __ jmp(done); |
| 1271 } else if (var->mode() == DYNAMIC_LOCAL) { | 1266 } else if (var->mode() == DYNAMIC_LOCAL) { |
| 1272 Variable* local = var->local_if_not_shadowed(); | 1267 Variable* local = var->local_if_not_shadowed(); |
| 1273 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); | 1268 __ ldr(r0, ContextSlotOperandCheckExtensions(local, slow)); |
| 1274 if (local->mode() == LET || local->mode() == CONST) { | 1269 if (local->binding_needs_init()) { |
| 1275 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1270 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
| 1276 __ b(ne, done); | 1271 __ b(ne, done); |
| 1277 __ mov(r0, Operand(var->name())); | 1272 __ mov(r0, Operand(var->name())); |
| 1278 __ push(r0); | 1273 __ push(r0); |
| 1279 __ CallRuntime(Runtime::kThrowReferenceError); | 1274 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1275 } else { |
| 1276 __ jmp(done); |
| 1280 } | 1277 } |
| 1281 __ jmp(done); | |
| 1282 } | 1278 } |
| 1283 } | 1279 } |
| 1284 | 1280 |
| 1285 | 1281 |
| 1286 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1282 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
| 1287 TypeofMode typeof_mode) { | 1283 TypeofMode typeof_mode) { |
| 1288 #ifdef DEBUG | 1284 #ifdef DEBUG |
| 1289 Variable* var = proxy->var(); | 1285 Variable* var = proxy->var(); |
| 1290 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1286 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
| 1291 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); | 1287 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1314 break; | 1310 break; |
| 1315 } | 1311 } |
| 1316 | 1312 |
| 1317 case VariableLocation::PARAMETER: | 1313 case VariableLocation::PARAMETER: |
| 1318 case VariableLocation::LOCAL: | 1314 case VariableLocation::LOCAL: |
| 1319 case VariableLocation::CONTEXT: { | 1315 case VariableLocation::CONTEXT: { |
| 1320 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 1316 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); |
| 1321 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1317 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
| 1322 : "[ Stack variable"); | 1318 : "[ Stack variable"); |
| 1323 if (NeedsHoleCheckForLoad(proxy)) { | 1319 if (NeedsHoleCheckForLoad(proxy)) { |
| 1324 // Let and const need a read barrier. | 1320 // Throw a reference error when using an uninitialized let/const |
| 1321 // binding in harmony mode. |
| 1322 Label done; |
| 1325 GetVar(r0, var); | 1323 GetVar(r0, var); |
| 1326 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); | 1324 __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); |
| 1327 if (var->mode() == LET || var->mode() == CONST) { | 1325 __ b(ne, &done); |
| 1328 // Throw a reference error when using an uninitialized let/const | 1326 __ mov(r0, Operand(var->name())); |
| 1329 // binding in harmony mode. | 1327 __ push(r0); |
| 1330 Label done; | 1328 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1331 __ b(ne, &done); | 1329 __ bind(&done); |
| 1332 __ mov(r0, Operand(var->name())); | |
| 1333 __ push(r0); | |
| 1334 __ CallRuntime(Runtime::kThrowReferenceError); | |
| 1335 __ bind(&done); | |
| 1336 } | |
| 1337 context()->Plug(r0); | 1330 context()->Plug(r0); |
| 1338 break; | 1331 break; |
| 1339 } | 1332 } |
| 1340 context()->Plug(var); | 1333 context()->Plug(var); |
| 1341 break; | 1334 break; |
| 1342 } | 1335 } |
| 1343 | 1336 |
| 1344 case VariableLocation::LOOKUP: { | 1337 case VariableLocation::LOOKUP: { |
| 1345 Comment cmnt(masm_, "[ Lookup variable"); | 1338 Comment cmnt(masm_, "[ Lookup variable"); |
| 1346 Label done, slow; | 1339 Label done, slow; |
| (...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2158 | 2151 |
| 2159 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 2152 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
| 2160 FeedbackVectorSlot slot) { | 2153 FeedbackVectorSlot slot) { |
| 2161 if (var->IsUnallocated()) { | 2154 if (var->IsUnallocated()) { |
| 2162 // Global var, const, or let. | 2155 // Global var, const, or let. |
| 2163 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); | 2156 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); |
| 2164 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 2157 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); |
| 2165 EmitLoadStoreICSlot(slot); | 2158 EmitLoadStoreICSlot(slot); |
| 2166 CallStoreIC(); | 2159 CallStoreIC(); |
| 2167 | 2160 |
| 2168 } else if (var->mode() == LET && op != Token::INIT) { | 2161 } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { |
| 2169 // Non-initializing assignment to let variable needs a write barrier. | |
| 2170 DCHECK(!var->IsLookupSlot()); | 2162 DCHECK(!var->IsLookupSlot()); |
| 2171 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2163 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2172 Label assign; | |
| 2173 MemOperand location = VarOperand(var, r1); | 2164 MemOperand location = VarOperand(var, r1); |
| 2174 __ ldr(r3, location); | 2165 // Perform an initialization check for lexically declared variables. |
| 2175 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 2166 if (var->binding_needs_init()) { |
| 2176 __ b(ne, &assign); | 2167 Label assign; |
| 2177 __ mov(r3, Operand(var->name())); | 2168 __ ldr(r3, location); |
| 2178 __ push(r3); | 2169 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 2179 __ CallRuntime(Runtime::kThrowReferenceError); | 2170 __ b(ne, &assign); |
| 2180 // Perform the assignment. | 2171 __ mov(r3, Operand(var->name())); |
| 2181 __ bind(&assign); | 2172 __ push(r3); |
| 2182 EmitStoreToStackLocalOrContextSlot(var, location); | 2173 __ CallRuntime(Runtime::kThrowReferenceError); |
| 2183 | 2174 __ bind(&assign); |
| 2184 } else if (var->mode() == CONST && op != Token::INIT) { | 2175 } |
| 2185 // Assignment to const variable needs a write barrier. | 2176 if (var->mode() == CONST) { |
| 2186 DCHECK(!var->IsLookupSlot()); | 2177 __ CallRuntime(Runtime::kThrowConstAssignError); |
| 2187 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2178 } else { |
| 2188 Label const_error; | 2179 EmitStoreToStackLocalOrContextSlot(var, location); |
| 2189 MemOperand location = VarOperand(var, r1); | 2180 } |
| 2190 __ ldr(r3, location); | |
| 2191 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | |
| 2192 __ b(ne, &const_error); | |
| 2193 __ mov(r3, Operand(var->name())); | |
| 2194 __ push(r3); | |
| 2195 __ CallRuntime(Runtime::kThrowReferenceError); | |
| 2196 __ bind(&const_error); | |
| 2197 __ CallRuntime(Runtime::kThrowConstAssignError); | |
| 2198 | |
| 2199 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2181 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
| 2200 // Initializing assignment to const {this} needs a write barrier. | 2182 // Initializing assignment to const {this} needs a write barrier. |
| 2201 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2183 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
| 2202 Label uninitialized_this; | 2184 Label uninitialized_this; |
| 2203 MemOperand location = VarOperand(var, r1); | 2185 MemOperand location = VarOperand(var, r1); |
| 2204 __ ldr(r3, location); | 2186 __ ldr(r3, location); |
| 2205 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); | 2187 __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); |
| 2206 __ b(eq, &uninitialized_this); | 2188 __ b(eq, &uninitialized_this); |
| 2207 __ mov(r0, Operand(var->name())); | 2189 __ mov(r0, Operand(var->name())); |
| 2208 __ Push(r0); | 2190 __ Push(r0); |
| (...skipping 1631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3840 DCHECK(interrupt_address == | 3822 DCHECK(interrupt_address == |
| 3841 isolate->builtins()->OnStackReplacement()->entry()); | 3823 isolate->builtins()->OnStackReplacement()->entry()); |
| 3842 return ON_STACK_REPLACEMENT; | 3824 return ON_STACK_REPLACEMENT; |
| 3843 } | 3825 } |
| 3844 | 3826 |
| 3845 | 3827 |
| 3846 } // namespace internal | 3828 } // namespace internal |
| 3847 } // namespace v8 | 3829 } // namespace v8 |
| 3848 | 3830 |
| 3849 #endif // V8_TARGET_ARCH_ARM | 3831 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |