blob: 2fa5967c86a64186a0e3ab276bab5db846835eda [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
6#define V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
7
8#include "src/compiler.h"
9#include "src/compiler/bytecode-branch-analysis.h"
10#include "src/compiler/js-graph.h"
11#include "src/interpreter/bytecode-array-iterator.h"
12#include "src/interpreter/bytecodes.h"
13
14namespace v8 {
15namespace internal {
16namespace compiler {
17
18// The BytecodeGraphBuilder produces a high-level IR graph based on
19// interpreter bytecodes.
20class BytecodeGraphBuilder {
21 public:
22 BytecodeGraphBuilder(Zone* local_zone, CompilationInfo* info,
23 JSGraph* jsgraph);
24
25 // Creates a graph by visiting bytecodes.
Ben Murdoch097c5b22016-05-18 11:27:45 +010026 bool CreateGraph();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000027
28 private:
29 class Environment;
30 class FrameStateBeforeAndAfter;
31
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032 void VisitBytecodes();
33
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000034 // Get or create the node that represents the outer function closure.
35 Node* GetFunctionClosure();
36
37 // Get or create the node that represents the outer function context.
38 Node* GetFunctionContext();
39
40 // Get or create the node that represents the incoming new target value.
41 Node* GetNewTarget();
42
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043 // Builder for loading the a native context field.
44 Node* BuildLoadNativeContextField(int index);
45
46 // Helper function for creating a pair containing type feedback vector and
47 // a feedback slot.
48 VectorSlotPair CreateVectorSlotPair(int slot_id);
49
50 void set_environment(Environment* env) { environment_ = env; }
51 const Environment* environment() const { return environment_; }
52 Environment* environment() { return environment_; }
53
54 // Node creation helpers
55 Node* NewNode(const Operator* op, bool incomplete = false) {
56 return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
57 }
58
59 Node* NewNode(const Operator* op, Node* n1) {
60 Node* buffer[] = {n1};
61 return MakeNode(op, arraysize(buffer), buffer, false);
62 }
63
64 Node* NewNode(const Operator* op, Node* n1, Node* n2) {
65 Node* buffer[] = {n1, n2};
66 return MakeNode(op, arraysize(buffer), buffer, false);
67 }
68
69 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
70 Node* buffer[] = {n1, n2, n3};
71 return MakeNode(op, arraysize(buffer), buffer, false);
72 }
73
74 Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
75 Node* buffer[] = {n1, n2, n3, n4};
76 return MakeNode(op, arraysize(buffer), buffer, false);
77 }
78
79 // Helpers to create new control nodes.
80 Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
81 Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
82 Node* NewMerge() { return NewNode(common()->Merge(1), true); }
83 Node* NewLoop() { return NewNode(common()->Loop(1), true); }
84 Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
85 return NewNode(common()->Branch(hint), condition);
86 }
87
88 // Creates a new Phi node having {count} input values.
89 Node* NewPhi(int count, Node* input, Node* control);
90 Node* NewEffectPhi(int count, Node* input, Node* control);
91
92 // Helpers for merging control, effect or value dependencies.
93 Node* MergeControl(Node* control, Node* other);
94 Node* MergeEffect(Node* effect, Node* other_effect, Node* control);
95 Node* MergeValue(Node* value, Node* other_value, Node* control);
96
97 // The main node creation chokepoint. Adds context, frame state, effect,
98 // and control dependencies depending on the operator.
99 Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
100 bool incomplete);
101
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 Node** EnsureInputBufferSize(int size);
103
104 Node* ProcessCallArguments(const Operator* call_op, Node* callee,
105 interpreter::Register receiver, size_t arity);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100106 Node* ProcessCallNewArguments(const Operator* call_new_op, Node* callee,
107 Node* new_target,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108 interpreter::Register first_arg, size_t arity);
109 Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
110 interpreter::Register first_arg,
111 size_t arity);
112
Ben Murdoch097c5b22016-05-18 11:27:45 +0100113 void BuildCreateLiteral(const Operator* op);
114 void BuildCreateRegExpLiteral();
115 void BuildCreateArrayLiteral();
116 void BuildCreateObjectLiteral();
117 void BuildCreateArguments(CreateArgumentsType type);
118 void BuildLoadGlobal(TypeofMode typeof_mode);
119 void BuildStoreGlobal(LanguageMode language_mode);
120 void BuildNamedLoad();
121 void BuildKeyedLoad();
122 void BuildNamedStore(LanguageMode language_mode);
123 void BuildKeyedStore(LanguageMode language_mode);
124 void BuildLdaLookupSlot(TypeofMode typeof_mode);
125 void BuildStaLookupSlot(LanguageMode language_mode);
126 void BuildCall(TailCallMode tail_call_mode);
127 void BuildCallJSRuntime();
128 void BuildCallRuntime();
129 void BuildCallRuntimeForPair();
130 void BuildCallConstruct();
131 void BuildThrow();
132 void BuildBinaryOp(const Operator* op);
133 void BuildCompareOp(const Operator* op);
134 void BuildDelete(LanguageMode language_mode);
135 void BuildCastOperator(const Operator* op);
136 void BuildForInPrepare();
137 void BuildForInNext();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138
139 // Control flow plumbing.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 void BuildJump();
141 void BuildConditionalJump(Node* condition);
142 void BuildJumpIfEqual(Node* comperand);
143 void BuildJumpIfToBooleanEqual(Node* boolean_comperand);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100144 void BuildJumpIfNotHole();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145
Ben Murdoch097c5b22016-05-18 11:27:45 +0100146 // Simulates control flow by forward-propagating environments.
147 void MergeIntoSuccessorEnvironment(int target_offset);
148 void BuildLoopHeaderEnvironment(int current_offset);
149 void SwitchToMergeEnvironment(int current_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150
Ben Murdoch097c5b22016-05-18 11:27:45 +0100151 // Simulates control flow that exits the function body.
152 void MergeControlToLeaveFunction(Node* exit);
153
154 // Simulates entry and exit of exception handlers.
155 void EnterAndExitExceptionHandlers(int current_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156
157 // Growth increment for the temporary buffer used to construct input lists to
158 // new nodes.
159 static const int kInputBufferSizeIncrement = 64;
160
Ben Murdoch097c5b22016-05-18 11:27:45 +0100161 // The catch prediction from the handler table is reused.
162 typedef HandlerTable::CatchPrediction CatchPrediction;
163
164 // An abstract representation for an exception handler that is being
165 // entered and exited while the graph builder is iterating over the
166 // underlying bytecode. The exception handlers within the bytecode are
167 // well scoped, hence will form a stack during iteration.
168 struct ExceptionHandler {
169 int start_offset_; // Start offset of the handled area in the bytecode.
170 int end_offset_; // End offset of the handled area in the bytecode.
171 int handler_offset_; // Handler entry offset within the bytecode.
172 int context_register_; // Index of register holding handler context.
173 CatchPrediction pred_; // Prediction of whether handler is catching.
174 };
175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 // Field accessors
Ben Murdoch097c5b22016-05-18 11:27:45 +0100177 Graph* graph() const { return jsgraph_->graph(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000178 CommonOperatorBuilder* common() const { return jsgraph_->common(); }
179 Zone* graph_zone() const { return graph()->zone(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180 JSGraph* jsgraph() const { return jsgraph_; }
181 JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); }
182 Zone* local_zone() const { return local_zone_; }
183 const Handle<BytecodeArray>& bytecode_array() const {
184 return bytecode_array_;
185 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100186 const Handle<HandlerTable>& exception_handler_table() const {
187 return exception_handler_table_;
188 }
189 const Handle<TypeFeedbackVector>& feedback_vector() const {
190 return feedback_vector_;
191 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 const FrameStateFunctionInfo* frame_state_function_info() const {
193 return frame_state_function_info_;
194 }
195
Ben Murdoch097c5b22016-05-18 11:27:45 +0100196 const interpreter::BytecodeArrayIterator& bytecode_iterator() const {
197 return *bytecode_iterator_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 }
199
200 void set_bytecode_iterator(
201 const interpreter::BytecodeArrayIterator* bytecode_iterator) {
202 bytecode_iterator_ = bytecode_iterator;
203 }
204
205 const BytecodeBranchAnalysis* branch_analysis() const {
206 return branch_analysis_;
207 }
208
209 void set_branch_analysis(const BytecodeBranchAnalysis* branch_analysis) {
210 branch_analysis_ = branch_analysis;
211 }
212
Ben Murdoch097c5b22016-05-18 11:27:45 +0100213#define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
215#undef DECLARE_VISIT_BYTECODE
216
217 Zone* local_zone_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 JSGraph* jsgraph_;
219 Handle<BytecodeArray> bytecode_array_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100220 Handle<HandlerTable> exception_handler_table_;
221 Handle<TypeFeedbackVector> feedback_vector_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 const FrameStateFunctionInfo* frame_state_function_info_;
223 const interpreter::BytecodeArrayIterator* bytecode_iterator_;
224 const BytecodeBranchAnalysis* branch_analysis_;
225 Environment* environment_;
226
Ben Murdoch097c5b22016-05-18 11:27:45 +0100227 // Indicates whether deoptimization support is enabled for this compilation
228 // and whether valid frame states need to be attached to deoptimizing nodes.
229 bool deoptimization_enabled_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230
Ben Murdoch097c5b22016-05-18 11:27:45 +0100231 // Merge environments are snapshots of the environment at points where the
232 // control flow merges. This models a forward data flow propagation of all
233 // values from all predecessors of the merge in question.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234 ZoneMap<int, Environment*> merge_environments_;
235
Ben Murdoch097c5b22016-05-18 11:27:45 +0100236 // Exception handlers currently entered by the iteration.
237 ZoneStack<ExceptionHandler> exception_handlers_;
238 int current_exception_handler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239
240 // Temporary storage for building node input lists.
241 int input_buffer_size_;
242 Node** input_buffer_;
243
244 // Nodes representing values in the activation record.
245 SetOncePointer<Node> function_context_;
246 SetOncePointer<Node> function_closure_;
247 SetOncePointer<Node> new_target_;
248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249 // Control nodes that exit the function body.
250 ZoneVector<Node*> exit_controls_;
251
252 DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilder);
253};
254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255} // namespace compiler
256} // namespace internal
257} // namespace v8
258
259#endif // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_