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