OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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_S390 | 5 #if V8_TARGET_ARCH_S390 |
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 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 __ LoadP(r3, FieldMemOperand(cp, HeapObject::kMapOffset)); | 692 __ LoadP(r3, FieldMemOperand(cp, HeapObject::kMapOffset)); |
693 __ CompareRoot(r3, Heap::kWithContextMapRootIndex); | 693 __ CompareRoot(r3, Heap::kWithContextMapRootIndex); |
694 __ Check(ne, kDeclarationInWithContext); | 694 __ Check(ne, kDeclarationInWithContext); |
695 __ CompareRoot(r3, Heap::kCatchContextMapRootIndex); | 695 __ CompareRoot(r3, Heap::kCatchContextMapRootIndex); |
696 __ Check(ne, kDeclarationInCatchContext); | 696 __ Check(ne, kDeclarationInCatchContext); |
697 } | 697 } |
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 | |
703 // need to "declare" it at runtime to make sure it actually exists in the | |
704 // local context. | |
705 VariableProxy* proxy = declaration->proxy(); | 702 VariableProxy* proxy = declaration->proxy(); |
706 VariableMode mode = declaration->mode(); | |
707 Variable* variable = proxy->var(); | 703 Variable* variable = proxy->var(); |
708 bool hole_init = mode == LET || mode == CONST; | |
709 switch (variable->location()) { | 704 switch (variable->location()) { |
710 case VariableLocation::GLOBAL: | 705 case VariableLocation::GLOBAL: |
711 case VariableLocation::UNALLOCATED: { | 706 case VariableLocation::UNALLOCATED: { |
712 DCHECK(!variable->binding_needs_init()); | 707 DCHECK(!variable->binding_needs_init()); |
713 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); | 708 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); |
714 DCHECK(!slot.IsInvalid()); | 709 DCHECK(!slot.IsInvalid()); |
715 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); | 710 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); |
716 globals_->Add(isolate()->factory()->undefined_value(), zone()); | 711 globals_->Add(isolate()->factory()->undefined_value(), zone()); |
717 break; | 712 break; |
718 } | 713 } |
719 case VariableLocation::PARAMETER: | 714 case VariableLocation::PARAMETER: |
720 case VariableLocation::LOCAL: | 715 case VariableLocation::LOCAL: |
721 if (hole_init) { | 716 if (variable->binding_needs_init()) { |
722 Comment cmnt(masm_, "[ VariableDeclaration"); | 717 Comment cmnt(masm_, "[ VariableDeclaration"); |
723 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 718 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
724 __ StoreP(ip, StackOperand(variable)); | 719 __ StoreP(ip, StackOperand(variable)); |
725 } | 720 } |
726 break; | 721 break; |
727 | 722 |
728 case VariableLocation::CONTEXT: | 723 case VariableLocation::CONTEXT: |
729 if (hole_init) { | 724 if (variable->binding_needs_init()) { |
730 Comment cmnt(masm_, "[ VariableDeclaration"); | 725 Comment cmnt(masm_, "[ VariableDeclaration"); |
731 EmitDebugCheckDeclarationContext(variable); | 726 EmitDebugCheckDeclarationContext(variable); |
732 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 727 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
733 __ StoreP(ip, ContextMemOperand(cp, variable->index())); | 728 __ StoreP(ip, ContextMemOperand(cp, variable->index())); |
734 // No write barrier since the_hole_value is in old space. | 729 // No write barrier since the_hole_value is in old space. |
735 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 730 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
736 } | 731 } |
737 break; | 732 break; |
738 | 733 |
739 case VariableLocation::LOOKUP: { | 734 case VariableLocation::LOOKUP: { |
740 Comment cmnt(masm_, "[ VariableDeclaration"); | 735 Comment cmnt(masm_, "[ VariableDeclaration"); |
741 DCHECK_EQ(VAR, mode); | 736 DCHECK_EQ(VAR, variable->mode()); |
742 DCHECK(!hole_init); | 737 DCHECK(!variable->binding_needs_init()); |
743 __ mov(r4, Operand(variable->name())); | 738 __ mov(r4, Operand(variable->name())); |
744 __ Push(r4); | 739 __ Push(r4); |
745 __ CallRuntime(Runtime::kDeclareEvalVar); | 740 __ CallRuntime(Runtime::kDeclareEvalVar); |
746 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); | 741 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); |
747 break; | 742 break; |
748 } | 743 } |
749 | 744 |
750 case VariableLocation::MODULE: | 745 case VariableLocation::MODULE: |
751 UNREACHABLE(); | 746 UNREACHABLE(); |
752 } | 747 } |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1200 // introducing variables. In those cases, we do not want to | 1195 // introducing variables. In those cases, we do not want to |
1201 // perform a runtime call for all variables in the scope | 1196 // perform a runtime call for all variables in the scope |
1202 // containing the eval. | 1197 // containing the eval. |
1203 Variable* var = proxy->var(); | 1198 Variable* var = proxy->var(); |
1204 if (var->mode() == DYNAMIC_GLOBAL) { | 1199 if (var->mode() == DYNAMIC_GLOBAL) { |
1205 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); | 1200 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); |
1206 __ b(done); | 1201 __ b(done); |
1207 } else if (var->mode() == DYNAMIC_LOCAL) { | 1202 } else if (var->mode() == DYNAMIC_LOCAL) { |
1208 Variable* local = var->local_if_not_shadowed(); | 1203 Variable* local = var->local_if_not_shadowed(); |
1209 __ LoadP(r2, ContextSlotOperandCheckExtensions(local, slow)); | 1204 __ LoadP(r2, ContextSlotOperandCheckExtensions(local, slow)); |
1210 if (local->mode() == LET || local->mode() == CONST) { | 1205 if (local->binding_needs_init()) { |
1211 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 1206 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
1212 __ bne(done); | 1207 __ bne(done); |
1213 __ mov(r2, Operand(var->name())); | 1208 __ mov(r2, Operand(var->name())); |
1214 __ push(r2); | 1209 __ push(r2); |
1215 __ CallRuntime(Runtime::kThrowReferenceError); | 1210 __ CallRuntime(Runtime::kThrowReferenceError); |
| 1211 } else { |
| 1212 __ b(done); |
1216 } | 1213 } |
1217 __ b(done); | |
1218 } | 1214 } |
1219 } | 1215 } |
1220 | 1216 |
1221 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, | 1217 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, |
1222 TypeofMode typeof_mode) { | 1218 TypeofMode typeof_mode) { |
1223 #ifdef DEBUG | 1219 #ifdef DEBUG |
1224 Variable* var = proxy->var(); | 1220 Variable* var = proxy->var(); |
1225 DCHECK(var->IsUnallocatedOrGlobalSlot() || | 1221 DCHECK(var->IsUnallocatedOrGlobalSlot() || |
1226 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); | 1222 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); |
1227 #endif | 1223 #endif |
(...skipping 20 matching lines...) Expand all Loading... |
1248 break; | 1244 break; |
1249 } | 1245 } |
1250 | 1246 |
1251 case VariableLocation::PARAMETER: | 1247 case VariableLocation::PARAMETER: |
1252 case VariableLocation::LOCAL: | 1248 case VariableLocation::LOCAL: |
1253 case VariableLocation::CONTEXT: { | 1249 case VariableLocation::CONTEXT: { |
1254 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); | 1250 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); |
1255 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" | 1251 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" |
1256 : "[ Stack variable"); | 1252 : "[ Stack variable"); |
1257 if (NeedsHoleCheckForLoad(proxy)) { | 1253 if (NeedsHoleCheckForLoad(proxy)) { |
| 1254 // Throw a reference error when using an uninitialized let/const |
| 1255 // binding in harmony mode. |
1258 Label done; | 1256 Label done; |
1259 // Let and const need a read barrier. | |
1260 GetVar(r2, var); | 1257 GetVar(r2, var); |
1261 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); | 1258 __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); |
1262 __ bne(&done); | 1259 __ bne(&done); |
1263 if (var->mode() == LET || var->mode() == CONST) { | 1260 __ mov(r2, Operand(var->name())); |
1264 // Throw a reference error when using an uninitialized let/const | 1261 __ push(r2); |
1265 // binding in harmony mode. | 1262 __ CallRuntime(Runtime::kThrowReferenceError); |
1266 __ mov(r2, Operand(var->name())); | |
1267 __ push(r2); | |
1268 __ CallRuntime(Runtime::kThrowReferenceError); | |
1269 } | |
1270 __ bind(&done); | 1263 __ bind(&done); |
1271 context()->Plug(r2); | 1264 context()->Plug(r2); |
1272 break; | 1265 break; |
1273 } | 1266 } |
1274 context()->Plug(var); | 1267 context()->Plug(var); |
1275 break; | 1268 break; |
1276 } | 1269 } |
1277 | 1270 |
1278 case VariableLocation::LOOKUP: { | 1271 case VariableLocation::LOOKUP: { |
1279 Comment cmnt(masm_, "[ Lookup variable"); | 1272 Comment cmnt(masm_, "[ Lookup variable"); |
(...skipping 854 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2134 | 2127 |
2135 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, | 2128 void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, |
2136 FeedbackVectorSlot slot) { | 2129 FeedbackVectorSlot slot) { |
2137 if (var->IsUnallocated()) { | 2130 if (var->IsUnallocated()) { |
2138 // Global var, const, or let. | 2131 // Global var, const, or let. |
2139 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); | 2132 __ mov(StoreDescriptor::NameRegister(), Operand(var->name())); |
2140 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); | 2133 __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); |
2141 EmitLoadStoreICSlot(slot); | 2134 EmitLoadStoreICSlot(slot); |
2142 CallStoreIC(); | 2135 CallStoreIC(); |
2143 | 2136 |
2144 } else if (var->mode() == LET && op != Token::INIT) { | 2137 } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { |
2145 // Non-initializing assignment to let variable needs a write barrier. | 2138 // Non-initializing assignment to let variable needs a write barrier. |
2146 DCHECK(!var->IsLookupSlot()); | 2139 DCHECK(!var->IsLookupSlot()); |
2147 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2140 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2148 Label assign; | |
2149 MemOperand location = VarOperand(var, r3); | 2141 MemOperand location = VarOperand(var, r3); |
2150 __ LoadP(r5, location); | 2142 // Perform an initialization check for lexically declared variables. |
2151 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2143 if (var->binding_needs_init()) { |
2152 __ bne(&assign); | 2144 Label assign; |
2153 __ mov(r5, Operand(var->name())); | 2145 __ LoadP(r5, location); |
2154 __ push(r5); | 2146 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
2155 __ CallRuntime(Runtime::kThrowReferenceError); | 2147 __ bne(&assign); |
2156 // Perform the assignment. | 2148 __ mov(r5, Operand(var->name())); |
2157 __ bind(&assign); | 2149 __ push(r5); |
2158 EmitStoreToStackLocalOrContextSlot(var, location); | 2150 __ CallRuntime(Runtime::kThrowReferenceError); |
2159 | 2151 __ bind(&assign); |
2160 } else if (var->mode() == CONST && op != Token::INIT) { | 2152 } |
2161 // Assignment to const variable needs a write barrier. | 2153 if (var->mode() == CONST) { |
2162 DCHECK(!var->IsLookupSlot()); | 2154 __ CallRuntime(Runtime::kThrowConstAssignError); |
2163 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2155 } else { |
2164 Label const_error; | 2156 EmitStoreToStackLocalOrContextSlot(var, location); |
2165 MemOperand location = VarOperand(var, r3); | 2157 } |
2166 __ LoadP(r5, location); | |
2167 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | |
2168 __ bne(&const_error, Label::kNear); | |
2169 __ mov(r5, Operand(var->name())); | |
2170 __ push(r5); | |
2171 __ CallRuntime(Runtime::kThrowReferenceError); | |
2172 __ bind(&const_error); | |
2173 __ CallRuntime(Runtime::kThrowConstAssignError); | |
2174 | |
2175 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { | 2158 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { |
2176 // Initializing assignment to const {this} needs a write barrier. | 2159 // Initializing assignment to const {this} needs a write barrier. |
2177 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); | 2160 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); |
2178 Label uninitialized_this; | 2161 Label uninitialized_this; |
2179 MemOperand location = VarOperand(var, r3); | 2162 MemOperand location = VarOperand(var, r3); |
2180 __ LoadP(r5, location); | 2163 __ LoadP(r5, location); |
2181 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); | 2164 __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); |
2182 __ beq(&uninitialized_this); | 2165 __ beq(&uninitialized_this); |
2183 __ mov(r3, Operand(var->name())); | 2166 __ mov(r3, Operand(var->name())); |
2184 __ push(r3); | 2167 __ push(r3); |
(...skipping 1505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3690 DCHECK(kOSRBranchInstruction == br_instr); | 3673 DCHECK(kOSRBranchInstruction == br_instr); |
3691 | 3674 |
3692 DCHECK(interrupt_address == | 3675 DCHECK(interrupt_address == |
3693 isolate->builtins()->OnStackReplacement()->entry()); | 3676 isolate->builtins()->OnStackReplacement()->entry()); |
3694 return ON_STACK_REPLACEMENT; | 3677 return ON_STACK_REPLACEMENT; |
3695 } | 3678 } |
3696 | 3679 |
3697 } // namespace internal | 3680 } // namespace internal |
3698 } // namespace v8 | 3681 } // namespace v8 |
3699 #endif // V8_TARGET_ARCH_S390 | 3682 #endif // V8_TARGET_ARCH_S390 |
OLD | NEW |