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