blob: 66cd96e0fb32b731bb97b3a7d84d900458a1e8bc [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);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100114 void BuildCreateArguments(CreateArgumentsType type);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100115 Node* BuildLoadContextSlot();
116 Node* BuildLoadGlobal(TypeofMode typeof_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100117 void BuildStoreGlobal(LanguageMode language_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100118 Node* BuildNamedLoad();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100119 void BuildNamedStore(LanguageMode language_mode);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100120 Node* BuildKeyedLoad();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100121 void BuildKeyedStore(LanguageMode language_mode);
122 void BuildLdaLookupSlot(TypeofMode typeof_mode);
123 void BuildStaLookupSlot(LanguageMode language_mode);
124 void BuildCall(TailCallMode tail_call_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 void BuildThrow();
126 void BuildBinaryOp(const Operator* op);
127 void BuildCompareOp(const Operator* op);
128 void BuildDelete(LanguageMode language_mode);
129 void BuildCastOperator(const Operator* op);
130 void BuildForInPrepare();
131 void BuildForInNext();
Ben Murdochda12d292016-06-02 14:46:10 +0100132 void BuildInvokeIntrinsic();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133
134 // Control flow plumbing.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135 void BuildJump();
136 void BuildConditionalJump(Node* condition);
137 void BuildJumpIfEqual(Node* comperand);
138 void BuildJumpIfToBooleanEqual(Node* boolean_comperand);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100139 void BuildJumpIfNotHole();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140
Ben Murdoch097c5b22016-05-18 11:27:45 +0100141 // Simulates control flow by forward-propagating environments.
142 void MergeIntoSuccessorEnvironment(int target_offset);
143 void BuildLoopHeaderEnvironment(int current_offset);
144 void SwitchToMergeEnvironment(int current_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145
Ben Murdoch097c5b22016-05-18 11:27:45 +0100146 // Simulates control flow that exits the function body.
147 void MergeControlToLeaveFunction(Node* exit);
148
149 // Simulates entry and exit of exception handlers.
150 void EnterAndExitExceptionHandlers(int current_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151
152 // Growth increment for the temporary buffer used to construct input lists to
153 // new nodes.
154 static const int kInputBufferSizeIncrement = 64;
155
Ben Murdoch097c5b22016-05-18 11:27:45 +0100156 // The catch prediction from the handler table is reused.
157 typedef HandlerTable::CatchPrediction CatchPrediction;
158
159 // An abstract representation for an exception handler that is being
160 // entered and exited while the graph builder is iterating over the
161 // underlying bytecode. The exception handlers within the bytecode are
162 // well scoped, hence will form a stack during iteration.
163 struct ExceptionHandler {
164 int start_offset_; // Start offset of the handled area in the bytecode.
165 int end_offset_; // End offset of the handled area in the bytecode.
166 int handler_offset_; // Handler entry offset within the bytecode.
167 int context_register_; // Index of register holding handler context.
168 CatchPrediction pred_; // Prediction of whether handler is catching.
169 };
170
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 // Field accessors
Ben Murdoch097c5b22016-05-18 11:27:45 +0100172 Graph* graph() const { return jsgraph_->graph(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000173 CommonOperatorBuilder* common() const { return jsgraph_->common(); }
174 Zone* graph_zone() const { return graph()->zone(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175 JSGraph* jsgraph() const { return jsgraph_; }
176 JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); }
177 Zone* local_zone() const { return local_zone_; }
178 const Handle<BytecodeArray>& bytecode_array() const {
179 return bytecode_array_;
180 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100181 const Handle<HandlerTable>& exception_handler_table() const {
182 return exception_handler_table_;
183 }
184 const Handle<TypeFeedbackVector>& feedback_vector() const {
185 return feedback_vector_;
186 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 const FrameStateFunctionInfo* frame_state_function_info() const {
188 return frame_state_function_info_;
189 }
190
Ben Murdoch097c5b22016-05-18 11:27:45 +0100191 const interpreter::BytecodeArrayIterator& bytecode_iterator() const {
192 return *bytecode_iterator_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 }
194
195 void set_bytecode_iterator(
196 const interpreter::BytecodeArrayIterator* bytecode_iterator) {
197 bytecode_iterator_ = bytecode_iterator;
198 }
199
200 const BytecodeBranchAnalysis* branch_analysis() const {
201 return branch_analysis_;
202 }
203
204 void set_branch_analysis(const BytecodeBranchAnalysis* branch_analysis) {
205 branch_analysis_ = branch_analysis;
206 }
207
Ben Murdoch097c5b22016-05-18 11:27:45 +0100208#define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209 BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
210#undef DECLARE_VISIT_BYTECODE
211
212 Zone* local_zone_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213 JSGraph* jsgraph_;
214 Handle<BytecodeArray> bytecode_array_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100215 Handle<HandlerTable> exception_handler_table_;
216 Handle<TypeFeedbackVector> feedback_vector_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000217 const FrameStateFunctionInfo* frame_state_function_info_;
218 const interpreter::BytecodeArrayIterator* bytecode_iterator_;
219 const BytecodeBranchAnalysis* branch_analysis_;
220 Environment* environment_;
221
Ben Murdoch097c5b22016-05-18 11:27:45 +0100222 // Merge environments are snapshots of the environment at points where the
223 // control flow merges. This models a forward data flow propagation of all
224 // values from all predecessors of the merge in question.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225 ZoneMap<int, Environment*> merge_environments_;
226
Ben Murdoch097c5b22016-05-18 11:27:45 +0100227 // Exception handlers currently entered by the iteration.
228 ZoneStack<ExceptionHandler> exception_handlers_;
229 int current_exception_handler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230
231 // Temporary storage for building node input lists.
232 int input_buffer_size_;
233 Node** input_buffer_;
234
235 // Nodes representing values in the activation record.
236 SetOncePointer<Node> function_context_;
237 SetOncePointer<Node> function_closure_;
238 SetOncePointer<Node> new_target_;
239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 // Control nodes that exit the function body.
241 ZoneVector<Node*> exit_controls_;
242
243 DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilder);
244};
245
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246} // namespace compiler
247} // namespace internal
248} // namespace v8
249
250#endif // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_