[turbofan] Implicitly emit eager checkpoint at graph building.
This makes preparation of eager checkpoints within the graph builder implicit. Every sub-expression visitation is now guaranteed to emit valid checkpoints in AstContext. R=jarin@chromium.org BUG=v8:5021 Review-Url: https://codereview.chromium.org/2074703002 Cr-Commit-Position: refs/heads/master@{#37368}
This commit is contained in:
parent
85c9f0018a
commit
74e328efee
@ -40,14 +40,14 @@ class AstGraphBuilder::AstContext BASE_EMBEDDED {
|
||||
|
||||
// Plug a node into this expression context. Call this function in tail
|
||||
// position in the Visit functions for expressions.
|
||||
virtual void ProduceValue(Node* value) = 0;
|
||||
virtual void ProduceValue(Expression* expr, Node* value) = 0;
|
||||
|
||||
// Unplugs a node from this expression context. Call this to retrieve the
|
||||
// result of another Visit function that already plugged the context.
|
||||
virtual Node* ConsumeValue() = 0;
|
||||
|
||||
// Shortcut for "context->ProduceValue(context->ConsumeValue())".
|
||||
void ReplaceValue() { ProduceValue(ConsumeValue()); }
|
||||
void ReplaceValue(Expression* expr) { ProduceValue(expr, ConsumeValue()); }
|
||||
|
||||
protected:
|
||||
AstContext(AstGraphBuilder* owner, Expression::Context kind);
|
||||
@ -75,7 +75,7 @@ class AstGraphBuilder::AstEffectContext final : public AstContext {
|
||||
explicit AstEffectContext(AstGraphBuilder* owner)
|
||||
: AstContext(owner, Expression::kEffect) {}
|
||||
~AstEffectContext() final;
|
||||
void ProduceValue(Node* value) final;
|
||||
void ProduceValue(Expression* expr, Node* value) final;
|
||||
Node* ConsumeValue() final;
|
||||
};
|
||||
|
||||
@ -86,7 +86,7 @@ class AstGraphBuilder::AstValueContext final : public AstContext {
|
||||
explicit AstValueContext(AstGraphBuilder* owner)
|
||||
: AstContext(owner, Expression::kValue) {}
|
||||
~AstValueContext() final;
|
||||
void ProduceValue(Node* value) final;
|
||||
void ProduceValue(Expression* expr, Node* value) final;
|
||||
Node* ConsumeValue() final;
|
||||
};
|
||||
|
||||
@ -97,7 +97,7 @@ class AstGraphBuilder::AstTestContext final : public AstContext {
|
||||
AstTestContext(AstGraphBuilder* owner, TypeFeedbackId feedback_id)
|
||||
: AstContext(owner, Expression::kTest), feedback_id_(feedback_id) {}
|
||||
~AstTestContext() final;
|
||||
void ProduceValue(Node* value) final;
|
||||
void ProduceValue(Expression* expr, Node* value) final;
|
||||
Node* ConsumeValue() final;
|
||||
|
||||
private:
|
||||
@ -968,19 +968,22 @@ AstGraphBuilder::AstTestContext::~AstTestContext() {
|
||||
DCHECK(environment()->stack_height() == original_height_ + 1);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
|
||||
void AstGraphBuilder::AstEffectContext::ProduceValue(Expression* expr,
|
||||
Node* value) {
|
||||
// The value is ignored.
|
||||
owner()->PrepareEagerCheckpoint(expr->id());
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
|
||||
void AstGraphBuilder::AstValueContext::ProduceValue(Expression* expr,
|
||||
Node* value) {
|
||||
environment()->Push(value);
|
||||
owner()->PrepareEagerCheckpoint(expr->id());
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
|
||||
void AstGraphBuilder::AstTestContext::ProduceValue(Expression* expr,
|
||||
Node* value) {
|
||||
environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
|
||||
owner()->PrepareEagerCheckpoint(expr->id());
|
||||
}
|
||||
|
||||
|
||||
@ -1071,7 +1074,7 @@ void AstGraphBuilder::VisitForValue(Expression* expr) {
|
||||
if (!CheckStackOverflow()) {
|
||||
expr->Accept(this);
|
||||
} else {
|
||||
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
|
||||
ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1081,7 +1084,7 @@ void AstGraphBuilder::VisitForEffect(Expression* expr) {
|
||||
if (!CheckStackOverflow()) {
|
||||
expr->Accept(this);
|
||||
} else {
|
||||
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
|
||||
ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1091,7 +1094,7 @@ void AstGraphBuilder::VisitForTest(Expression* expr) {
|
||||
if (!CheckStackOverflow()) {
|
||||
expr->Accept(this);
|
||||
} else {
|
||||
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
|
||||
ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1101,7 +1104,7 @@ void AstGraphBuilder::Visit(Expression* expr) {
|
||||
if (!CheckStackOverflow()) {
|
||||
expr->Accept(this);
|
||||
} else {
|
||||
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
|
||||
ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1433,10 +1436,13 @@ void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
|
||||
test_value.Then();
|
||||
test_value.Else();
|
||||
{
|
||||
environment()->Push(value);
|
||||
PrepareEagerCheckpoint(stmt->FilterId());
|
||||
value = environment()->Pop();
|
||||
// Bind value and do loop body.
|
||||
VectorSlotPair feedback =
|
||||
CreateVectorSlotPair(stmt->EachFeedbackSlot());
|
||||
VisitForInAssignment(stmt->each(), value, feedback, stmt->FilterId(),
|
||||
VisitForInAssignment(stmt->each(), value, feedback,
|
||||
stmt->AssignmentId());
|
||||
VisitIterationBody(stmt, &for_loop);
|
||||
}
|
||||
@ -1584,7 +1590,7 @@ void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
|
||||
PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
|
||||
const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
|
||||
Node* value = NewNode(op);
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -1699,7 +1705,7 @@ void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
|
||||
BuildVariableAssignment(var, literal, Token::INIT, feedback,
|
||||
BailoutId::None());
|
||||
}
|
||||
ast_context()->ProduceValue(literal);
|
||||
ast_context()->ProduceValue(expr, literal);
|
||||
}
|
||||
|
||||
|
||||
@ -1711,7 +1717,7 @@ void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
|
||||
void AstGraphBuilder::VisitDoExpression(DoExpression* expr) {
|
||||
VisitBlock(expr->block());
|
||||
VisitVariableProxy(expr->result());
|
||||
ast_context()->ReplaceValue();
|
||||
ast_context()->ReplaceValue(expr);
|
||||
}
|
||||
|
||||
|
||||
@ -1725,7 +1731,11 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) {
|
||||
compare_if.Else();
|
||||
Visit(expr->else_expression());
|
||||
compare_if.End();
|
||||
ast_context()->ReplaceValue();
|
||||
// Skip plugging AST evaluation contexts of the test kind. This is to stay in
|
||||
// sync with full codegen which doesn't prepare the proper bailout point (see
|
||||
// the implementation of FullCodeGenerator::VisitForControl).
|
||||
if (ast_context()->IsTest()) return;
|
||||
ast_context()->ReplaceValue(expr);
|
||||
}
|
||||
|
||||
|
||||
@ -1734,13 +1744,13 @@ void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
|
||||
PrepareEagerCheckpoint(BeforeId(expr));
|
||||
Node* value = BuildVariableLoad(expr->var(), expr->id(), pair,
|
||||
ast_context()->GetStateCombine());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitLiteral(Literal* expr) {
|
||||
Node* value = jsgraph()->Constant(expr->value());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -1752,7 +1762,7 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
|
||||
expr->pattern(), expr->flags(), expr->literal_index());
|
||||
Node* literal = NewNode(op, closure);
|
||||
PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
|
||||
ast_context()->ProduceValue(literal);
|
||||
ast_context()->ProduceValue(expr, literal);
|
||||
}
|
||||
|
||||
|
||||
@ -1792,7 +1802,6 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
if (key->value()->IsInternalizedString()) {
|
||||
if (property->emit_store()) {
|
||||
VisitForValue(property->value());
|
||||
PrepareEagerCheckpoint(property->value()->id());
|
||||
Node* value = environment()->Pop();
|
||||
Node* literal = environment()->Top();
|
||||
Handle<Name> name = key->AsPropertyName();
|
||||
@ -1938,7 +1947,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
|
||||
}
|
||||
}
|
||||
|
||||
ast_context()->ProduceValue(environment()->Pop());
|
||||
ast_context()->ProduceValue(expr, environment()->Pop());
|
||||
}
|
||||
|
||||
|
||||
@ -1977,16 +1986,13 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
|
||||
|
||||
VisitForValue(subexpr);
|
||||
{
|
||||
PrepareEagerCheckpoint(subexpr->id());
|
||||
VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
|
||||
Node* value = environment()->Pop();
|
||||
Node* index = jsgraph()->Constant(array_index);
|
||||
Node* literal = environment()->Top();
|
||||
Node* store = BuildKeyedStore(literal, index, value, pair);
|
||||
PrepareFrameState(store, expr->GetIdForElement(array_index),
|
||||
OutputFrameStateCombine::Ignore());
|
||||
}
|
||||
VectorSlotPair pair = CreateVectorSlotPair(expr->LiteralFeedbackSlot());
|
||||
Node* value = environment()->Pop();
|
||||
Node* index = jsgraph()->Constant(array_index);
|
||||
Node* literal = environment()->Top();
|
||||
Node* store = BuildKeyedStore(literal, index, value, pair);
|
||||
PrepareFrameState(store, expr->GetIdForElement(array_index),
|
||||
OutputFrameStateCombine::Ignore());
|
||||
}
|
||||
|
||||
// In case the array literal contains spread expressions it has two parts. The
|
||||
@ -2009,14 +2015,12 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
|
||||
}
|
||||
}
|
||||
|
||||
ast_context()->ProduceValue(environment()->Pop());
|
||||
ast_context()->ProduceValue(expr, environment()->Pop());
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
||||
const VectorSlotPair& feedback,
|
||||
BailoutId bailout_id_before,
|
||||
BailoutId bailout_id_after) {
|
||||
BailoutId bailout_id) {
|
||||
DCHECK(expr->IsValidReferenceExpressionOrThis());
|
||||
|
||||
// Left-hand side can only be a property, a global or a variable slot.
|
||||
@ -2027,50 +2031,40 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
||||
switch (assign_type) {
|
||||
case VARIABLE: {
|
||||
Variable* var = expr->AsVariableProxy()->var();
|
||||
environment()->Push(value);
|
||||
PrepareEagerCheckpoint(bailout_id_before);
|
||||
value = environment()->Pop();
|
||||
BuildVariableAssignment(var, value, Token::ASSIGN, feedback,
|
||||
bailout_id_after);
|
||||
BuildVariableAssignment(var, value, Token::ASSIGN, feedback, bailout_id);
|
||||
break;
|
||||
}
|
||||
case NAMED_PROPERTY: {
|
||||
environment()->Push(value);
|
||||
VisitForValue(property->obj());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
Node* object = environment()->Pop();
|
||||
value = environment()->Pop();
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
Node* store = BuildNamedStore(object, name, value, feedback);
|
||||
PrepareFrameState(store, bailout_id_after,
|
||||
OutputFrameStateCombine::Ignore());
|
||||
PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
|
||||
break;
|
||||
}
|
||||
case KEYED_PROPERTY: {
|
||||
environment()->Push(value);
|
||||
VisitForValue(property->obj());
|
||||
VisitForValue(property->key());
|
||||
PrepareEagerCheckpoint(property->key()->id());
|
||||
Node* key = environment()->Pop();
|
||||
Node* object = environment()->Pop();
|
||||
value = environment()->Pop();
|
||||
Node* store = BuildKeyedStore(object, key, value, feedback);
|
||||
PrepareFrameState(store, bailout_id_after,
|
||||
OutputFrameStateCombine::Ignore());
|
||||
PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
|
||||
break;
|
||||
}
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
environment()->Push(value);
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
Node* home_object = environment()->Pop();
|
||||
Node* receiver = environment()->Pop();
|
||||
value = environment()->Pop();
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
Node* store = BuildNamedSuperStore(receiver, home_object, name, value);
|
||||
PrepareFrameState(store, bailout_id_after,
|
||||
OutputFrameStateCombine::Ignore());
|
||||
PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
|
||||
break;
|
||||
}
|
||||
case KEYED_SUPER_PROPERTY: {
|
||||
@ -2078,14 +2072,12 @@ void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
|
||||
VisitForValue(property->key());
|
||||
PrepareEagerCheckpoint(property->key()->id());
|
||||
Node* key = environment()->Pop();
|
||||
Node* home_object = environment()->Pop();
|
||||
Node* receiver = environment()->Pop();
|
||||
value = environment()->Pop();
|
||||
Node* store = BuildKeyedSuperStore(receiver, home_object, key, value);
|
||||
PrepareFrameState(store, bailout_id_after,
|
||||
OutputFrameStateCombine::Ignore());
|
||||
PrepareFrameState(store, bailout_id, OutputFrameStateCombine::Ignore());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2129,7 +2121,6 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
break;
|
||||
}
|
||||
|
||||
BailoutId before_store_id = BailoutId::None();
|
||||
// Evaluate the value and potentially handle compound assignments by loading
|
||||
// the left-hand side value and performing a binary operation.
|
||||
if (expr->is_compound()) {
|
||||
@ -2149,7 +2140,6 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
VectorSlotPair pair =
|
||||
CreateVectorSlotPair(property->PropertyFeedbackSlot());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
old_value = BuildNamedLoad(object, name, pair);
|
||||
PrepareFrameState(old_value, property->LoadId(),
|
||||
OutputFrameStateCombine::Push());
|
||||
@ -2160,7 +2150,6 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
Node* object = environment()->Peek(1);
|
||||
VectorSlotPair pair =
|
||||
CreateVectorSlotPair(property->PropertyFeedbackSlot());
|
||||
PrepareEagerCheckpoint(property->key()->id());
|
||||
old_value = BuildKeyedLoad(object, key, pair);
|
||||
PrepareFrameState(old_value, property->LoadId(),
|
||||
OutputFrameStateCombine::Push());
|
||||
@ -2172,7 +2161,6 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
VectorSlotPair pair =
|
||||
CreateVectorSlotPair(property->PropertyFeedbackSlot());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
|
||||
PrepareFrameState(old_value, property->LoadId(),
|
||||
OutputFrameStateCombine::Push());
|
||||
@ -2184,7 +2172,6 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
Node* receiver = environment()->Peek(2);
|
||||
VectorSlotPair pair =
|
||||
CreateVectorSlotPair(property->PropertyFeedbackSlot());
|
||||
PrepareEagerCheckpoint(property->key()->id());
|
||||
old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
|
||||
PrepareFrameState(old_value, property->LoadId(),
|
||||
OutputFrameStateCombine::Push());
|
||||
@ -2206,17 +2193,13 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
environment()->Push(value);
|
||||
if (needs_frame_state_before) {
|
||||
before_store_id = expr->binary_operation()->id();
|
||||
PrepareEagerCheckpoint(expr->binary_operation()->id());
|
||||
}
|
||||
} else {
|
||||
VisitForValue(expr->value());
|
||||
if (needs_frame_state_before) {
|
||||
before_store_id = expr->value()->id();
|
||||
}
|
||||
}
|
||||
|
||||
// Store the value.
|
||||
PrepareEagerCheckpoint(before_store_id);
|
||||
Node* value = environment()->Pop();
|
||||
VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
|
||||
switch (assign_type) {
|
||||
@ -2258,14 +2241,14 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
|
||||
}
|
||||
}
|
||||
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitYield(Yield* expr) {
|
||||
// Generator functions are supported only by going through Ignition first.
|
||||
SetStackOverflow();
|
||||
ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
|
||||
ast_context()->ProduceValue(expr, jsgraph()->UndefinedConstant());
|
||||
}
|
||||
|
||||
|
||||
@ -2273,7 +2256,7 @@ void AstGraphBuilder::VisitThrow(Throw* expr) {
|
||||
VisitForValue(expr->exception());
|
||||
Node* exception = environment()->Pop();
|
||||
Node* value = BuildThrowError(exception, expr->id());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2287,7 +2270,6 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
||||
break;
|
||||
case NAMED_PROPERTY: {
|
||||
VisitForValue(expr->obj());
|
||||
PrepareEagerCheckpoint(expr->obj()->id());
|
||||
Node* object = environment()->Pop();
|
||||
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
|
||||
value = BuildNamedLoad(object, name, pair);
|
||||
@ -2297,7 +2279,6 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
||||
case KEYED_PROPERTY: {
|
||||
VisitForValue(expr->obj());
|
||||
VisitForValue(expr->key());
|
||||
PrepareEagerCheckpoint(expr->key()->id());
|
||||
Node* key = environment()->Pop();
|
||||
Node* object = environment()->Pop();
|
||||
value = BuildKeyedLoad(object, key, pair);
|
||||
@ -2307,7 +2288,6 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
|
||||
PrepareEagerCheckpoint(expr->obj()->id());
|
||||
Node* home_object = environment()->Pop();
|
||||
Node* receiver = environment()->Pop();
|
||||
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
|
||||
@ -2319,7 +2299,6 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
||||
VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
|
||||
VisitForValue(expr->key());
|
||||
PrepareEagerCheckpoint(expr->key()->id());
|
||||
Node* key = environment()->Pop();
|
||||
Node* home_object = environment()->Pop();
|
||||
Node* receiver = environment()->Pop();
|
||||
@ -2328,7 +2307,7 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2371,7 +2350,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
VectorSlotPair feedback =
|
||||
CreateVectorSlotPair(property->PropertyFeedbackSlot());
|
||||
VisitForValue(property->obj());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
Node* object = environment()->Top();
|
||||
callee_value = BuildNamedLoad(object, name, feedback);
|
||||
@ -2390,7 +2368,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
CreateVectorSlotPair(property->PropertyFeedbackSlot());
|
||||
VisitForValue(property->obj());
|
||||
VisitForValue(property->key());
|
||||
PrepareEagerCheckpoint(property->key()->id());
|
||||
Node* key = environment()->Pop();
|
||||
Node* object = environment()->Top();
|
||||
callee_value = BuildKeyedLoad(object, key, feedback);
|
||||
@ -2412,7 +2389,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
Node* home = environment()->Peek(1);
|
||||
Node* object = environment()->Top();
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
callee_value = BuildNamedSuperLoad(object, home, name, VectorSlotPair());
|
||||
PrepareFrameState(callee_value, property->LoadId(),
|
||||
OutputFrameStateCombine::Push());
|
||||
@ -2435,7 +2411,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
Node* key = environment()->Pop();
|
||||
Node* home = environment()->Pop();
|
||||
Node* object = environment()->Pop();
|
||||
PrepareEagerCheckpoint(property->key()->id());
|
||||
callee_value = BuildKeyedSuperLoad(object, home, key, VectorSlotPair());
|
||||
PrepareFrameState(callee_value, property->LoadId(),
|
||||
OutputFrameStateCombine::Push());
|
||||
@ -2511,12 +2486,12 @@ void AstGraphBuilder::VisitCall(Call* expr) {
|
||||
VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
|
||||
const Operator* call = javascript()->CallFunction(
|
||||
args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
|
||||
PrepareEagerCheckpoint(expr->CallId());
|
||||
PrepareEagerCheckpoint(possibly_eval ? expr->EvalId() : expr->CallId());
|
||||
Node* value = ProcessArguments(call, args->length() + 2);
|
||||
environment()->Push(value->InputAt(0)); // The callee passed to the call.
|
||||
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
|
||||
environment()->Drop(1);
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2542,10 +2517,9 @@ void AstGraphBuilder::VisitCallSuper(Call* expr) {
|
||||
// Create node to perform the super call.
|
||||
const Operator* call =
|
||||
javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
|
||||
PrepareEagerCheckpoint(super->new_target_var()->id());
|
||||
Node* value = ProcessArguments(call, args->length() + 2);
|
||||
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2556,11 +2530,6 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
|
||||
ZoneList<Expression*>* args = expr->arguments();
|
||||
VisitForValues(args);
|
||||
|
||||
// The baseline compiler doesn't push the new.target, so we need to record
|
||||
// the frame state before the push.
|
||||
PrepareEagerCheckpoint(args->is_empty() ? expr->expression()->id()
|
||||
: args->last()->id());
|
||||
|
||||
// The new target is the same as the callee.
|
||||
environment()->Push(environment()->Peek(args->length()));
|
||||
|
||||
@ -2570,7 +2539,7 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
|
||||
javascript()->CallConstruct(args->length() + 2, feedback);
|
||||
Node* value = ProcessArguments(call, args->length() + 2);
|
||||
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2592,7 +2561,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
|
||||
PrepareEagerCheckpoint(expr->CallId());
|
||||
Node* value = ProcessArguments(call, args->length() + 2);
|
||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2610,10 +2579,13 @@ void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
|
||||
// Create node to perform the runtime call.
|
||||
Runtime::FunctionId functionId = expr->function()->function_id;
|
||||
const Operator* call = javascript()->CallRuntime(functionId, args->length());
|
||||
PrepareEagerCheckpoint(expr->CallId());
|
||||
if (expr->function()->intrinsic_type == Runtime::IntrinsicType::RUNTIME ||
|
||||
expr->function()->function_id == Runtime::kInlineCall) {
|
||||
PrepareEagerCheckpoint(expr->CallId());
|
||||
}
|
||||
Node* value = ProcessArguments(call, args->length());
|
||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2661,7 +2633,6 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
}
|
||||
case NAMED_PROPERTY: {
|
||||
VisitForValue(property->obj());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
Node* object = environment()->Top();
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
VectorSlotPair pair =
|
||||
@ -2675,7 +2646,6 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
case KEYED_PROPERTY: {
|
||||
VisitForValue(property->obj());
|
||||
VisitForValue(property->key());
|
||||
PrepareEagerCheckpoint(property->key()->id());
|
||||
Node* key = environment()->Top();
|
||||
Node* object = environment()->Peek(1);
|
||||
VectorSlotPair pair =
|
||||
@ -2689,7 +2659,6 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
case NAMED_SUPER_PROPERTY: {
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
Node* home_object = environment()->Top();
|
||||
Node* receiver = environment()->Peek(1);
|
||||
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
|
||||
@ -2705,7 +2674,6 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
|
||||
VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
|
||||
VisitForValue(property->key());
|
||||
PrepareEagerCheckpoint(property->obj()->id());
|
||||
Node* key = environment()->Top();
|
||||
Node* home_object = environment()->Peek(1);
|
||||
Node* receiver = environment()->Peek(2);
|
||||
@ -2804,7 +2772,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
|
||||
// Restore old value for postfix expressions.
|
||||
if (is_postfix) value = environment()->Pop();
|
||||
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2824,7 +2792,7 @@ void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
|
||||
Node* value = BuildBinaryOp(left, right, expr->op(),
|
||||
expr->BinaryOperationFeedbackId());
|
||||
states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2844,23 +2812,21 @@ void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
|
||||
UNREACHABLE();
|
||||
}
|
||||
VisitForValue(sub_expr);
|
||||
PrepareEagerCheckpoint(sub_expr->id());
|
||||
Node* value_to_compare = environment()->Pop();
|
||||
Node* value = NewNode(op, value_to_compare, nil_value);
|
||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
||||
return ast_context()->ProduceValue(value);
|
||||
return ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
|
||||
Expression* sub_expr,
|
||||
Handle<String> check) {
|
||||
VisitTypeofExpression(sub_expr);
|
||||
PrepareEagerCheckpoint(sub_expr->id());
|
||||
Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
|
||||
Node* value = NewNode(javascript()->StrictEqual(CompareOperationHints::Any()),
|
||||
typeof_arg, jsgraph()->Constant(check));
|
||||
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
|
||||
return ast_context()->ProduceValue(value);
|
||||
return ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
||||
@ -2930,7 +2896,7 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
|
||||
Node* left = environment()->Pop();
|
||||
Node* value = NewNode(op, left, right);
|
||||
states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -2948,14 +2914,14 @@ void AstGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
|
||||
|
||||
void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
|
||||
Node* value = GetFunctionClosure();
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitSuperPropertyReference(
|
||||
SuperPropertyReference* expr) {
|
||||
Node* value = BuildThrowUnsupportedSuperError(expr->id());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
@ -3036,14 +3002,14 @@ void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
|
||||
VisitForEffect(expr->expression());
|
||||
value = jsgraph()->TrueConstant();
|
||||
}
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
|
||||
VisitForEffect(expr->expression());
|
||||
Node* value = jsgraph()->UndefinedConstant();
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
|
||||
@ -3065,33 +3031,46 @@ void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
|
||||
void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
|
||||
VisitTypeofExpression(expr->expression());
|
||||
Node* value = NewNode(javascript()->TypeOf(), environment()->Pop());
|
||||
ast_context()->ProduceValue(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
|
||||
VisitForValue(expr->expression());
|
||||
Node* operand = environment()->Pop();
|
||||
Node* input = BuildToBoolean(operand, expr->expression()->test_id());
|
||||
VisitForTest(expr->expression());
|
||||
Node* input = environment()->Pop();
|
||||
Node* value = NewNode(common()->Select(MachineRepresentation::kTagged), input,
|
||||
jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
|
||||
ast_context()->ProduceValue(value);
|
||||
// Skip plugging AST evaluation contexts of the test kind. This is to stay in
|
||||
// sync with full codegen which doesn't prepare the proper bailout point (see
|
||||
// the implementation of FullCodeGenerator::VisitForControl).
|
||||
if (ast_context()->IsTest()) return environment()->Push(value);
|
||||
ast_context()->ProduceValue(expr, value);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
|
||||
VisitForEffect(expr->left());
|
||||
Visit(expr->right());
|
||||
ast_context()->ReplaceValue();
|
||||
ast_context()->ReplaceValue(expr);
|
||||
}
|
||||
|
||||
|
||||
void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
|
||||
bool is_logical_and = expr->op() == Token::AND;
|
||||
IfBuilder compare_if(this);
|
||||
VisitForValue(expr->left());
|
||||
Node* condition = environment()->Top();
|
||||
compare_if.If(BuildToBoolean(condition, expr->left()->test_id()));
|
||||
// Only use an AST evaluation context of the value kind when this expression
|
||||
// is evaluated as value as well. Otherwise stick to a test context which is
|
||||
// in sync with full codegen (see FullCodeGenerator::VisitLogicalExpression).
|
||||
Node* condition = nullptr;
|
||||
if (ast_context()->IsValue()) {
|
||||
VisitForValue(expr->left());
|
||||
Node* left = environment()->Top();
|
||||
condition = BuildToBoolean(left, expr->left()->test_id());
|
||||
} else {
|
||||
VisitForTest(expr->left());
|
||||
condition = environment()->Top();
|
||||
}
|
||||
compare_if.If(condition);
|
||||
compare_if.Then();
|
||||
if (is_logical_and) {
|
||||
environment()->Pop();
|
||||
@ -3111,7 +3090,11 @@ void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
|
||||
environment()->Poke(0, jsgraph()->FalseConstant());
|
||||
}
|
||||
compare_if.End();
|
||||
ast_context()->ReplaceValue();
|
||||
// Skip plugging AST evaluation contexts of the test kind. This is to stay in
|
||||
// sync with full codegen which doesn't prepare the proper bailout point (see
|
||||
// the implementation of FullCodeGenerator::VisitForControl).
|
||||
if (ast_context()->IsTest()) return;
|
||||
ast_context()->ReplaceValue(expr);
|
||||
}
|
||||
|
||||
|
||||
@ -4072,6 +4055,7 @@ void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) {
|
||||
return;
|
||||
}
|
||||
if (ast_id != BailoutId::None()) {
|
||||
DCHECK(info()->shared_info()->VerifyBailoutId(ast_id));
|
||||
Node* node = NewNode(common()->Checkpoint());
|
||||
DCHECK_EQ(IrOpcode::kDead,
|
||||
NodeProperties::GetFrameStateInput(node, 0)->opcode());
|
||||
|
@ -445,8 +445,7 @@ class AstGraphBuilder : public AstVisitor {
|
||||
// Dispatched from VisitForInStatement.
|
||||
void VisitForInAssignment(Expression* expr, Node* value,
|
||||
const VectorSlotPair& feedback,
|
||||
BailoutId bailout_id_before,
|
||||
BailoutId bailout_id_after);
|
||||
BailoutId bailout_id);
|
||||
|
||||
// Dispatched from VisitObjectLiteral.
|
||||
void VisitObjectLiteralAccessor(Node* home_object,
|
||||
|
@ -30,14 +30,39 @@ bool IsRedundantCheckpoint(Node* node) {
|
||||
|
||||
} // namespace
|
||||
|
||||
Reduction CheckpointElimination::Reduce(Node* node) {
|
||||
if (node->opcode() != IrOpcode::kCheckpoint) return NoChange();
|
||||
Reduction CheckpointElimination::ReduceCheckpoint(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kCheckpoint, node->opcode());
|
||||
if (IsRedundantCheckpoint(node)) {
|
||||
return Replace(NodeProperties::GetEffectInput(node));
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction CheckpointElimination::ReduceReturn(Node* node) {
|
||||
DCHECK_EQ(IrOpcode::kReturn, node->opcode());
|
||||
Node* effect = NodeProperties::GetEffectInput(node);
|
||||
if (effect->opcode() == IrOpcode::kCheckpoint && effect->OwnedBy(node)) {
|
||||
// Any checkpoint that is wholly owned by a {Return} node can never be used
|
||||
// for an actual bailout and can hence be cut out of the effect chain.
|
||||
Node* replacement = NodeProperties::GetEffectInput(effect);
|
||||
NodeProperties::ReplaceEffectInput(node, replacement);
|
||||
return Changed(node);
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
Reduction CheckpointElimination::Reduce(Node* node) {
|
||||
switch (node->opcode()) {
|
||||
case IrOpcode::kCheckpoint:
|
||||
return ReduceCheckpoint(node);
|
||||
case IrOpcode::kReturn:
|
||||
return ReduceReturn(node);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NoChange();
|
||||
}
|
||||
|
||||
} // namespace compiler
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -18,6 +18,10 @@ class CheckpointElimination final : public AdvancedReducer {
|
||||
~CheckpointElimination() final {}
|
||||
|
||||
Reduction Reduce(Node* node) final;
|
||||
|
||||
private:
|
||||
Reduction ReduceCheckpoint(Node* node);
|
||||
Reduction ReduceReturn(Node* node);
|
||||
};
|
||||
|
||||
} // namespace compiler
|
||||
|
@ -875,7 +875,7 @@ void FullCodeGenerator::VisitDoExpression(DoExpression* expr) {
|
||||
Comment cmnt(masm_, "[ Do Expression");
|
||||
SetExpressionPosition(expr);
|
||||
VisitBlock(expr->block());
|
||||
EmitVariableLoad(expr->result());
|
||||
VisitInDuplicateContext(expr->result());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user