Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Side by Side Diff: src/compiler/graph-assembler.h

Issue 2571903004: [turbofan] Introduce graph assembler to build effect-control-linearizer sub-graphs. (Closed)
Patch Set: Fixes Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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_GRAPH_ASSEMBLER_H_
6 #define V8_COMPILER_GRAPH_ASSEMBLER_H_
7
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/node.h"
10 #include "src/compiler/simplified-operator.h"
11
12 namespace v8 {
13 namespace internal {
14
15 class JSGraph;
16 class Graph;
17
18 namespace compiler {
19
20 #define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \
21 V(ChangeInt32ToInt64) \
22 V(ChangeInt32ToFloat64) \
23 V(ChangeUint32ToFloat64) \
24 V(ChangeUint32ToUint64) \
25 V(ChangeFloat64ToInt32) \
26 V(ChangeFloat64ToUint32) \
27 V(TruncateInt64ToInt32) \
28 V(RoundFloat64ToInt32) \
29 V(TruncateFloat64ToWord32) \
30 V(Float64ExtractHighWord32) \
31 V(Float64Abs)
32
33 #define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \
34 V(WordShl) \
35 V(WordSar) \
36 V(WordAnd) \
37 V(Word32Or) \
38 V(Word32And) \
39 V(Word32Shr) \
40 V(Word32Shl) \
41 V(Int32Add) \
42 V(Int32Sub) \
43 V(Int32Mul) \
44 V(Int32LessThanOrEqual) \
45 V(Uint32LessThanOrEqual) \
46 V(Uint32LessThan) \
47 V(Int32LessThan) \
48 V(Float64Add) \
49 V(Float64Sub) \
50 V(Float64Mod) \
51 V(Float64Equal) \
52 V(Float64LessThan) \
53 V(Float64LessThanOrEqual) \
54 V(Word32Equal) \
55 V(WordEqual)
56
57 #define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V) \
58 V(Int32AddWithOverflow) \
59 V(Int32SubWithOverflow) \
60 V(Int32MulWithOverflow) \
61 V(Int32Mod) \
62 V(Int32Div) \
63 V(Uint32Mod) \
64 V(Uint32Div)
65
66 class GraphAssembler;
67
68 enum class GraphAssemblerLabelType { kDeferred, kNonDeferred };
69
70 // Label with statically known count of incoming branches and phis.
71 template <size_t MergeCount, size_t VarCount = 0u>
72 class GraphAssemblerStaticLabel {
73 public:
74 Node* PhiAt(size_t index);
75
76 template <typename... Reps>
77 explicit GraphAssemblerStaticLabel(GraphAssemblerLabelType is_deferred,
78 Reps... reps)
79 : is_deferred_(is_deferred == GraphAssemblerLabelType::kDeferred) {
80 STATIC_ASSERT(VarCount == sizeof...(reps));
81 MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
82 reps...};
83 for (size_t i = 0; i < VarCount; i++) {
84 representations_[i] = reps_array[i + 1];
85 }
86 }
87
88 ~GraphAssemblerStaticLabel() { DCHECK(IsBound() || MergedCount() == 0); }
89
90 private:
91 friend class GraphAssembler;
92
93 void SetBound() {
94 DCHECK(!IsBound());
95 DCHECK_EQ(merged_count_, MergeCount);
96 is_bound_ = true;
97 }
98 bool IsBound() { return is_bound_; }
Igor Sheludko 2017/01/02 13:23:27 Please make all getters const.
Jarin 2017/01/03 09:27:55 Done.
99
100 size_t PhiCount() { return VarCount; }
101 size_t MaxMergeCount() { return MergeCount; }
102 size_t MergedCount() { return merged_count_; }
103 bool IsDeferred() { return is_deferred_; }
104
105 // For each phi, the buffer must have at least MaxMergeCount() + 1
106 // node entries.
107 Node** GetBindingsPtrFor(size_t phi_index) {
Igor Sheludko 2017/01/02 13:23:27 Please add bounds checks here and in other getters
Jarin 2017/01/03 09:27:55 Done.
108 return &bindings_[phi_index * (MergeCount + 1)];
109 }
110 MachineRepresentation GetRepresentationFor(size_t phi_index) {
111 return representations_[phi_index];
112 }
113 // The controls buffer must have at least MaxMergeCount() entries.
114 Node** GetControlsPtr() { return controls_; }
115 // The effects buffer must have at least MaxMergeCount() + 1 entries.
116 Node** GetEffectsPtr() { return effects_; }
117 void IncrementMergedCount() { merged_count_++; }
118
119 bool is_bound_ = false;
120 bool is_deferred_;
121 size_t merged_count_ = 0;
122 Node* effects_[MergeCount + 1]; // Extra element for control edge,
123 // so that we can use the array to
124 // construct EffectPhi.
125 Node* controls_[MergeCount];
126 Node* bindings_[(MergeCount + 1) * VarCount + 1];
127 MachineRepresentation representations_[VarCount + 1];
128 };
129
130 // General label (with zone allocated buffers for incoming branches and phi
131 // inputs).
132 class GraphAssemblerLabel {
133 public:
134 Node* PhiAt(size_t index);
135
136 GraphAssemblerLabel(GraphAssemblerLabelType is_deferred, size_t merge_count,
137 size_t var_count, MachineRepresentation* representations,
138 Zone* zone);
139
140 ~GraphAssemblerLabel();
141
142 private:
143 friend class GraphAssembler;
144
145 void SetBound() {
146 DCHECK(!is_bound_);
147 is_bound_ = true;
148 }
149 bool IsBound() { return is_bound_; }
Igor Sheludko 2017/01/02 13:23:27 Same here.
Jarin 2017/01/03 09:27:55 Done.
150 size_t PhiCount() { return var_count_; }
151 size_t MaxMergeCount() { return max_merge_count_; }
152 size_t MergedCount() { return merged_count_; }
153 bool IsDeferred() { return is_deferred_; }
154
155 // For each phi, the buffer must have at least MaxMergeCount() + 1
156 // node entries.
157 Node** GetBindingsPtrFor(size_t phi_index);
158 MachineRepresentation GetRepresentationFor(size_t phi_index);
159 // The controls buffer must have at least MaxMergeCount() entries.
160 Node** GetControlsPtr();
161 // The effects buffer must have at least MaxMergeCount() + 1 entries.
162 Node** GetEffectsPtr();
163 void IncrementMergedCount() { merged_count_++; }
164
165 bool is_bound_ = false;
166 bool is_deferred_;
167 size_t merged_count_ = 0;
168 size_t max_merge_count_;
169 size_t var_count_;
170 Node** effects_ = nullptr;
171 Node** controls_ = nullptr;
172 Node** bindings_ = nullptr;
173 MachineRepresentation* representations_ = nullptr;
174 };
175
176 class GraphAssembler {
177 public:
178 GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, Zone* zone);
179
180 void Reset(Node* effect, Node* control);
181
182 // Create non-deferred label with statically known number of incoming
183 // gotos/branches.
184 template <size_t MergeCount, typename... Reps>
185 static GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)> MakeLabel(
Jarin 2016/12/27 13:51:06 There is one thing I do not like about this: the M
Igor Sheludko 2017/01/02 13:23:27 I think it's fine for labels to support move seman
186 Reps... reps) {
187 return GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>(
188 GraphAssemblerLabelType::kNonDeferred, reps...);
189 }
190
191 // Create deferred label with statically known number of incoming
192 // gotos/branches.
193 template <size_t MergeCount, typename... Reps>
194 static GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>
195 MakeDeferredLabel(Reps... reps) {
196 return GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>(
197 GraphAssemblerLabelType::kDeferred, reps...);
198 }
199
200 // Create label with number of incoming branches supplied at runtime.
201 template <typename... Reps>
202 GraphAssemblerLabel MakeLabelFor(GraphAssemblerLabelType is_deferred,
203 size_t merge_count, Reps... reps) {
204 MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
205 reps...};
206 return GraphAssemblerLabel(is_deferred, merge_count, sizeof...(reps),
207 &(reps_array[1]), temp_zone());
208 }
209
210 // Value creation.
211 Node* TrueConstant();
212 Node* FalseConstant();
213 Node* HeapNumberMapConstant();
214 Node* IntPtrConstant(intptr_t value);
215 Node* Uint32Constant(int32_t value);
216 Node* Int32Constant(int32_t value);
217 Node* SmiConstant(int32_t value);
218 Node* Float64Constant(double value);
219 Node* Projection(int index, Node* value);
220 Node* HeapConstant(Handle<HeapObject> object);
221 Node* NoContextConstant();
222 Node* CEntryStubConstant(int result_size);
223 Node* ExternalConstant(ExternalReference ref);
224 Node* EmptyStringConstant();
225 Node* UndefinedConstant();
226 Node* TheHoleConstant();
227 Node* FixedArrayMapConstant();
228
229 #define PURE_UNOP_DECL(Name) Node* Name(Node* input);
230 PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
231 #undef PURE_UNOP_DECL
232
233 #define BINOP_DECL(Name) Node* Name(Node* left, Node* right);
234 PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
235 CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
236 #undef BINOP_DECL
237
238 Node* Float64RoundDown(Node* value);
239
240 Node* ToNumber(Node* value);
241 Node* Allocate(PretenureFlag pretenure, Node* size);
242 Node* LoadField(FieldAccess const&, Node* object);
243 Node* LoadElement(ElementAccess const&, Node* object, Node* index);
244 Node* StoreField(FieldAccess const&, Node* object, Node* value);
245 Node* StoreElement(ElementAccess const&, Node* object, Node* index,
246 Node* value);
247
248 Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
249
250 Node* Retain(Node* buffer);
251 Node* UnsafePointerAdd(Node* base, Node* external);
252
253 Node* DeoptimizeIf(DeoptimizeReason reason, Node* condition,
254 Node* frame_state);
255 Node* DeoptimizeUnless(DeoptimizeReason reason, Node* condition,
256 Node* frame_state);
257 template <typename... Args>
258 Node* Call(const CallDescriptor* desc, Args... args);
259
260 // Basic control operations.
261 template <class LabelType>
262 void Bind(LabelType* label);
263
264 template <class LabelType, typename... vars>
265 void Goto(LabelType* label, vars...);
266
267 void Branch(Node* condition, GraphAssemblerStaticLabel<1>* if_true,
268 GraphAssemblerStaticLabel<1>* if_false);
269
270 // Control helpers.
271 // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
272 template <class LabelType, typename... vars>
273 void GotoIf(Node* condition, LabelType* label, vars...);
274
275 // {GotoUnless(c, l)} is equivalent to {Branch(c, templ, l);Bind(templ)}.
276 template <class LabelType, typename... vars>
277 void GotoUnless(Node* condition, LabelType* label, vars...);
278
279 // Extractors (should be only used when destructing/resetting the assembler).
280 Node* ExtractCurrentControl();
281 Node* ExtractCurrentEffect();
282
283 private:
284 template <class LabelType, typename... Vars>
285 void MergeState(LabelType label, Vars... vars);
286
287 Operator const* ToNumberOperator();
288
289 JSGraph* jsgraph() const { return jsgraph_; }
290 Graph* graph() const { return jsgraph_->graph(); }
291 Zone* temp_zone() const { return temp_zone_; }
292 CommonOperatorBuilder* common() const { return jsgraph()->common(); }
293 MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
294 SimplifiedOperatorBuilder* simplified() const {
295 return jsgraph()->simplified();
296 }
297
298 SetOncePointer<Operator const> to_number_operator_;
299 Zone* temp_zone_;
300 JSGraph* jsgraph_;
301 Node* current_effect_;
302 Node* current_control_;
303 };
304
305 template <size_t MergeCount, size_t VarCount>
306 Node* GraphAssemblerStaticLabel<MergeCount, VarCount>::PhiAt(size_t index) {
307 DCHECK(IsBound());
308 return GetBindingsPtrFor(index)[0];
309 }
310
311 template <class LabelType, typename... Vars>
312 void GraphAssembler::MergeState(LabelType label, Vars... vars) {
313 DCHECK(!label->IsBound());
314 size_t merged_count = label->MergedCount();
315 DCHECK_LT(merged_count, label->MaxMergeCount());
316 DCHECK_EQ(label->PhiCount(), sizeof...(vars));
317 label->GetEffectsPtr()[merged_count] = current_effect_;
318 label->GetControlsPtr()[merged_count] = current_control_;
319 // We need to start with nullptr to avoid 0-length arrays.
320 Node* var_array[] = {nullptr, vars...};
321 for (size_t i = 0; i < sizeof...(vars); i++) {
322 label->GetBindingsPtrFor(i)[merged_count] = var_array[i + 1];
Igor Sheludko 2017/01/02 13:23:27 I think it would be better to call here a setter t
Jarin 2017/01/03 09:27:55 Done.
323 }
324 label->IncrementMergedCount();
325 }
326
327 template <class LabelType>
328 void GraphAssembler::Bind(LabelType* label) {
329 DCHECK(current_control_ == nullptr);
330 DCHECK(current_effect_ == nullptr);
331 DCHECK(label->MaxMergeCount() > 0);
332 DCHECK_EQ(label->MaxMergeCount(), label->MergedCount());
333
334 int merge_count = static_cast<int>(label->MaxMergeCount());
335 if (merge_count == 1) {
336 current_control_ = label->GetControlsPtr()[0];
337 current_effect_ = label->GetEffectsPtr()[0];
338 label->SetBound();
339 return;
340 }
341
342 current_control_ = graph()->NewNode(common()->Merge(merge_count), merge_count,
343 label->GetControlsPtr());
344
345 Node** effects = label->GetEffectsPtr();
346 current_effect_ = effects[0];
347 for (size_t i = 1; i < label->MaxMergeCount(); i++) {
348 if (current_effect_ != effects[i]) {
349 effects[label->MaxMergeCount()] = current_control_;
350 current_effect_ = graph()->NewNode(common()->EffectPhi(merge_count),
351 merge_count + 1, effects);
352 break;
353 }
354 }
355
356 for (size_t var = 0; var < label->PhiCount(); var++) {
357 Node** bindings = label->GetBindingsPtrFor(var);
358 bindings[label->MaxMergeCount()] = current_control_;
359 bindings[0] = graph()->NewNode(
360 common()->Phi(label->GetRepresentationFor(var), merge_count),
361 merge_count + 1, bindings);
362 }
363
364 label->SetBound();
365 }
366
367 template <class LabelType, typename... Vars>
368 void GraphAssembler::Goto(LabelType* label, Vars... vars) {
369 DCHECK_NOT_NULL(current_control_);
370 DCHECK_NOT_NULL(current_effect_);
371 MergeState(label, vars...);
372 current_control_ = nullptr;
373 current_effect_ = nullptr;
374 }
375
376 template <class LabelType, typename... Vars>
377 void GraphAssembler::GotoIf(Node* condition, LabelType* label, Vars... vars) {
378 BranchHint hint =
379 label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone;
380 Node* branch =
381 graph()->NewNode(common()->Branch(hint), condition, current_control_);
382
383 current_control_ = graph()->NewNode(common()->IfTrue(), branch);
384 MergeState(label, vars...);
385
386 current_control_ = graph()->NewNode(common()->IfFalse(), branch);
387 }
388
389 template <class LabelType, typename... Vars>
390 void GraphAssembler::GotoUnless(Node* condition, LabelType* label,
391 Vars... vars) {
392 BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone;
393 Node* branch =
394 graph()->NewNode(common()->Branch(hint), condition, current_control_);
395
396 current_control_ = graph()->NewNode(common()->IfFalse(), branch);
397 MergeState(label, vars...);
398
399 current_control_ = graph()->NewNode(common()->IfTrue(), branch);
400 }
401
402 template <typename... Args>
403 Node* GraphAssembler::Call(const CallDescriptor* desc, Args... args) {
404 const Operator* op = common()->Call(desc);
405 Node* args_array[] = {args..., current_effect_, current_control_};
406 int size = static_cast<int>(sizeof...(args)) + op->EffectInputCount() +
407 op->ControlInputCount();
408 Node* call = graph()->NewNode(op, size, args_array);
409 DCHECK_EQ(0, op->ControlOutputCount());
410 current_effect_ = call;
411 return call;
412 }
413
414 } // namespace compiler
415 } // namespace internal
416 } // namespace v8
417
418 #endif // V8_COMPILER_GRAPH_ASSEMBLER_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698