Index: src/compiler/ast-graph-builder.cc |
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc |
index 9cfc8f77790dd09a3dcc121cc657cf1429c67b35..9b7eeac37ce8866d147740abaa9fd0a848573e96 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: |
@@ -2481,47 +2471,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. |
@@ -2532,19 +2487,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()); |
@@ -2555,15 +2500,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: |
@@ -2605,8 +2542,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. |
@@ -2617,93 +2553,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); |
} |
@@ -2820,18 +2696,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); |