| Index: src/compiler/ast-graph-builder.cc
|
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
|
| index 03640780b656186b653eb05aba656d5093553e76..01cde01515d0693054abe1b5e21d969cbd5021e0 100644
|
| --- a/src/compiler/ast-graph-builder.cc
|
| +++ b/src/compiler/ast-graph-builder.cc
|
| @@ -861,6 +861,7 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
|
| const Operator* op =
|
| javascript()->Runtime(Runtime::kMaterializeRegExpLiteral, 4);
|
| Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
|
| + PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
|
| ast_context()->ProduceValue(literal);
|
| }
|
|
|
| @@ -1095,14 +1096,16 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
| Unique<Name> name =
|
| MakeUnique(property->key()->AsLiteral()->AsPropertyName());
|
| old_value = NewNode(javascript()->LoadNamed(name), object);
|
| - PrepareFrameState(old_value, property->LoadId(), kPushOutput);
|
| + PrepareFrameState(old_value, property->LoadId(),
|
| + OutputFrameStateCombine::Push());
|
| break;
|
| }
|
| case KEYED_PROPERTY: {
|
| Node* key = environment()->Top();
|
| Node* object = environment()->Peek(1);
|
| old_value = NewNode(javascript()->LoadProperty(), object, key);
|
| - PrepareFrameState(old_value, property->LoadId(), kPushOutput);
|
| + PrepareFrameState(old_value, property->LoadId(),
|
| + OutputFrameStateCombine::Push());
|
| break;
|
| }
|
| }
|
| @@ -1111,7 +1114,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
| Node* right = environment()->Pop();
|
| Node* left = environment()->Pop();
|
| Node* value = BuildBinaryOp(left, right, expr->binary_op());
|
| - PrepareFrameState(value, expr->binary_operation()->id(), kPushOutput);
|
| + PrepareFrameState(value, expr->binary_operation()->id(),
|
| + OutputFrameStateCombine::Push());
|
| environment()->Push(value);
|
| } else {
|
| VisitForValue(expr->value());
|
| @@ -1164,6 +1168,7 @@ void AstGraphBuilder::VisitThrow(Throw* expr) {
|
| Node* exception = environment()->Pop();
|
| const Operator* op = javascript()->Runtime(Runtime::kThrow, 1);
|
| Node* value = NewNode(op, exception);
|
| + PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
| ast_context()->ProduceValue(value);
|
| }
|
|
|
| @@ -1212,6 +1217,9 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
| Node* pair = NewNode(op, current_context(), name);
|
| callee_value = NewNode(common()->Projection(0), pair);
|
| receiver_value = NewNode(common()->Projection(1), pair);
|
| +
|
| + PrepareFrameState(pair, expr->EvalOrLookupId(),
|
| + OutputFrameStateCombine::Push());
|
| break;
|
| }
|
| case Call::PROPERTY_CALL: {
|
| @@ -1227,7 +1235,8 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
| Node* key = environment()->Pop();
|
| callee_value = NewNode(javascript()->LoadProperty(), object, key);
|
| }
|
| - PrepareFrameState(callee_value, property->LoadId(), kPushOutput);
|
| + PrepareFrameState(callee_value, property->LoadId(),
|
| + OutputFrameStateCombine::Push());
|
| receiver_value = environment()->Pop();
|
| // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
|
| // object for sloppy callees. This could also be modeled explicitly here,
|
| @@ -1271,6 +1280,8 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
| const Operator* op =
|
| javascript()->Runtime(Runtime::kResolvePossiblyDirectEval, 5);
|
| Node* pair = NewNode(op, callee, source, receiver, strict, position);
|
| + PrepareFrameState(pair, expr->EvalOrLookupId(),
|
| + OutputFrameStateCombine::PokeAt(arg_count + 1));
|
| Node* new_callee = NewNode(common()->Projection(0), pair);
|
| Node* new_receiver = NewNode(common()->Projection(1), pair);
|
|
|
| @@ -1313,7 +1324,8 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
|
| Node* callee_value = NewNode(javascript()->LoadNamed(unique), receiver_value);
|
| // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
|
| // refuses to optimize functions with jsruntime calls).
|
| - PrepareFrameState(callee_value, BailoutId::None(), kPushOutput);
|
| + PrepareFrameState(callee_value, BailoutId::None(),
|
| + OutputFrameStateCombine::Push());
|
| environment()->Push(callee_value);
|
| environment()->Push(receiver_value);
|
|
|
| @@ -1395,7 +1407,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| Unique<Name> name =
|
| MakeUnique(property->key()->AsLiteral()->AsPropertyName());
|
| old_value = NewNode(javascript()->LoadNamed(name), object);
|
| - PrepareFrameState(old_value, property->LoadId(), kPushOutput);
|
| + PrepareFrameState(old_value, property->LoadId(),
|
| + OutputFrameStateCombine::Push());
|
| stack_depth = 1;
|
| break;
|
| }
|
| @@ -1405,7 +1418,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
| Node* key = environment()->Top();
|
| Node* object = environment()->Peek(1);
|
| old_value = NewNode(javascript()->LoadProperty(), object, key);
|
| - PrepareFrameState(old_value, property->LoadId(), kPushOutput);
|
| + PrepareFrameState(old_value, property->LoadId(),
|
| + OutputFrameStateCombine::Push());
|
| stack_depth = 2;
|
| break;
|
| }
|
| @@ -1583,7 +1597,8 @@ void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
|
| // deleting "this" is allowed in all language modes.
|
| Variable* variable = expr->expression()->AsVariableProxy()->var();
|
| DCHECK(strict_mode() == SLOPPY || variable->is_this());
|
| - value = BuildVariableDelete(variable);
|
| + value = BuildVariableDelete(variable, expr->id(),
|
| + ast_context()->GetStateCombine());
|
| } else if (expr->expression()->IsProperty()) {
|
| Property* property = expr->expression()->AsProperty();
|
| VisitForValue(property->obj());
|
| @@ -1591,6 +1606,7 @@ void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
|
| Node* key = environment()->Pop();
|
| Node* object = environment()->Pop();
|
| value = NewNode(javascript()->DeleteProperty(strict_mode()), object, key);
|
| + PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
| } else {
|
| VisitForEffect(expr->expression());
|
| value = jsgraph()->TrueConstant();
|
| @@ -1736,13 +1752,14 @@ Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
|
|
|
|
|
| Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
|
| - Node* not_hole) {
|
| + Node* not_hole,
|
| + BailoutId bailout_id) {
|
| IfBuilder hole_check(this);
|
| Node* the_hole = jsgraph()->TheHoleConstant();
|
| Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
|
| hole_check.If(check);
|
| hole_check.Then();
|
| - environment()->Push(BuildThrowReferenceError(variable));
|
| + environment()->Push(BuildThrowReferenceError(variable, bailout_id));
|
| hole_check.Else();
|
| environment()->Push(not_hole);
|
| hole_check.End();
|
| @@ -1762,7 +1779,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
| Unique<Name> name = MakeUnique(variable->name());
|
| const Operator* op = javascript()->LoadNamed(name, contextual_mode);
|
| Node* node = NewNode(op, global);
|
| - PrepareFrameState(node, bailout_id, kPushOutput);
|
| + PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push());
|
| return node;
|
| }
|
| case Variable::PARAMETER:
|
| @@ -1780,9 +1797,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
| } else if (mode == LET || mode == CONST) {
|
| // Perform check for uninitialized let/const variables.
|
| if (value->op() == the_hole->op()) {
|
| - value = BuildThrowReferenceError(variable);
|
| + value = BuildThrowReferenceError(variable, bailout_id);
|
| } else if (value->opcode() == IrOpcode::kPhi) {
|
| - value = BuildHoleCheckThrow(value, variable, value);
|
| + value = BuildHoleCheckThrow(value, variable, value, bailout_id);
|
| }
|
| }
|
| return value;
|
| @@ -1803,7 +1820,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
| value = BuildHoleCheckSilent(value, undefined, value);
|
| } else if (mode == LET || mode == CONST) {
|
| // Perform check for uninitialized let/const variables.
|
| - value = BuildHoleCheckThrow(value, variable, value);
|
| + value = BuildHoleCheckThrow(value, variable, value, bailout_id);
|
| }
|
| return value;
|
| }
|
| @@ -1816,6 +1833,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
| : Runtime::kLoadLookupSlotNoReferenceError;
|
| const Operator* op = javascript()->Runtime(function_id, 2);
|
| Node* pair = NewNode(op, current_context(), name);
|
| + PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1));
|
| return NewNode(common()->Projection(0), pair);
|
| }
|
| }
|
| @@ -1824,14 +1842,18 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
|
| }
|
|
|
|
|
| -Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
|
| +Node* AstGraphBuilder::BuildVariableDelete(
|
| + Variable* variable, BailoutId bailout_id,
|
| + OutputFrameStateCombine state_combine) {
|
| switch (variable->location()) {
|
| case Variable::UNALLOCATED: {
|
| // Global var, const, or let variable.
|
| Node* global = BuildLoadGlobalObject();
|
| Node* name = jsgraph()->Constant(variable->name());
|
| const Operator* op = javascript()->DeleteProperty(strict_mode());
|
| - return NewNode(op, global, name);
|
| + Node* result = NewNode(op, global, name);
|
| + PrepareFrameState(result, bailout_id, state_combine);
|
| + return result;
|
| }
|
| case Variable::PARAMETER:
|
| case Variable::LOCAL:
|
| @@ -1843,7 +1865,9 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
|
| // Dynamic lookup of context variable (anywhere in the chain).
|
| Node* name = jsgraph()->Constant(variable->name());
|
| const Operator* op = javascript()->Runtime(Runtime::kDeleteLookupSlot, 2);
|
| - return NewNode(op, current_context(), name);
|
| + Node* result = NewNode(op, current_context(), name);
|
| + PrepareFrameState(result, bailout_id, state_combine);
|
| + return result;
|
| }
|
| }
|
| UNREACHABLE();
|
| @@ -1885,9 +1909,9 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
|
| // temporal dead zone of a let declared variable.
|
| Node* current = environment()->Lookup(variable);
|
| if (current->op() == the_hole->op()) {
|
| - value = BuildThrowReferenceError(variable);
|
| + value = BuildThrowReferenceError(variable, bailout_id);
|
| } else if (value->opcode() == IrOpcode::kPhi) {
|
| - value = BuildHoleCheckThrow(current, variable, value);
|
| + value = BuildHoleCheckThrow(current, variable, value, bailout_id);
|
| }
|
| } else if (mode == CONST && op != Token::INIT_CONST) {
|
| // All assignments to const variables are early errors.
|
| @@ -1912,7 +1936,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
|
| const Operator* op =
|
| javascript()->LoadContext(depth, variable->index(), false);
|
| Node* current = NewNode(op, current_context());
|
| - value = BuildHoleCheckThrow(current, variable, value);
|
| + value = BuildHoleCheckThrow(current, variable, value, bailout_id);
|
| } else if (mode == CONST && op != Token::INIT_CONST) {
|
| // All assignments to const variables are early errors.
|
| UNREACHABLE();
|
| @@ -1927,7 +1951,9 @@ Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
|
| // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
|
| // initializations of const declarations.
|
| const Operator* op = javascript()->Runtime(Runtime::kStoreLookupSlot, 4);
|
| - return NewNode(op, value, current_context(), name, strict);
|
| + Node* store = NewNode(op, value, current_context(), name, strict);
|
| + PrepareFrameState(store, bailout_id);
|
| + return store;
|
| }
|
| }
|
| UNREACHABLE();
|
| @@ -1965,11 +1991,14 @@ Node* AstGraphBuilder::BuildToBoolean(Node* value) {
|
| }
|
|
|
|
|
| -Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) {
|
| +Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
|
| + BailoutId bailout_id) {
|
| // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
|
| Node* variable_name = jsgraph()->Constant(variable->name());
|
| const Operator* op = javascript()->Runtime(Runtime::kThrowReferenceError, 1);
|
| - return NewNode(op, variable_name);
|
| + Node* call = NewNode(op, variable_name);
|
| + PrepareFrameState(call, bailout_id);
|
| + return call;
|
| }
|
|
|
|
|
|
|