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