diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc index 3318fac942..cca75e6665 100644 --- a/src/compiler/ast-graph-builder.cc +++ b/src/compiler/ast-graph-builder.cc @@ -924,9 +924,9 @@ void AstGraphBuilder::Visit(Expression* expr) { void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { Variable* variable = decl->proxy()->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals()->push_back(variable->name()); FeedbackVectorSlot slot = decl->proxy()->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -936,17 +936,7 @@ void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Node* value = jsgraph()->TheHoleConstant(); - environment()->Bind(variable, value); - } - break; case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Node* value = jsgraph()->TheHoleConstant(); - const Operator* op = javascript()->StoreContext(0, variable->index()); - NewNode(op, value); - } break; case VariableLocation::LOOKUP: case VariableLocation::MODULE: @@ -2482,47 +2472,12 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) { return object; } -Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable, - Node* not_hole, - BailoutId bailout_id) { - IfBuilder hole_check(this); - Node* the_hole = jsgraph()->TheHoleConstant(); - Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), - value, the_hole); - hole_check.If(check); - hole_check.Then(); - Node* error = BuildThrowReferenceError(variable, bailout_id); - environment()->Push(error); - hole_check.Else(); - environment()->Push(not_hole); - hole_check.End(); - return environment()->Pop(); -} - - -Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable, - Node* for_hole, - BailoutId bailout_id) { - IfBuilder hole_check(this); - Node* the_hole = jsgraph()->TheHoleConstant(); - Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), - value, the_hole); - hole_check.If(check); - hole_check.Then(); - environment()->Push(for_hole); - hole_check.Else(); - Node* error = BuildThrowReferenceError(variable, bailout_id); - environment()->Push(error); - hole_check.End(); - return environment()->Pop(); -} - Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, BailoutId bailout_id, const VectorSlotPair& feedback, OutputFrameStateCombine combine, TypeofMode typeof_mode) { - Node* the_hole = jsgraph()->TheHoleConstant(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { // Global var, const, or let variable. @@ -2533,19 +2488,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, return value; } case VariableLocation::PARAMETER: - case VariableLocation::LOCAL: { - // Local var, const, or let variable. - Node* value = environment()->Lookup(variable); - if (variable->binding_needs_init()) { - // Perform check for uninitialized let/const variables. - if (value->op() == the_hole->op()) { - value = BuildThrowReferenceError(variable, bailout_id); - } else if (value->opcode() == IrOpcode::kPhi) { - value = BuildHoleCheckThenThrow(value, variable, value, bailout_id); - } - } - return value; - } + case VariableLocation::LOCAL: + // Local variable. + return environment()->Lookup(variable); case VariableLocation::CONTEXT: { // Context variable (potentially up the context chain). int depth = current_scope()->ContextChainLength(variable->scope()); @@ -2556,15 +2501,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable, info()->is_function_context_specializing(); const Operator* op = javascript()->LoadContext(depth, variable->index(), immutable); - Node* value = NewNode(op); - // TODO(titzer): initialization checks are redundant for already - // initialized immutable context loads, but only specialization knows. - // Maybe specializer should be a parameter to the graph builder? - if (variable->binding_needs_init()) { - // Perform check for uninitialized let/const variables. - value = BuildHoleCheckThenThrow(value, variable, value, bailout_id); - } - return value; + return NewNode(op); } case VariableLocation::LOOKUP: case VariableLocation::MODULE: @@ -2606,8 +2543,7 @@ Node* AstGraphBuilder::BuildVariableAssignment( Variable* variable, Node* value, Token::Value op, const VectorSlotPair& feedback, BailoutId bailout_id, OutputFrameStateCombine combine) { - Node* the_hole = jsgraph()->TheHoleConstant(); - VariableMode mode = variable->mode(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { // Global var, const, or let variable. @@ -2618,93 +2554,33 @@ Node* AstGraphBuilder::BuildVariableAssignment( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - // Local var, const, or let variable. - if (mode == LET && op == Token::INIT) { - // No initialization check needed because scoping guarantees it. Note - // that we still perform a lookup to keep the variable live, because - // baseline code might contain debug code that inspects the variable. - Node* current = environment()->Lookup(variable); - CHECK_NOT_NULL(current); - } else if (mode == LET && op != Token::INIT && - variable->binding_needs_init()) { - // Perform an initialization check for let declared variables. - Node* current = environment()->Lookup(variable); - if (current->op() == the_hole->op()) { - return BuildThrowReferenceError(variable, bailout_id); - } else if (current->opcode() == IrOpcode::kPhi) { - BuildHoleCheckThenThrow(current, variable, value, bailout_id); - } - } else if (mode == CONST && op == Token::INIT) { - // Perform an initialization check for const {this} variables. - // Note that the {this} variable is the only const variable being able - // to trigger bind operations outside the TDZ, via {super} calls. - Node* current = environment()->Lookup(variable); - if (current->op() != the_hole->op() && variable->is_this()) { - value = BuildHoleCheckElseThrow(current, variable, value, bailout_id); - } - } else if (mode == CONST && op != Token::INIT && - variable->is_sloppy_function_name()) { + DCHECK(!variable->is_this()); + if (variable->mode() == CONST && op != Token::INIT) { // Non-initializing assignment to sloppy function names is // - exception in strict mode. // - ignored in sloppy mode. - DCHECK(!variable->binding_needs_init()); + DCHECK(variable->is_sloppy_function_name()); if (variable->throw_on_const_assignment(language_mode())) { return BuildThrowConstAssignError(bailout_id); } return value; - } else if (mode == CONST && op != Token::INIT) { - if (variable->binding_needs_init()) { - Node* current = environment()->Lookup(variable); - if (current->op() == the_hole->op()) { - return BuildThrowReferenceError(variable, bailout_id); - } else if (current->opcode() == IrOpcode::kPhi) { - BuildHoleCheckThenThrow(current, variable, value, bailout_id); - } - } - // Assignment to const is exception in all modes. - return BuildThrowConstAssignError(bailout_id); } environment()->Bind(variable, value); return value; case VariableLocation::CONTEXT: { + DCHECK(!variable->is_this()); // Context variable (potentially up the context chain). - int depth = current_scope()->ContextChainLength(variable->scope()); - if (mode == LET && op != Token::INIT && variable->binding_needs_init()) { - // Perform an initialization check for let declared variables. - const Operator* op = - javascript()->LoadContext(depth, variable->index(), false); - Node* current = NewNode(op); - value = BuildHoleCheckThenThrow(current, variable, value, bailout_id); - } else if (mode == CONST && op == Token::INIT) { - // Perform an initialization check for const {this} variables. - // Note that the {this} variable is the only const variable being able - // to trigger bind operations outside the TDZ, via {super} calls. - if (variable->is_this()) { - const Operator* op = - javascript()->LoadContext(depth, variable->index(), false); - Node* current = NewNode(op); - value = BuildHoleCheckElseThrow(current, variable, value, bailout_id); - } - } else if (mode == CONST && op != Token::INIT && - variable->is_sloppy_function_name()) { + if (variable->mode() == CONST && op != Token::INIT) { // Non-initializing assignment to sloppy function names is // - exception in strict mode. // - ignored in sloppy mode. - DCHECK(!variable->binding_needs_init()); + DCHECK(variable->is_sloppy_function_name()); if (variable->throw_on_const_assignment(language_mode())) { return BuildThrowConstAssignError(bailout_id); } return value; - } else if (mode == CONST && op != Token::INIT) { - if (variable->binding_needs_init()) { - const Operator* op = - javascript()->LoadContext(depth, variable->index(), false); - Node* current = NewNode(op); - BuildHoleCheckThenThrow(current, variable, value, bailout_id); - } - // Assignment to const is exception in all modes. - return BuildThrowConstAssignError(bailout_id); } + int depth = current_scope()->ContextChainLength(variable->scope()); const Operator* op = javascript()->StoreContext(depth, variable->index()); return NewNode(op, value); } @@ -2821,18 +2697,6 @@ Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) { } -Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable, - BailoutId bailout_id) { - Node* variable_name = jsgraph()->Constant(variable->name()); - const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError); - Node* call = NewNode(op, variable_name); - PrepareFrameState(call, bailout_id); - Node* control = NewNode(common()->Throw(), call); - UpdateControlDependencyToLeaveFunction(control); - return call; -} - - Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) { const Operator* op = javascript()->CallRuntime(Runtime::kThrowConstAssignError); diff --git a/src/compiler/ast-graph-builder.h b/src/compiler/ast-graph-builder.h index 975e08094c..0211c72153 100644 --- a/src/compiler/ast-graph-builder.h +++ b/src/compiler/ast-graph-builder.h @@ -309,15 +309,8 @@ class AstGraphBuilder : public AstVisitor { // Builders for error reporting at runtime. Node* BuildThrowError(Node* exception, BailoutId bailout_id); - Node* BuildThrowReferenceError(Variable* var, BailoutId bailout_id); Node* BuildThrowConstAssignError(BailoutId bailout_id); - // Builders for dynamic hole-checks at runtime. - Node* BuildHoleCheckThenThrow(Node* value, Variable* var, Node* not_hole, - BailoutId bailout_id); - Node* BuildHoleCheckElseThrow(Node* value, Variable* var, Node* for_hole, - BailoutId bailout_id); - // Builders for non-local control flow. Node* BuildReturn(Node* return_value); Node* BuildThrow(Node* exception_value); diff --git a/src/full-codegen/arm/full-codegen-arm.cc b/src/full-codegen/arm/full-codegen-arm.cc index edd9f5c743..c3b9a7cc5d 100644 --- a/src/full-codegen/arm/full-codegen-arm.cc +++ b/src/full-codegen/arm/full-codegen-arm.cc @@ -755,9 +755,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -767,22 +767,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); - __ str(r0, StackOperand(variable)); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ LoadRoot(r0, Heap::kTheHoleValueRootIndex); - __ str(r0, ContextMemOperand(cp, variable->index())); - // No write barrier since the_hole_value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1147,6 +1132,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variables and all other types of variables. switch (var->location()) { @@ -1163,20 +1149,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" : "[ Stack variable"); - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(r0, var); - __ CompareRoot(r0, Heap::kTheHoleValueRootIndex); - __ b(ne, &done); - __ mov(r0, Operand(var->name())); - __ push(r0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(r0); - break; - } context()->Plug(var); break; } @@ -1493,8 +1465,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(r0); break; @@ -1676,8 +1647,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1720,60 +1690,22 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, r1); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ ldr(r3, location); - __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); - __ b(ne, &assign); - __ mov(r3, Operand(var->name())); - __ push(r3); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, r1); - __ ldr(r3, location); - __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); - __ b(eq, &uninitialized_this); - __ mov(r0, Operand(var->name())); - __ Push(r0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK(var->IsStackAllocated() || var->IsContextSlot()); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, r1); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ ldr(r2, location); - __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); - __ Check(eq, kLetBindingReInitialization); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2505,8 +2437,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { VariableProxy* proxy = expr->expression()->AsVariableProxy(); if (expr->is_postfix()) { { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(r0); @@ -2517,8 +2449,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { context()->PlugTOS(); } } else { - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(r0); diff --git a/src/full-codegen/arm64/full-codegen-arm64.cc b/src/full-codegen/arm64/full-codegen-arm64.cc index 179965f14b..494c656d6e 100644 --- a/src/full-codegen/arm64/full-codegen-arm64.cc +++ b/src/full-codegen/arm64/full-codegen-arm64.cc @@ -750,9 +750,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -762,22 +762,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); - __ Str(x10, StackOperand(variable)); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ LoadRoot(x10, Heap::kTheHoleValueRootIndex); - __ Str(x10, ContextMemOperand(cp, variable->index())); - // No write barrier since the_hole_value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1134,6 +1119,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variables and all other types of variables. switch (var->location()) { @@ -1151,19 +1137,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, Comment cmnt(masm_, var->IsContextSlot() ? "Context variable" : "Stack variable"); - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(x0, var); - __ JumpIfNotRoot(x0, Heap::kTheHoleValueRootIndex, &done); - __ Mov(x0, Operand(var->name())); - __ Push(x0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ Bind(&done); - context()->Plug(x0); - break; - } context()->Plug(var); break; } @@ -1477,8 +1450,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(x0); break; @@ -1619,8 +1591,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1665,58 +1636,23 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment"); + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, x1); - // Perform an initialization check for lexically declared variables. - if (var->binding_needs_init()) { - Label assign; - __ Ldr(x10, location); - __ JumpIfNotRoot(x10, Heap::kTheHoleValueRootIndex, &assign); - __ Mov(x10, Operand(var->name())); - __ Push(x10); - __ CallRuntime(Runtime::kThrowReferenceError); - __ Bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, x1); - __ Ldr(x10, location); - __ JumpIfRoot(x10, Heap::kTheHoleValueRootIndex, &uninitialized_this); - __ Mov(x0, Operand(var->name())); - __ Push(x0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK(var->IsStackAllocated() || var->IsContextSlot()); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, x1); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - __ Ldr(x10, location); - __ CompareRoot(x10, Heap::kTheHoleValueRootIndex); - __ Check(eq, kLetBindingReInitialization); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2471,8 +2407,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { VariableProxy* proxy = expr->expression()->AsVariableProxy(); if (expr->is_postfix()) { { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(x0); @@ -2483,8 +2419,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { context()->PlugTOS(); } } else { - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(x0); diff --git a/src/full-codegen/full-codegen.h b/src/full-codegen/full-codegen.h index cdf4d1fa06..b5c432cc1a 100644 --- a/src/full-codegen/full-codegen.h +++ b/src/full-codegen/full-codegen.h @@ -475,8 +475,7 @@ class FullCodeGenerator final : public AstVisitor { // Complete a variable assignment. The right-hand-side value is expected // in the accumulator. void EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode); + FeedbackVectorSlot slot); // Helper functions to EmitVariableAssignment void EmitStoreToStackLocalOrContextSlot(Variable* var, diff --git a/src/full-codegen/ia32/full-codegen-ia32.cc b/src/full-codegen/ia32/full-codegen-ia32.cc index 6a046f3cdf..fb1674f020 100644 --- a/src/full-codegen/ia32/full-codegen-ia32.cc +++ b/src/full-codegen/ia32/full-codegen-ia32.cc @@ -703,9 +703,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -715,22 +715,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ mov(StackOperand(variable), - Immediate(isolate()->factory()->the_hole_value())); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ mov(ContextOperand(esi, variable->index()), - Immediate(isolate()->factory()->the_hole_value())); - // No write barrier since the hole value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1074,6 +1059,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variables and all other types of variables. switch (var->location()) { @@ -1090,20 +1076,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" : "[ Stack variable"); - - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(eax, var); - __ cmp(eax, isolate()->factory()->the_hole_value()); - __ j(not_equal, &done, Label::kNear); - __ push(Immediate(var->name())); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(eax); - break; - } context()->Plug(var); break; } @@ -1419,8 +1391,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(eax); break; @@ -1601,8 +1572,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1643,8 +1613,8 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); @@ -1653,51 +1623,15 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, Context::EXTENSION_INDEX)); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, ecx); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ mov(edx, location); - __ cmp(edx, isolate()->factory()->the_hole_value()); - __ j(not_equal, &assign, Label::kNear); - __ push(Immediate(var->name())); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, ecx); - __ mov(edx, location); - __ cmp(edx, isolate()->factory()->the_hole_value()); - __ j(equal, &uninitialized_this); - __ push(Immediate(var->name())); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK(var->IsStackAllocated() || var->IsContextSlot()); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, ecx); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ mov(edx, location); - __ cmp(edx, isolate()->factory()->the_hole_value()); - __ Check(equal, kLetBindingReInitialization); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2439,8 +2373,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { // Perform the assignment as if via '='. { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(eax); @@ -2452,8 +2386,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } else { // Perform the assignment as if via '='. - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(eax); diff --git a/src/full-codegen/mips/full-codegen-mips.cc b/src/full-codegen/mips/full-codegen-mips.cc index 298ec7fb08..a2135643ff 100644 --- a/src/full-codegen/mips/full-codegen-mips.cc +++ b/src/full-codegen/mips/full-codegen-mips.cc @@ -754,9 +754,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -766,22 +766,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); - __ sw(t0, StackOperand(variable)); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - __ sw(at, ContextMemOperand(cp, variable->index())); - // No write barrier since the_hole_value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1146,6 +1131,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variables and all other types of variables. switch (var->location()) { @@ -1162,21 +1148,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" : "[ Stack variable"); - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(v0, var); - __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - __ subu(at, v0, at); // Sub as compare: at == 0 on eq. - __ Branch(&done, ne, at, Operand(zero_reg)); - __ li(a0, Operand(var->name())); - __ push(a0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(v0); - break; - } context()->Plug(var); break; } @@ -1496,8 +1467,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(v0); break; @@ -1689,8 +1659,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1733,61 +1702,23 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::ValueRegister(), result_register()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, a1); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ lw(a3, location); - __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); - __ Branch(&assign, ne, a3, Operand(t0)); - __ li(a3, Operand(var->name())); - __ push(a3); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, a1); - __ lw(a3, location); - __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - __ Branch(&uninitialized_this, eq, a3, Operand(at)); - __ li(a0, Operand(var->name())); - __ Push(a0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK((var->IsStackAllocated() || var->IsContextSlot())); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, a1); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ lw(a2, location); - __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); - __ Check(eq, kLetBindingReInitialization, a2, Operand(t0)); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2529,8 +2460,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { VariableProxy* proxy = expr->expression()->AsVariableProxy(); if (expr->is_postfix()) { { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(v0); @@ -2541,8 +2472,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { context()->PlugTOS(); } } else { - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(v0); diff --git a/src/full-codegen/mips64/full-codegen-mips64.cc b/src/full-codegen/mips64/full-codegen-mips64.cc index 019123dcea..9df8cb728d 100644 --- a/src/full-codegen/mips64/full-codegen-mips64.cc +++ b/src/full-codegen/mips64/full-codegen-mips64.cc @@ -754,9 +754,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -766,22 +766,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); - __ sd(a4, StackOperand(variable)); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - __ sd(at, ContextMemOperand(cp, variable->index())); - // No write barrier since the_hole_value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1148,6 +1133,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variables and all other types of variables. switch (var->location()) { @@ -1164,21 +1150,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" : "[ Stack variable"); - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(v0, var); - __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - __ dsubu(at, v0, at); // Sub as compare: at == 0 on eq. - __ Branch(&done, ne, at, Operand(zero_reg)); - __ li(a0, Operand(var->name())); - __ push(a0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(v0); - break; - } context()->Plug(var); break; } @@ -1498,8 +1469,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(v0); break; @@ -1690,8 +1660,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1734,61 +1703,23 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::ValueRegister(), result_register()); __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, a1); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ ld(a3, location); - __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); - __ Branch(&assign, ne, a3, Operand(a4)); - __ li(a3, Operand(var->name())); - __ push(a3); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, a1); - __ ld(a3, location); - __ LoadRoot(at, Heap::kTheHoleValueRootIndex); - __ Branch(&uninitialized_this, eq, a3, Operand(at)); - __ li(a0, Operand(var->name())); - __ Push(a0); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK((var->IsStackAllocated() || var->IsContextSlot())); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, a1); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ ld(a2, location); - __ LoadRoot(a4, Heap::kTheHoleValueRootIndex); - __ Check(eq, kLetBindingReInitialization, a2, Operand(a4)); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2530,8 +2461,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { VariableProxy* proxy = expr->expression()->AsVariableProxy(); if (expr->is_postfix()) { { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(v0); @@ -2542,8 +2473,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { context()->PlugTOS(); } } else { - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(v0); diff --git a/src/full-codegen/ppc/full-codegen-ppc.cc b/src/full-codegen/ppc/full-codegen-ppc.cc index 418ba26f5f..3dfdec74ba 100644 --- a/src/full-codegen/ppc/full-codegen-ppc.cc +++ b/src/full-codegen/ppc/full-codegen-ppc.cc @@ -723,9 +723,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -735,22 +735,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ StoreP(ip, StackOperand(variable)); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ StoreP(ip, ContextMemOperand(cp, variable->index()), r0); - // No write barrier since the_hole_value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1118,6 +1103,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variables and all other types of variables. switch (var->location()) { @@ -1134,20 +1120,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" : "[ Stack variable"); - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(r3, var); - __ CompareRoot(r3, Heap::kTheHoleValueRootIndex); - __ bne(&done); - __ mov(r3, Operand(var->name())); - __ push(r3); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(r3); - break; - } context()->Plug(var); break; } @@ -1461,8 +1433,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(r3); break; @@ -1689,8 +1660,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1733,60 +1703,22 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, r4); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ LoadP(r6, location); - __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); - __ bne(&assign); - __ mov(r6, Operand(var->name())); - __ push(r6); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, r4); - __ LoadP(r6, location); - __ CompareRoot(r6, Heap::kTheHoleValueRootIndex); - __ beq(&uninitialized_this); - __ mov(r4, Operand(var->name())); - __ push(r4); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK((var->IsStackAllocated() || var->IsContextSlot())); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, r4); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ LoadP(r5, location); - __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); - __ Check(eq, kLetBindingReInitialization); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2517,8 +2449,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(r3); @@ -2529,8 +2461,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { context()->PlugTOS(); } } else { - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(r3); diff --git a/src/full-codegen/s390/full-codegen-s390.cc b/src/full-codegen/s390/full-codegen-s390.cc index 9afdbdba80..f66934a8f1 100644 --- a/src/full-codegen/s390/full-codegen-s390.cc +++ b/src/full-codegen/s390/full-codegen-s390.cc @@ -696,9 +696,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -708,22 +708,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ StoreP(ip, StackOperand(variable)); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); - __ StoreP(ip, ContextMemOperand(cp, variable->index())); - // No write barrier since the_hole_value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1099,20 +1084,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" : "[ Stack variable"); - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(r2, var); - __ CompareRoot(r2, Heap::kTheHoleValueRootIndex); - __ bne(&done); - __ mov(r2, Operand(var->name())); - __ push(r2); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(r2); - break; - } context()->Plug(var); break; } @@ -1422,8 +1393,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(r2); break; @@ -1649,8 +1619,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1692,60 +1661,22 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - // Non-initializing assignment to let variable needs a write barrier. - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, r3); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ LoadP(r5, location); - __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); - __ bne(&assign); - __ mov(r5, Operand(var->name())); - __ push(r5); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, r3); - __ LoadP(r5, location); - __ CompareRoot(r5, Heap::kTheHoleValueRootIndex); - __ beq(&uninitialized_this); - __ mov(r3, Operand(var->name())); - __ push(r3); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK((var->IsStackAllocated() || var->IsContextSlot())); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, r3); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ LoadP(r4, location); - __ CompareRoot(r4, Heap::kTheHoleValueRootIndex); - __ Check(eq, kLetBindingReInitialization); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2458,8 +2389,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(r2); @@ -2470,8 +2401,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { context()->PlugTOS(); } } else { - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(r2); diff --git a/src/full-codegen/x64/full-codegen-x64.cc b/src/full-codegen/x64/full-codegen-x64.cc index 1c890f2c31..bf1cc1a26c 100644 --- a/src/full-codegen/x64/full-codegen-x64.cc +++ b/src/full-codegen/x64/full-codegen-x64.cc @@ -717,9 +717,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -729,22 +729,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); - __ movp(StackOperand(variable), kScratchRegister); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); - __ movp(ContextOperand(rsi, variable->index()), kScratchRegister); - // No write barrier since the hole value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1104,6 +1089,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variable, and all other types of variables. switch (var->location()) { @@ -1120,20 +1106,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context slot" : "[ Stack slot"); - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - DCHECK(IsLexicalVariableMode(var->mode())); - Label done; - GetVar(rax, var); - __ CompareRoot(rax, Heap::kTheHoleValueRootIndex); - __ j(not_equal, &done, Label::kNear); - __ Push(var->name()); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(rax); - break; - } context()->Plug(var); break; } @@ -1446,8 +1418,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(rax); break; @@ -1593,8 +1564,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1635,59 +1605,22 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ LoadGlobalObject(StoreDescriptor::ReceiverRegister()); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, rcx); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ movp(rdx, location); - __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); - __ j(not_equal, &assign, Label::kNear); - __ Push(var->name()); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, rcx); - __ movp(rdx, location); - __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); - __ j(equal, &uninitialized_this); - __ Push(var->name()); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK(var->IsStackAllocated() || var->IsContextSlot()); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, rcx); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ movp(rdx, location); - __ CompareRoot(rdx, Heap::kTheHoleValueRootIndex); - __ Check(equal, kLetBindingReInitialization); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2424,8 +2357,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { // Perform the assignment as if via '='. { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(rax); @@ -2437,8 +2370,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } else { // Perform the assignment as if via '='. - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(rax); diff --git a/src/full-codegen/x87/full-codegen-x87.cc b/src/full-codegen/x87/full-codegen-x87.cc index 39a0e6bec8..33829047f5 100644 --- a/src/full-codegen/x87/full-codegen-x87.cc +++ b/src/full-codegen/x87/full-codegen-x87.cc @@ -700,9 +700,9 @@ void FullCodeGenerator::VisitVariableDeclaration( VariableDeclaration* declaration) { VariableProxy* proxy = declaration->proxy(); Variable* variable = proxy->var(); + DCHECK(!variable->binding_needs_init()); switch (variable->location()) { case VariableLocation::UNALLOCATED: { - DCHECK(!variable->binding_needs_init()); globals_->Add(variable->name(), zone()); FeedbackVectorSlot slot = proxy->VariableFeedbackSlot(); DCHECK(!slot.IsInvalid()); @@ -712,22 +712,7 @@ void FullCodeGenerator::VisitVariableDeclaration( } case VariableLocation::PARAMETER: case VariableLocation::LOCAL: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - __ mov(StackOperand(variable), - Immediate(isolate()->factory()->the_hole_value())); - } - break; - case VariableLocation::CONTEXT: - if (variable->binding_needs_init()) { - Comment cmnt(masm_, "[ VariableDeclaration"); - EmitDebugCheckDeclarationContext(variable); - __ mov(ContextOperand(esi, variable->index()), - Immediate(isolate()->factory()->the_hole_value())); - // No write barrier since the hole value is in old space. - PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS); - } break; case VariableLocation::LOOKUP: @@ -1066,6 +1051,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, SetExpressionPosition(proxy); PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS); Variable* var = proxy->var(); + DCHECK(!var->binding_needs_init()); // Two cases: global variables and all other types of variables. switch (var->location()) { @@ -1082,20 +1068,6 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy, DCHECK_EQ(NOT_INSIDE_TYPEOF, typeof_mode); Comment cmnt(masm_, var->IsContextSlot() ? "[ Context variable" : "[ Stack variable"); - - if (proxy->hole_check_mode() == HoleCheckMode::kRequired) { - // Throw a reference error when using an uninitialized let/const - // binding in harmony mode. - Label done; - GetVar(eax, var); - __ cmp(eax, isolate()->factory()->the_hole_value()); - __ j(not_equal, &done, Label::kNear); - __ push(Immediate(var->name())); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&done); - context()->Plug(eax); - break; - } context()->Plug(var); break; } @@ -1411,8 +1383,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) { switch (assign_type) { case VARIABLE: { VariableProxy* proxy = expr->target()->AsVariableProxy(); - EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), expr->op(), expr->AssignmentSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(eax); break; @@ -1593,8 +1564,7 @@ void FullCodeGenerator::EmitAssignment(Expression* expr, case VARIABLE: { VariableProxy* proxy = expr->AsVariableProxy(); EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot, - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, slot); break; } case NAMED_PROPERTY: { @@ -1635,8 +1605,8 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot( } void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, - FeedbackVectorSlot slot, - HoleCheckMode hole_check_mode) { + FeedbackVectorSlot slot) { + DCHECK(!var->binding_needs_init()); if (var->IsUnallocated()) { // Global var, const, or let. __ mov(StoreDescriptor::ReceiverRegister(), NativeContextOperand()); @@ -1645,51 +1615,15 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op, Context::EXTENSION_INDEX)); CallStoreIC(slot, var->name()); - } else if (IsLexicalVariableMode(var->mode()) && op != Token::INIT) { - DCHECK(!var->IsLookupSlot()); - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - MemOperand location = VarOperand(var, ecx); - // Perform an initialization check for lexically declared variables. - if (hole_check_mode == HoleCheckMode::kRequired) { - Label assign; - __ mov(edx, location); - __ cmp(edx, isolate()->factory()->the_hole_value()); - __ j(not_equal, &assign, Label::kNear); - __ push(Immediate(var->name())); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&assign); - } - if (var->mode() != CONST) { - EmitStoreToStackLocalOrContextSlot(var, location); - } else if (var->throw_on_const_assignment(language_mode())) { + } else if (var->mode() == CONST && op != Token::INIT) { + if (var->throw_on_const_assignment(language_mode())) { __ CallRuntime(Runtime::kThrowConstAssignError); } - } else if (var->is_this() && var->mode() == CONST && op == Token::INIT) { - // Initializing assignment to const {this} needs a write barrier. - DCHECK(var->IsStackAllocated() || var->IsContextSlot()); - Label uninitialized_this; - MemOperand location = VarOperand(var, ecx); - __ mov(edx, location); - __ cmp(edx, isolate()->factory()->the_hole_value()); - __ j(equal, &uninitialized_this); - __ push(Immediate(var->name())); - __ CallRuntime(Runtime::kThrowReferenceError); - __ bind(&uninitialized_this); - EmitStoreToStackLocalOrContextSlot(var, location); - } else { - DCHECK(var->mode() != CONST || op == Token::INIT); + DCHECK(!var->is_this()); DCHECK(var->IsStackAllocated() || var->IsContextSlot()); DCHECK(!var->IsLookupSlot()); - // Assignment to var or initializing assignment to let/const in harmony - // mode. MemOperand location = VarOperand(var, ecx); - if (FLAG_debug_code && var->mode() == LET && op == Token::INIT) { - // Check for an uninitialized let binding. - __ mov(edx, location); - __ cmp(edx, isolate()->factory()->the_hole_value()); - __ Check(equal, kLetBindingReInitialization); - } EmitStoreToStackLocalOrContextSlot(var, location); } } @@ -2431,8 +2365,8 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { if (expr->is_postfix()) { // Perform the assignment as if via '='. { EffectContext context(this); - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, + expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context.Plug(eax); @@ -2444,8 +2378,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { } } else { // Perform the assignment as if via '='. - EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot(), - proxy->hole_check_mode()); + EmitVariableAssignment(proxy->var(), Token::ASSIGN, expr->CountSlot()); PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER); context()->Plug(eax);