| Index: src/compiler/ast-graph-builder.cc
|
| diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
|
| index 3a9fcd9d83447d60e13359652f62fdbf40228f4c..87b0b2ddab3337879e2772be12a6605872b76168 100644
|
| --- a/src/compiler/ast-graph-builder.cc
|
| +++ b/src/compiler/ast-graph-builder.cc
|
| @@ -21,6 +21,115 @@ namespace internal {
|
| namespace compiler {
|
|
|
|
|
| +// Each expression in the AST is evaluated in a specific context. This context
|
| +// decides how the evaluation result is passed up the visitor.
|
| +class AstGraphBuilder::AstContext BASE_EMBEDDED {
|
| + public:
|
| + bool IsEffect() const { return kind_ == Expression::kEffect; }
|
| + bool IsValue() const { return kind_ == Expression::kValue; }
|
| + bool IsTest() const { return kind_ == Expression::kTest; }
|
| +
|
| + // Determines how to combine the frame state with the value
|
| + // that is about to be plugged into this AstContext.
|
| + OutputFrameStateCombine GetStateCombine() {
|
| + return IsEffect() ? OutputFrameStateCombine::Ignore()
|
| + : OutputFrameStateCombine::Push();
|
| + }
|
| +
|
| + // 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;
|
| +
|
| + // 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()); }
|
| +
|
| + protected:
|
| + AstContext(AstGraphBuilder* owner, Expression::Context kind);
|
| + virtual ~AstContext();
|
| +
|
| + AstGraphBuilder* owner() const { return owner_; }
|
| + Environment* environment() const { return owner_->environment(); }
|
| +
|
| +// We want to be able to assert, in a context-specific way, that the stack
|
| +// height makes sense when the context is filled.
|
| +#ifdef DEBUG
|
| + int original_height_;
|
| +#endif
|
| +
|
| + private:
|
| + Expression::Context kind_;
|
| + AstGraphBuilder* owner_;
|
| + AstContext* outer_;
|
| +};
|
| +
|
| +
|
| +// Context to evaluate expression for its side effects only.
|
| +class AstGraphBuilder::AstEffectContext FINAL : public AstContext {
|
| + public:
|
| + explicit AstEffectContext(AstGraphBuilder* owner)
|
| + : AstContext(owner, Expression::kEffect) {}
|
| + ~AstEffectContext() FINAL;
|
| + void ProduceValue(Node* value) FINAL;
|
| + Node* ConsumeValue() FINAL;
|
| +};
|
| +
|
| +
|
| +// Context to evaluate expression for its value (and side effects).
|
| +class AstGraphBuilder::AstValueContext FINAL : public AstContext {
|
| + public:
|
| + explicit AstValueContext(AstGraphBuilder* owner)
|
| + : AstContext(owner, Expression::kValue) {}
|
| + ~AstValueContext() FINAL;
|
| + void ProduceValue(Node* value) FINAL;
|
| + Node* ConsumeValue() FINAL;
|
| +};
|
| +
|
| +
|
| +// Context to evaluate expression for a condition value (and side effects).
|
| +class AstGraphBuilder::AstTestContext FINAL : public AstContext {
|
| + public:
|
| + explicit AstTestContext(AstGraphBuilder* owner)
|
| + : AstContext(owner, Expression::kTest) {}
|
| + ~AstTestContext() FINAL;
|
| + void ProduceValue(Node* value) FINAL;
|
| + Node* ConsumeValue() FINAL;
|
| +};
|
| +
|
| +
|
| +// Scoped class tracking context objects created by the visitor. Represents
|
| +// mutations of the context chain within the function body and allows to
|
| +// change the current {scope} and {context} during visitation.
|
| +class AstGraphBuilder::ContextScope BASE_EMBEDDED {
|
| + public:
|
| + ContextScope(AstGraphBuilder* owner, Scope* scope, Node* context)
|
| + : owner_(owner),
|
| + next_(owner->execution_context()),
|
| + outer_(owner->current_context()),
|
| + scope_(scope) {
|
| + owner_->set_execution_context(this); // Push.
|
| + owner_->set_current_context(context);
|
| + }
|
| +
|
| + ~ContextScope() {
|
| + owner_->set_execution_context(next_); // Pop.
|
| + owner_->set_current_context(outer_);
|
| + }
|
| +
|
| + // Current scope during visitation.
|
| + Scope* scope() const { return scope_; }
|
| +
|
| + private:
|
| + AstGraphBuilder* owner_;
|
| + ContextScope* next_;
|
| + Node* outer_;
|
| + Scope* scope_;
|
| +};
|
| +
|
| +
|
| // Scoped class tracking control statements entered by the visitor. There are
|
| // different types of statements participating in this stack to properly track
|
| // local as well as non-local control flow:
|
| @@ -541,6 +650,11 @@ Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
|
| }
|
|
|
|
|
| +Scope* AstGraphBuilder::current_scope() const {
|
| + return execution_context_->scope();
|
| +}
|
| +
|
| +
|
| void AstGraphBuilder::ControlScope::PerformCommand(Command command,
|
| Statement* target,
|
| Node* value) {
|
|
|