| 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 |