aboutsummaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/ast-graph-builder.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/ast-graph-builder.h')
-rw-r--r--deps/v8/src/compiler/ast-graph-builder.h437
1 files changed, 231 insertions, 206 deletions
diff --git a/deps/v8/src/compiler/ast-graph-builder.h b/deps/v8/src/compiler/ast-graph-builder.h
index 0337c813b9..ebeb6c613c 100644
--- a/deps/v8/src/compiler/ast-graph-builder.h
+++ b/deps/v8/src/compiler/ast-graph-builder.h
@@ -5,63 +5,191 @@
#ifndef V8_COMPILER_AST_GRAPH_BUILDER_H_
#define V8_COMPILER_AST_GRAPH_BUILDER_H_
-#include "src/v8.h"
-
#include "src/ast.h"
-#include "src/compiler/graph-builder.h"
#include "src/compiler/js-graph.h"
namespace v8 {
namespace internal {
+
+class BitVector;
+
namespace compiler {
class ControlBuilder;
class Graph;
class LoopAssignmentAnalysis;
class LoopBuilder;
+class Node;
// The AstGraphBuilder produces a high-level IR graph, based on an
// underlying AST. The produced graph can either be compiled into a
// stand-alone function or be wired into another graph for the purposes
// of function inlining.
-class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
+class AstGraphBuilder : public AstVisitor {
public:
AstGraphBuilder(Zone* local_zone, CompilationInfo* info, JSGraph* jsgraph,
LoopAssignmentAnalysis* loop_assignment = NULL);
// Creates a graph by visiting the entire AST.
- bool CreateGraph();
+ bool CreateGraph(bool constant_context);
+
+ // Helpers to create new control nodes.
+ Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
+ Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
+ Node* NewMerge() { return NewNode(common()->Merge(1), true); }
+ Node* NewLoop() { return NewNode(common()->Loop(1), true); }
+ Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
+ return NewNode(common()->Branch(hint), condition);
+ }
protected:
+#define DECLARE_VISIT(type) void Visit##type(type* node) OVERRIDE;
+ // Visiting functions for AST nodes make this an AstVisitor.
+ AST_NODE_LIST(DECLARE_VISIT)
+#undef DECLARE_VISIT
+
+ // Visiting function for declarations list is overridden.
+ void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE;
+
+ private:
class AstContext;
class AstEffectContext;
class AstValueContext;
class AstTestContext;
- class BreakableScope;
class ContextScope;
+ class ControlScope;
+ class ControlScopeForBreakable;
+ class ControlScopeForIteration;
+ class ControlScopeForCatch;
+ class ControlScopeForFinally;
class Environment;
+ friend class ControlBuilder;
- Environment* environment() {
- return reinterpret_cast<Environment*>(
- StructuredGraphBuilder::environment());
- }
+ Zone* local_zone_;
+ CompilationInfo* info_;
+ JSGraph* jsgraph_;
+ Environment* environment_;
+ AstContext* ast_context_;
+ // List of global declarations for functions and variables.
+ ZoneVector<Handle<Object>> globals_;
+
+ // Stack of control scopes currently entered by the visitor.
+ ControlScope* execution_control_;
+
+ // Stack of context objects pushed onto the chain by the visitor.
+ ContextScope* execution_context_;
+
+ // Nodes representing values in the activation record.
+ SetOncePointer<Node> function_closure_;
+ SetOncePointer<Node> function_context_;
+
+ // Temporary storage for building node input lists.
+ int input_buffer_size_;
+ Node** input_buffer_;
+
+ // Merge of all control nodes that exit the function body.
+ Node* exit_control_;
+
+ // Result of loop assignment analysis performed before graph creation.
+ LoopAssignmentAnalysis* loop_assignment_analysis_;
+
+ // Growth increment for the temporary buffer used to construct input lists to
+ // new nodes.
+ static const int kInputBufferSizeIncrement = 64;
+
+ Zone* local_zone() const { return local_zone_; }
+ Environment* environment() const { return environment_; }
AstContext* ast_context() const { return ast_context_; }
- BreakableScope* breakable() const { return breakable_; }
+ ControlScope* execution_control() const { return execution_control_; }
ContextScope* execution_context() const { return execution_context_; }
+ CommonOperatorBuilder* common() const { return jsgraph_->common(); }
+ CompilationInfo* info() const { return info_; }
+ LanguageMode language_mode() const;
+ JSGraph* jsgraph() { return jsgraph_; }
+ Graph* graph() { return jsgraph_->graph(); }
+ Zone* graph_zone() { return graph()->zone(); }
+ JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
+ ZoneVector<Handle<Object>>* globals() { return &globals_; }
+ Scope* current_scope() const;
+ Node* current_context() const;
+ Node* exit_control() const { return exit_control_; }
+ void set_environment(Environment* env) { environment_ = env; }
void set_ast_context(AstContext* ctx) { ast_context_ = ctx; }
- void set_breakable(BreakableScope* brk) { breakable_ = brk; }
+ void set_execution_control(ControlScope* ctrl) { execution_control_ = ctrl; }
void set_execution_context(ContextScope* ctx) { execution_context_ = ctx; }
+ void set_exit_control(Node* exit) { exit_control_ = exit; }
+
+ // Create the main graph body by visiting the AST.
+ void CreateGraphBody();
- // Support for control flow builders. The concrete type of the environment
- // depends on the graph builder, but environments themselves are not virtual.
- typedef StructuredGraphBuilder::Environment BaseEnvironment;
- BaseEnvironment* CopyEnvironment(BaseEnvironment* env) OVERRIDE;
+ // Create the node that represents the outer context of the function.
+ void CreateFunctionContext(bool constant_context);
- // Getters for values in the activation record.
+ // Get or create the node that represents the outer function closure.
Node* GetFunctionClosure();
- Node* GetFunctionContext();
+
+ // Node creation helpers.
+ Node* NewNode(const Operator* op, bool incomplete = false) {
+ return MakeNode(op, 0, static_cast<Node**>(NULL), incomplete);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1) {
+ return MakeNode(op, 1, &n1, false);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2) {
+ Node* buffer[] = {n1, n2};
+ return MakeNode(op, arraysize(buffer), buffer, false);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
+ Node* buffer[] = {n1, n2, n3};
+ return MakeNode(op, arraysize(buffer), buffer, false);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
+ Node* buffer[] = {n1, n2, n3, n4};
+ return MakeNode(op, arraysize(buffer), buffer, false);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
+ Node* n5) {
+ Node* buffer[] = {n1, n2, n3, n4, n5};
+ return MakeNode(op, arraysize(buffer), buffer, false);
+ }
+
+ Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
+ Node* n5, Node* n6) {
+ Node* nodes[] = {n1, n2, n3, n4, n5, n6};
+ return MakeNode(op, arraysize(nodes), nodes, false);
+ }
+
+ Node* NewNode(const Operator* op, int value_input_count, Node** value_inputs,
+ bool incomplete = false) {
+ return MakeNode(op, value_input_count, value_inputs, incomplete);
+ }
+
+ // Creates a new Phi node having {count} input values.
+ Node* NewPhi(int count, Node* input, Node* control);
+ Node* NewEffectPhi(int count, Node* input, Node* control);
+
+ Node* NewOuterContextParam();
+ Node* NewCurrentContextOsrValue();
+
+ // Helpers for merging control, effect or value dependencies.
+ Node* MergeControl(Node* control, Node* other);
+ Node* MergeEffect(Node* value, Node* other, Node* control);
+ Node* MergeValue(Node* value, Node* other, Node* control);
+
+ // The main node creation chokepoint. Adds context, frame state, effect,
+ // and control dependencies depending on the operator.
+ Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
+ bool incomplete);
+
+ // Helper to indicate a node exits the function body.
+ void UpdateControlDependencyToLeaveFunction(Node* exit);
//
// The following build methods all generate graph fragments and return one
@@ -72,12 +200,16 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
// Builder to create a receiver check for sloppy mode.
Node* BuildPatchReceiverToGlobalProxy(Node* receiver);
- // Builder to create a local function context.
+ // Builders to create local function and block contexts.
Node* BuildLocalFunctionContext(Node* context, Node* closure);
+ Node* BuildLocalBlockContext(Scope* scope);
// Builder to create an arguments object if it is used.
Node* BuildArgumentsObject(Variable* arguments);
+ // Builder to create an array of rest parameters if used
+ Node* BuildRestArgumentsArray(Variable* rest, int index);
+
// Builders for variable load and assignment.
Node* BuildVariableAssignment(Variable* var, Node* value, Token::Value op,
BailoutId bailout_id,
@@ -98,6 +230,11 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
// Builders for automatic type conversion.
Node* BuildToBoolean(Node* value);
+ Node* BuildToName(Node* value, BailoutId bailout_id);
+
+ // Builder for adding the [[HomeObject]] to a value if the value came from a
+ // function literal and needs a home object. Do nothing otherwise.
+ Node* BuildSetHomeObject(Node* value, Node* home_object, Expression* expr);
// Builders for error reporting at runtime.
Node* BuildThrowReferenceError(Variable* var, BailoutId bailout_id);
@@ -108,49 +245,27 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
Node* BuildHoleCheckThrow(Node* value, Variable* var, Node* not_hole,
BailoutId bailout_id);
+ // Builders for non-local control flow.
+ Node* BuildReturn(Node* return_value);
+ Node* BuildThrow(Node* exception_value);
+
// Builders for binary operations.
Node* BuildBinaryOp(Node* left, Node* right, Token::Value op);
// Builder for stack-check guards.
Node* BuildStackCheck();
-#define DECLARE_VISIT(type) void Visit##type(type* node) OVERRIDE;
- // Visiting functions for AST nodes make this an AstVisitor.
- AST_NODE_LIST(DECLARE_VISIT)
-#undef DECLARE_VISIT
-
- // Visiting function for declarations list is overridden.
- void VisitDeclarations(ZoneList<Declaration*>* declarations) OVERRIDE;
+ // Check if the given statement is an OSR entry.
+ // If so, record the stack height into the compilation and return {true}.
+ bool CheckOsrEntry(IterationStatement* stmt);
- private:
- CompilationInfo* info_;
- AstContext* ast_context_;
- JSGraph* jsgraph_;
-
- // List of global declarations for functions and variables.
- ZoneVector<Handle<Object>> globals_;
-
- // Stack of breakable statements entered by the visitor.
- BreakableScope* breakable_;
-
- // Stack of context objects pushed onto the chain by the visitor.
- ContextScope* execution_context_;
-
- // Nodes representing values in the activation record.
- SetOncePointer<Node> function_closure_;
- SetOncePointer<Node> function_context_;
-
- // Result of loop assignment analysis performed before graph creation.
- LoopAssignmentAnalysis* loop_assignment_analysis_;
-
- CompilationInfo* info() const { return info_; }
- inline StrictMode strict_mode() const;
- JSGraph* jsgraph() { return jsgraph_; }
- JSOperatorBuilder* javascript() { return jsgraph_->javascript(); }
- ZoneVector<Handle<Object>>* globals() { return &globals_; }
+ // Helper to wrap a Handle<T> into a Unique<T>.
+ template <class T>
+ Unique<T> MakeUnique(Handle<T> object) {
+ return Unique<T>::CreateUninitialized(object);
+ }
- // Current scope during visitation.
- inline Scope* current_scope() const;
+ Node** EnsureInputBufferSize(int size);
// Named and keyed loads require a VectorSlotPair for successful lowering.
VectorSlotPair CreateVectorSlotPair(FeedbackVectorICSlot slot) const;
@@ -168,6 +283,7 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
void VisitForEffect(Expression* expr);
void VisitForValue(Expression* expr);
void VisitForValueOrNull(Expression* expr);
+ void VisitForValueOrTheHole(Expression* expr);
void VisitForValues(ZoneList<Expression*>* exprs);
// Common for all IterationStatement bodies.
@@ -188,7 +304,12 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
void VisitArithmeticExpression(BinaryOperation* expr);
// Dispatched from VisitForInStatement.
- void VisitForInAssignment(Expression* expr, Node* value);
+ void VisitForInAssignment(Expression* expr, Node* value,
+ BailoutId bailout_id);
+ void VisitForInBody(ForInStatement* stmt);
+
+ // Dispatched from VisitClassLiteral.
+ void VisitClassLiteralContents(ClassLiteral* expr);
// Builds deoptimization for a given node.
void PrepareFrameState(
@@ -210,11 +331,9 @@ class AstGraphBuilder : public StructuredGraphBuilder, public AstVisitor {
//
// [parameters (+receiver)] [locals] [operand stack]
//
-class AstGraphBuilder::Environment
- : public StructuredGraphBuilder::Environment {
+class AstGraphBuilder::Environment : public ZoneObject {
public:
Environment(AstGraphBuilder* builder, Scope* scope, Node* control_dependency);
- Environment(const Environment& copy);
int parameters_count() const { return parameters_count_; }
int locals_count() const { return locals_count_; }
@@ -244,6 +363,10 @@ class AstGraphBuilder::Environment
}
}
+ Node* Context() const { return contexts_.back(); }
+ void PushContext(Node* context) { contexts()->push_back(context); }
+ void PopContext() { contexts()->pop_back(); }
+
// Operations on the operand stack.
void Push(Node* node) {
values()->push_back(node);
@@ -279,170 +402,72 @@ class AstGraphBuilder::Environment
// further mutation of the environment will not affect checkpoints.
Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine);
- protected:
- AstGraphBuilder* builder() const {
- return reinterpret_cast<AstGraphBuilder*>(
- StructuredGraphBuilder::Environment::builder());
+ // Control dependency tracked by this environment.
+ Node* GetControlDependency() { return control_dependency_; }
+ void UpdateControlDependency(Node* dependency) {
+ control_dependency_ = dependency;
}
- private:
- void UpdateStateValues(Node** state_values, int offset, int count);
-
- int parameters_count_;
- int locals_count_;
- Node* parameters_node_;
- Node* locals_node_;
- Node* stack_node_;
-};
-
-
-// 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();
+ // Effect dependency tracked by this environment.
+ Node* GetEffectDependency() { return effect_dependency_; }
+ void UpdateEffectDependency(Node* dependency) {
+ effect_dependency_ = dependency;
}
- // 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 breakable statements entered by the visitor. Allows to
-// properly 'break' and 'continue' iteration statements as well as to 'break'
-// from blocks within switch statements.
-class AstGraphBuilder::BreakableScope BASE_EMBEDDED {
- public:
- BreakableScope(AstGraphBuilder* owner, BreakableStatement* target,
- ControlBuilder* control, int drop_extra)
- : owner_(owner),
- target_(target),
- next_(owner->breakable()),
- control_(control),
- drop_extra_(drop_extra) {
- owner_->set_breakable(this); // Push.
+ // Mark this environment as being unreachable.
+ void MarkAsUnreachable() {
+ UpdateControlDependency(builder()->jsgraph()->DeadControl());
}
-
- ~BreakableScope() {
- owner_->set_breakable(next_); // Pop.
+ bool IsMarkedAsUnreachable() {
+ return GetControlDependency()->opcode() == IrOpcode::kDead;
}
- // Either 'break' or 'continue' the target statement.
- void BreakTarget(BreakableStatement* target);
- void ContinueTarget(BreakableStatement* target);
-
- private:
- AstGraphBuilder* owner_;
- BreakableStatement* target_;
- BreakableScope* next_;
- ControlBuilder* control_;
- int drop_extra_;
-
- // Find the correct scope for the target statement. Note that this also drops
- // extra operands from the environment for each scope skipped along the way.
- BreakableScope* FindBreakable(BreakableStatement* target);
-};
+ // Merge another environment into this one.
+ void Merge(Environment* other);
+ // Copies this environment at a control-flow split point.
+ Environment* CopyForConditional() { return Copy(); }
-// 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);
+ // Copies this environment to a potentially unreachable control-flow point.
+ Environment* CopyAsUnreachable() {
+ Environment* env = Copy();
+ env->MarkAsUnreachable();
+ return env;
}
- ~ContextScope() {
- owner_->set_execution_context(next_); // Pop.
- owner_->set_current_context(outer_);
+ // Copies this environment at a loop header control-flow point.
+ Environment* CopyForLoop(BitVector* assigned, bool is_osr = false) {
+ PrepareForLoop(assigned, is_osr);
+ return Copy();
}
- // Current scope during visitation.
- Scope* scope() const { return scope_; }
+ int ContextStackDepth() { return static_cast<int>(contexts_.size()); }
private:
- AstGraphBuilder* owner_;
- ContextScope* next_;
- Node* outer_;
- Scope* scope_;
-};
+ AstGraphBuilder* builder_;
+ int parameters_count_;
+ int locals_count_;
+ NodeVector values_;
+ NodeVector contexts_;
+ Node* control_dependency_;
+ Node* effect_dependency_;
+ Node* parameters_node_;
+ Node* locals_node_;
+ Node* stack_node_;
-Scope* AstGraphBuilder::current_scope() const {
- return execution_context_->scope();
-}
+ explicit Environment(const Environment* copy);
+ Environment* Copy() { return new (zone()) Environment(this); }
+ void UpdateStateValues(Node** state_values, int offset, int count);
+ Zone* zone() const { return builder_->local_zone(); }
+ Graph* graph() const { return builder_->graph(); }
+ AstGraphBuilder* builder() const { return builder_; }
+ CommonOperatorBuilder* common() { return builder_->common(); }
+ NodeVector* values() { return &values_; }
+ NodeVector* contexts() { return &contexts_; }
+
+ // Prepare environment to be used as loop header.
+ void PrepareForLoop(BitVector* assigned, bool is_osr = false);
+};
} // namespace compiler
} // namespace internal