blob: c842c24b8cc8860ec85641d3491551b0e1382543 [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);
115 void BuildLoadGlobal(TypeofMode typeof_mode);
116 void BuildStoreGlobal(LanguageMode language_mode);
117 void BuildNamedLoad();
118 void BuildKeyedLoad();
119 void BuildNamedStore(LanguageMode language_mode);
120 void BuildKeyedStore(LanguageMode language_mode);
121 void BuildLdaLookupSlot(TypeofMode typeof_mode);
122 void BuildStaLookupSlot(LanguageMode language_mode);
123 void BuildCall(TailCallMode tail_call_mode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100124 void BuildThrow();
125 void BuildBinaryOp(const Operator* op);
126 void BuildCompareOp(const Operator* op);
127 void BuildDelete(LanguageMode language_mode);
128 void BuildCastOperator(const Operator* op);
129 void BuildForInPrepare();
130 void BuildForInNext();
Ben Murdochda12d292016-06-02 14:46:10 +0100131 void BuildInvokeIntrinsic();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132
133 // Control flow plumbing.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 void BuildJump();
135 void BuildConditionalJump(Node* condition);
136 void BuildJumpIfEqual(Node* comperand);
137 void BuildJumpIfToBooleanEqual(Node* boolean_comperand);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100138 void BuildJumpIfNotHole();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000139
Ben Murdoch097c5b22016-05-18 11:27:45 +0100140 // Simulates control flow by forward-propagating environments.
141 void MergeIntoSuccessorEnvironment(int target_offset);
142 void BuildLoopHeaderEnvironment(int current_offset);
143 void SwitchToMergeEnvironment(int current_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000144
Ben Murdoch097c5b22016-05-18 11:27:45 +0100145 // Simulates control flow that exits the function body.
146 void MergeControlToLeaveFunction(Node* exit);
147
148 // Simulates entry and exit of exception handlers.
149 void EnterAndExitExceptionHandlers(int current_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150
151 // Growth increment for the temporary buffer used to construct input lists to
152 // new nodes.
153 static const int kInputBufferSizeIncrement = 64;
154
Ben Murdoch097c5b22016-05-18 11:27:45 +0100155 // The catch prediction from the handler table is reused.
156 typedef HandlerTable::CatchPrediction CatchPrediction;
157
158 // An abstract representation for an exception handler that is being
159 // entered and exited while the graph builder is iterating over the
160 // underlying bytecode. The exception handlers within the bytecode are
161 // well scoped, hence will form a stack during iteration.
162 struct ExceptionHandler {
163 int start_offset_; // Start offset of the handled area in the bytecode.
164 int end_offset_; // End offset of the handled area in the bytecode.
165 int handler_offset_; // Handler entry offset within the bytecode.
166 int context_register_; // Index of register holding handler context.
167 CatchPrediction pred_; // Prediction of whether handler is catching.
168 };
169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 // Field accessors
Ben Murdoch097c5b22016-05-18 11:27:45 +0100171 Graph* graph() const { return jsgraph_->graph(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172 CommonOperatorBuilder* common() const { return jsgraph_->common(); }
173 Zone* graph_zone() const { return graph()->zone(); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 JSGraph* jsgraph() const { return jsgraph_; }
175 JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); }
176 Zone* local_zone() const { return local_zone_; }
177 const Handle<BytecodeArray>& bytecode_array() const {
178 return bytecode_array_;
179 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100180 const Handle<HandlerTable>& exception_handler_table() const {
181 return exception_handler_table_;
182 }
183 const Handle<TypeFeedbackVector>& feedback_vector() const {
184 return feedback_vector_;
185 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000186 const FrameStateFunctionInfo* frame_state_function_info() const {
187 return frame_state_function_info_;
188 }
189
Ben Murdoch097c5b22016-05-18 11:27:45 +0100190 const interpreter::BytecodeArrayIterator& bytecode_iterator() const {
191 return *bytecode_iterator_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 }
193
194 void set_bytecode_iterator(
195 const interpreter::BytecodeArrayIterator* bytecode_iterator) {
196 bytecode_iterator_ = bytecode_iterator;
197 }
198
199 const BytecodeBranchAnalysis* branch_analysis() const {
200 return branch_analysis_;
201 }
202
203 void set_branch_analysis(const BytecodeBranchAnalysis* branch_analysis) {
204 branch_analysis_ = branch_analysis;
205 }
206
Ben Murdoch097c5b22016-05-18 11:27:45 +0100207#define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
209#undef DECLARE_VISIT_BYTECODE
210
211 Zone* local_zone_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 JSGraph* jsgraph_;
213 Handle<BytecodeArray> bytecode_array_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100214 Handle<HandlerTable> exception_handler_table_;
215 Handle<TypeFeedbackVector> feedback_vector_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 const FrameStateFunctionInfo* frame_state_function_info_;
217 const interpreter::BytecodeArrayIterator* bytecode_iterator_;
218 const BytecodeBranchAnalysis* branch_analysis_;
219 Environment* environment_;
220
Ben Murdoch097c5b22016-05-18 11:27:45 +0100221 // Indicates whether deoptimization support is enabled for this compilation
222 // and whether valid frame states need to be attached to deoptimizing nodes.
223 bool deoptimization_enabled_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224
Ben Murdoch097c5b22016-05-18 11:27:45 +0100225 // Merge environments are snapshots of the environment at points where the
226 // control flow merges. This models a forward data flow propagation of all
227 // values from all predecessors of the merge in question.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 ZoneMap<int, Environment*> merge_environments_;
229
Ben Murdoch097c5b22016-05-18 11:27:45 +0100230 // Exception handlers currently entered by the iteration.
231 ZoneStack<ExceptionHandler> exception_handlers_;
232 int current_exception_handler_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233
234 // Temporary storage for building node input lists.
235 int input_buffer_size_;
236 Node** input_buffer_;
237
238 // Nodes representing values in the activation record.
239 SetOncePointer<Node> function_context_;
240 SetOncePointer<Node> function_closure_;
241 SetOncePointer<Node> new_target_;
242
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000243 // Control nodes that exit the function body.
244 ZoneVector<Node*> exit_controls_;
245
246 DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilder);
247};
248
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249} // namespace compiler
250} // namespace internal
251} // namespace v8
252
253#endif // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_