Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(260)

Side by Side Diff: src/full-codegen/ia32/full-codegen-ia32.cc

Issue 2201193004: Use Variable::binding_needs_init() to determine hole initialization (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove one more comment Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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_IA32 5 #if V8_TARGET_ARCH_IA32
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 690 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 __ cmp(ebx, isolate()->factory()->with_context_map()); 701 __ cmp(ebx, isolate()->factory()->with_context_map());
702 __ Check(not_equal, kDeclarationInWithContext); 702 __ Check(not_equal, kDeclarationInWithContext);
703 __ cmp(ebx, isolate()->factory()->catch_context_map()); 703 __ cmp(ebx, isolate()->factory()->catch_context_map());
704 __ Check(not_equal, kDeclarationInCatchContext); 704 __ Check(not_equal, kDeclarationInCatchContext);
705 } 705 }
706 } 706 }
707 707
708 708
709 void FullCodeGenerator::VisitVariableDeclaration( 709 void FullCodeGenerator::VisitVariableDeclaration(
710 VariableDeclaration* declaration) { 710 VariableDeclaration* declaration) {
711 // If it was not possible to allocate the variable at compile time, we
712 // need to "declare" it at runtime to make sure it actually exists in the
713 // local context.
714 VariableProxy* proxy = declaration->proxy(); 711 VariableProxy* proxy = declaration->proxy();
715 VariableMode mode = declaration->mode();
716 Variable* variable = proxy->var(); 712 Variable* variable = proxy->var();
717 bool hole_init = mode == LET || mode == CONST;
718 switch (variable->location()) { 713 switch (variable->location()) {
719 case VariableLocation::GLOBAL: 714 case VariableLocation::GLOBAL:
720 case VariableLocation::UNALLOCATED: { 715 case VariableLocation::UNALLOCATED: {
721 DCHECK(!variable->binding_needs_init()); 716 DCHECK(!variable->binding_needs_init());
722 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); 717 FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
723 DCHECK(!slot.IsInvalid()); 718 DCHECK(!slot.IsInvalid());
724 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone()); 719 globals_->Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
725 globals_->Add(isolate()->factory()->undefined_value(), zone()); 720 globals_->Add(isolate()->factory()->undefined_value(), zone());
726 break; 721 break;
727 } 722 }
728 case VariableLocation::PARAMETER: 723 case VariableLocation::PARAMETER:
729 case VariableLocation::LOCAL: 724 case VariableLocation::LOCAL:
730 if (hole_init) { 725 if (variable->binding_needs_init()) {
731 Comment cmnt(masm_, "[ VariableDeclaration"); 726 Comment cmnt(masm_, "[ VariableDeclaration");
732 __ mov(StackOperand(variable), 727 __ mov(StackOperand(variable),
733 Immediate(isolate()->factory()->the_hole_value())); 728 Immediate(isolate()->factory()->the_hole_value()));
734 } 729 }
735 break; 730 break;
736 731
737 case VariableLocation::CONTEXT: 732 case VariableLocation::CONTEXT:
738 if (hole_init) { 733 if (variable->binding_needs_init()) {
739 Comment cmnt(masm_, "[ VariableDeclaration"); 734 Comment cmnt(masm_, "[ VariableDeclaration");
740 EmitDebugCheckDeclarationContext(variable); 735 EmitDebugCheckDeclarationContext(variable);
741 __ mov(ContextOperand(esi, variable->index()), 736 __ mov(ContextOperand(esi, variable->index()),
742 Immediate(isolate()->factory()->the_hole_value())); 737 Immediate(isolate()->factory()->the_hole_value()));
743 // No write barrier since the hole value is in old space. 738 // No write barrier since the hole value is in old space.
744 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 739 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
745 } 740 }
746 break; 741 break;
747 742
748 case VariableLocation::LOOKUP: { 743 case VariableLocation::LOOKUP: {
749 Comment cmnt(masm_, "[ VariableDeclaration"); 744 Comment cmnt(masm_, "[ VariableDeclaration");
750 DCHECK_EQ(VAR, mode); 745 DCHECK_EQ(VAR, variable->mode());
751 DCHECK(!hole_init); 746 DCHECK(!variable->binding_needs_init());
752 __ push(Immediate(variable->name())); 747 __ push(Immediate(variable->name()));
753 __ CallRuntime(Runtime::kDeclareEvalVar); 748 __ CallRuntime(Runtime::kDeclareEvalVar);
754 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); 749 PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
755 break; 750 break;
756 } 751 }
757 } 752 }
758 } 753 }
759 754
760 755
761 void FullCodeGenerator::VisitFunctionDeclaration( 756 void FullCodeGenerator::VisitFunctionDeclaration(
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 // introducing variables. In those cases, we do not want to 1184 // introducing variables. In those cases, we do not want to
1190 // perform a runtime call for all variables in the scope 1185 // perform a runtime call for all variables in the scope
1191 // containing the eval. 1186 // containing the eval.
1192 Variable* var = proxy->var(); 1187 Variable* var = proxy->var();
1193 if (var->mode() == DYNAMIC_GLOBAL) { 1188 if (var->mode() == DYNAMIC_GLOBAL) {
1194 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow); 1189 EmitLoadGlobalCheckExtensions(proxy, typeof_mode, slow);
1195 __ jmp(done); 1190 __ jmp(done);
1196 } else if (var->mode() == DYNAMIC_LOCAL) { 1191 } else if (var->mode() == DYNAMIC_LOCAL) {
1197 Variable* local = var->local_if_not_shadowed(); 1192 Variable* local = var->local_if_not_shadowed();
1198 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow)); 1193 __ mov(eax, ContextSlotOperandCheckExtensions(local, slow));
1199 if (local->mode() == LET || local->mode() == CONST) { 1194 if (local->binding_needs_init()) {
1200 __ cmp(eax, isolate()->factory()->the_hole_value()); 1195 __ cmp(eax, isolate()->factory()->the_hole_value());
1201 __ j(not_equal, done); 1196 __ j(not_equal, done);
1202 __ push(Immediate(var->name())); 1197 __ push(Immediate(var->name()));
1203 __ CallRuntime(Runtime::kThrowReferenceError); 1198 __ CallRuntime(Runtime::kThrowReferenceError);
1199 } else {
1200 __ jmp(done);
1204 } 1201 }
1205 __ jmp(done);
1206 } 1202 }
1207 } 1203 }
1208 1204
1209 1205
1210 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy, 1206 void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
1211 TypeofMode typeof_mode) { 1207 TypeofMode typeof_mode) {
1212 #ifdef DEBUG 1208 #ifdef DEBUG
1213 Variable* var = proxy->var(); 1209 Variable* var = proxy->var();
1214 DCHECK(var->IsUnallocatedOrGlobalSlot() || 1210 DCHECK(var->IsUnallocatedOrGlobalSlot() ||
1215 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL)); 1211 (var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
(...skipping 22 matching lines...) Expand all
1238 } 1234 }
1239 1235
1240 case VariableLocation::PARAMETER: 1236 case VariableLocation::PARAMETER:
1241 case VariableLocation::LOCAL: 1237 case VariableLocation::LOCAL:
1242 case VariableLocation::CONTEXT: { 1238 case VariableLocation::CONTEXT: {
1243 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); 1239 DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode);
1244 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" 1240 Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable"
1245 : "[ Stack variable"); 1241 : "[ Stack variable");
1246 1242
1247 if (NeedsHoleCheckForLoad(proxy)) { 1243 if (NeedsHoleCheckForLoad(proxy)) {
1248 // Let and const need a read barrier. 1244 // Throw a reference error when using an uninitialized let/const
1245 // binding in harmony mode.
1249 Label done; 1246 Label done;
1250 GetVar(eax, var); 1247 GetVar(eax, var);
1251 __ cmp(eax, isolate()->factory()->the_hole_value()); 1248 __ cmp(eax, isolate()->factory()->the_hole_value());
1252 __ j(not_equal, &done, Label::kNear); 1249 __ j(not_equal, &done, Label::kNear);
1253 if (var->mode() == LET || var->mode() == CONST) { 1250 __ push(Immediate(var->name()));
1254 // Throw a reference error when using an uninitialized let/const 1251 __ CallRuntime(Runtime::kThrowReferenceError);
1255 // binding in harmony mode.
1256 __ push(Immediate(var->name()));
1257 __ CallRuntime(Runtime::kThrowReferenceError);
1258 }
1259 __ bind(&done); 1252 __ bind(&done);
1260 context()->Plug(eax); 1253 context()->Plug(eax);
1261 break; 1254 break;
1262 } 1255 }
1263 context()->Plug(var); 1256 context()->Plug(var);
1264 break; 1257 break;
1265 } 1258 }
1266 1259
1267 case VariableLocation::LOOKUP: { 1260 case VariableLocation::LOOKUP: {
1268 Comment cmnt(masm_, "[ Lookup variable"); 1261 Comment cmnt(masm_, "[ Lookup variable");
(...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after
2068 if (var->IsUnallocated()) { 2061 if (var->IsUnallocated()) {
2069 // Global var, const, or let. 2062 // Global var, const, or let.
2070 __ mov(StoreDescriptor::NameRegister(), var->name()); 2063 __ mov(StoreDescriptor::NameRegister(), var->name());
2071 __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); 2064 __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand());
2072 __ mov(StoreDescriptor::ReceiverRegister(), 2065 __ mov(StoreDescriptor::ReceiverRegister(),
2073 ContextOperand(StoreDescriptor::ReceiverRegister(), 2066 ContextOperand(StoreDescriptor::ReceiverRegister(),
2074 Context::EXTENSION_INDEX)); 2067 Context::EXTENSION_INDEX));
2075 EmitLoadStoreICSlot(slot); 2068 EmitLoadStoreICSlot(slot);
2076 CallStoreIC(); 2069 CallStoreIC();
2077 2070
2078 } else if (var->mode() == LET && op != Token::INIT) { 2071 } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) {
2079 // Non-initializing assignment to let variable needs a write barrier.
2080 DCHECK(!var->IsLookupSlot()); 2072 DCHECK(!var->IsLookupSlot());
2081 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2073 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2082 Label assign;
2083 MemOperand location = VarOperand(var, ecx); 2074 MemOperand location = VarOperand(var, ecx);
2084 __ mov(edx, location); 2075 // Perform an initialization check for lexically declared variables.
2085 __ cmp(edx, isolate()->factory()->the_hole_value()); 2076 if (var->binding_needs_init()) {
2086 __ j(not_equal, &assign, Label::kNear); 2077 Label assign;
2087 __ push(Immediate(var->name())); 2078 __ mov(edx, location);
2088 __ CallRuntime(Runtime::kThrowReferenceError); 2079 __ cmp(edx, isolate()->factory()->the_hole_value());
2089 __ bind(&assign); 2080 __ j(not_equal, &assign, Label::kNear);
2090 EmitStoreToStackLocalOrContextSlot(var, location); 2081 __ push(Immediate(var->name()));
2091 2082 __ CallRuntime(Runtime::kThrowReferenceError);
2092 } else if (var->mode() == CONST && op != Token::INIT) { 2083 __ bind(&assign);
2093 // Assignment to const variable needs a write barrier. 2084 }
2094 DCHECK(!var->IsLookupSlot()); 2085 if (var->mode() == CONST) {
2095 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2086 __ CallRuntime(Runtime::kThrowConstAssignError);
2096 Label const_error; 2087 } else {
2097 MemOperand location = VarOperand(var, ecx); 2088 EmitStoreToStackLocalOrContextSlot(var, location);
2098 __ mov(edx, location); 2089 }
2099 __ cmp(edx, isolate()->factory()->the_hole_value());
2100 __ j(not_equal, &const_error, Label::kNear);
2101 __ push(Immediate(var->name()));
2102 __ CallRuntime(Runtime::kThrowReferenceError);
2103 __ bind(&const_error);
2104 __ CallRuntime(Runtime::kThrowConstAssignError);
2105
2106 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { 2090 } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) {
2107 // Initializing assignment to const {this} needs a write barrier. 2091 // Initializing assignment to const {this} needs a write barrier.
2108 DCHECK(var->IsStackAllocated() || var->IsContextSlot()); 2092 DCHECK(var->IsStackAllocated() || var->IsContextSlot());
2109 Label uninitialized_this; 2093 Label uninitialized_this;
2110 MemOperand location = VarOperand(var, ecx); 2094 MemOperand location = VarOperand(var, ecx);
2111 __ mov(edx, location); 2095 __ mov(edx, location);
2112 __ cmp(edx, isolate()->factory()->the_hole_value()); 2096 __ cmp(edx, isolate()->factory()->the_hole_value());
2113 __ j(equal, &uninitialized_this); 2097 __ j(equal, &uninitialized_this);
2114 __ push(Immediate(var->name())); 2098 __ push(Immediate(var->name()));
2115 __ CallRuntime(Runtime::kThrowReferenceError); 2099 __ CallRuntime(Runtime::kThrowReferenceError);
(...skipping 1555 matching lines...) Expand 10 before | Expand all | Expand 10 after
3671 isolate->builtins()->OnStackReplacement()->entry(), 3655 isolate->builtins()->OnStackReplacement()->entry(),
3672 Assembler::target_address_at(call_target_address, unoptimized_code)); 3656 Assembler::target_address_at(call_target_address, unoptimized_code));
3673 return ON_STACK_REPLACEMENT; 3657 return ON_STACK_REPLACEMENT;
3674 } 3658 }
3675 3659
3676 3660
3677 } // namespace internal 3661 } // namespace internal
3678 } // namespace v8 3662 } // namespace v8
3679 3663
3680 #endif // V8_TARGET_ARCH_IA32 3664 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/full-codegen/arm64/full-codegen-arm64.cc ('k') | src/full-codegen/mips/full-codegen-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698