5 #ifndef V8_COMPILER_GRAPH_ASSEMBLER_H_ 6 #define V8_COMPILER_GRAPH_ASSEMBLER_H_ 8 #include "src/compiler/js-graph.h" 9 #include "src/compiler/node.h" 10 #include "src/compiler/simplified-operator.h" 11 #include "src/vector-slot-pair.h" 21 #define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \ 22 V(ChangeInt32ToInt64) \ 23 V(ChangeInt32ToFloat64) \ 24 V(ChangeInt64ToFloat64) \ 25 V(ChangeUint32ToFloat64) \ 26 V(ChangeUint32ToUint64) \ 27 V(ChangeFloat64ToInt32) \ 28 V(ChangeFloat64ToInt64) \ 29 V(ChangeFloat64ToUint32) \ 30 V(TruncateInt64ToInt32) \ 31 V(RoundFloat64ToInt32) \ 32 V(TruncateFloat64ToInt64) \ 33 V(TruncateFloat64ToWord32) \ 34 V(Float64ExtractLowWord32) \ 35 V(Float64ExtractHighWord32) \ 36 V(BitcastInt32ToFloat32) \ 37 V(BitcastInt64ToFloat64) \ 38 V(BitcastFloat32ToInt32) \ 39 V(BitcastFloat64ToInt64) \ 41 V(Word32ReverseBytes) \ 44 #define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \ 62 V(Int32LessThanOrEqual) \ 64 V(Uint32LessThanOrEqual) \ 66 V(Uint64LessThanOrEqual) \ 74 V(Float64LessThanOrEqual) \ 75 V(Float64InsertLowWord32) \ 76 V(Float64InsertHighWord32) \ 81 #define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V) \ 82 V(Int32AddWithOverflow) \ 83 V(Int32SubWithOverflow) \ 84 V(Int32MulWithOverflow) \ 90 #define JSGRAPH_SINGLETON_CONSTANT_LIST(V) \ 94 V(BooleanMapConstant) \ 95 V(HeapNumberMapConstant) \ 96 V(NoContextConstant) \ 97 V(EmptyStringConstant) \ 98 V(UndefinedConstant) \ 100 V(FixedArrayMapConstant) \ 101 V(FixedDoubleArrayMapConstant) \ 102 V(ToNumberBuiltinConstant) \ 103 V(AllocateInNewSpaceStubConstant) \ 104 V(AllocateInOldSpaceStubConstant) 106 class GraphAssembler;
108 enum class GraphAssemblerLabelType { kDeferred, kNonDeferred, kLoop };
111 template <
size_t VarCount>
114 Node* PhiAt(
size_t index);
116 template <
typename... Reps>
119 STATIC_ASSERT(VarCount ==
sizeof...(reps));
120 MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
122 for (
size_t i = 0;
i < VarCount;
i++) {
123 representations_[
i] = reps_array[
i + 1];
136 bool IsBound()
const {
return is_bound_; }
137 bool IsDeferred()
const {
138 return type_ == GraphAssemblerLabelType::kDeferred;
140 bool IsLoop()
const {
return type_ == GraphAssemblerLabelType::kLoop; }
142 bool is_bound_ =
false;
143 GraphAssemblerLabelType
const type_;
144 size_t merged_count_ = 0;
147 Node* bindings_[VarCount + 1];
148 MachineRepresentation representations_[VarCount + 1];
155 void Reset(
Node* effect,
Node* control);
158 template <
typename... Reps>
160 GraphAssemblerLabelType
type, Reps... reps) {
165 template <
typename... Reps>
167 return MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, reps...);
171 template <
typename... Reps>
173 return MakeLabelFor(GraphAssemblerLabelType::kLoop, reps...);
177 template <
typename... Reps>
179 return MakeLabelFor(GraphAssemblerLabelType::kDeferred, reps...);
183 Node* IntPtrConstant(intptr_t value);
184 Node* Uint32Constant(int32_t value);
185 Node* Int32Constant(int32_t value);
187 Node* UniqueIntPtrConstant(intptr_t value);
188 Node* SmiConstant(int32_t value);
189 Node* Float64Constant(
double value);
190 Node* Projection(
int index,
Node* value);
192 Node* CEntryStubConstant(
int result_size);
195 Node* LoadFramePointer();
197 #define SINGLETON_CONST_DECL(Name) Node* Name(); 198 JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
199 #undef SINGLETON_CONST_DECL 201 #define PURE_UNOP_DECL(Name) Node* Name(Node* input); 202 PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
203 #undef PURE_UNOP_DECL 205 #define BINOP_DECL(Name) Node* Name(Node* left, Node* right); 206 PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
207 CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
215 Node* Float64RoundDown(
Node* value);
216 Node* Float64RoundTruncate(
Node* value);
219 Node* BitcastWordToTagged(
Node* value);
220 Node* Allocate(PretenureFlag pretenure,
Node* size);
230 Node* StoreUnaligned(MachineRepresentation rep,
Node*
object,
Node* offset,
237 Node* Word32PoisonOnSpeculation(
Node* value);
242 IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
243 Node* DeoptimizeIfNot(
246 IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
247 template <
typename... Args>
249 template <
typename... Args>
253 template <
size_t VarCount>
256 template <
typename... Vars>
261 IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
265 template <
typename... Vars>
270 template <
typename... Vars>
275 Node* ExtractCurrentControl();
276 Node* ExtractCurrentEffect();
279 template <
typename... Vars>
284 JSGraph* jsgraph()
const {
return jsgraph_; }
285 Isolate* isolate()
const {
return jsgraph_->isolate(); }
286 Graph* graph()
const {
return jsgraph_->graph(); }
287 Zone* temp_zone()
const {
return temp_zone_; }
291 return jsgraph()->simplified();
297 Node* current_effect_;
298 Node* current_control_;
301 template <
size_t VarCount>
304 DCHECK_LT(index, VarCount);
305 return bindings_[index];
308 template <
typename... Vars>
309 void GraphAssembler::MergeState(GraphAssemblerLabel<
sizeof...(Vars)>* label,
311 int merged_count =
static_cast<int>(label->merged_count_);
312 Node* var_array[] = {
nullptr, vars...};
313 if (label->IsLoop()) {
314 if (merged_count == 0) {
315 DCHECK(!label->IsBound());
316 label->control_ = graph()->NewNode(common()->Loop(2), current_control_,
318 label->effect_ = graph()->NewNode(common()->EffectPhi(2), current_effect_,
319 current_effect_, label->control_);
320 Node* terminate = graph()->NewNode(common()->Terminate(), label->effect_,
322 NodeProperties::MergeControlToEnd(graph(), common(), terminate);
323 for (
size_t i = 0;
i <
sizeof...(vars);
i++) {
324 label->bindings_[
i] = graph()->NewNode(
325 common()->Phi(label->representations_[
i], 2), var_array[
i + 1],
326 var_array[
i + 1], label->control_);
329 DCHECK(label->IsBound());
330 DCHECK_EQ(1, merged_count);
331 label->control_->ReplaceInput(1, current_control_);
332 label->effect_->ReplaceInput(1, current_effect_);
333 for (
size_t i = 0;
i <
sizeof...(vars);
i++) {
334 label->bindings_[
i]->ReplaceInput(1, var_array[
i + 1]);
338 DCHECK(!label->IsBound());
339 if (merged_count == 0) {
341 DCHECK(!label->IsBound());
342 label->control_ = current_control_;
343 label->effect_ = current_effect_;
344 for (
size_t i = 0;
i <
sizeof...(vars);
i++) {
345 label->bindings_[
i] = var_array[
i + 1];
347 }
else if (merged_count == 1) {
349 label->control_ = graph()->NewNode(common()->Merge(2), label->control_,
351 label->effect_ = graph()->NewNode(common()->EffectPhi(2), label->effect_,
352 current_effect_, label->control_);
353 for (
size_t i = 0;
i <
sizeof...(vars);
i++) {
354 label->bindings_[
i] = graph()->NewNode(
355 common()->Phi(label->representations_[
i], 2), label->bindings_[
i],
356 var_array[
i + 1], label->control_);
360 DCHECK_EQ(IrOpcode::kMerge, label->control_->opcode());
361 label->control_->AppendInput(graph()->zone(), current_control_);
362 NodeProperties::ChangeOp(label->control_,
363 common()->Merge(merged_count + 1));
365 DCHECK_EQ(IrOpcode::kEffectPhi, label->effect_->opcode());
366 label->effect_->ReplaceInput(merged_count, current_effect_);
367 label->effect_->AppendInput(graph()->zone(), label->control_);
368 NodeProperties::ChangeOp(label->effect_,
369 common()->EffectPhi(merged_count + 1));
371 for (
size_t i = 0;
i <
sizeof...(vars);
i++) {
372 DCHECK_EQ(IrOpcode::kPhi, label->bindings_[
i]->opcode());
373 label->bindings_[
i]->ReplaceInput(merged_count, var_array[
i + 1]);
374 label->bindings_[
i]->AppendInput(graph()->zone(), label->control_);
375 NodeProperties::ChangeOp(
377 common()->Phi(label->representations_[
i], merged_count + 1));
381 label->merged_count_++;
384 template <
size_t VarCount>
385 void GraphAssembler::Bind(GraphAssemblerLabel<VarCount>* label) {
386 DCHECK_NULL(current_control_);
387 DCHECK_NULL(current_effect_);
388 DCHECK_LT(0, label->merged_count_);
390 current_control_ = label->control_;
391 current_effect_ = label->effect_;
396 template <
typename... Vars>
397 void GraphAssembler::Goto(GraphAssemblerLabel<
sizeof...(Vars)>* label,
399 DCHECK_NOT_NULL(current_control_);
400 DCHECK_NOT_NULL(current_effect_);
401 MergeState(label, vars...);
402 current_control_ =
nullptr;
403 current_effect_ =
nullptr;
406 template <
typename... Vars>
407 void GraphAssembler::GotoIf(Node* condition,
408 GraphAssemblerLabel<
sizeof...(Vars)>* label,
411 label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone;
413 graph()->NewNode(common()->Branch(hint), condition, current_control_);
415 current_control_ = graph()->NewNode(common()->IfTrue(), branch);
416 MergeState(label, vars...);
418 current_control_ = graph()->NewNode(common()->IfFalse(), branch);
421 template <
typename... Vars>
422 void GraphAssembler::GotoIfNot(Node* condition,
423 GraphAssemblerLabel<
sizeof...(Vars)>* label,
425 BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone;
427 graph()->NewNode(common()->Branch(hint), condition, current_control_);
429 current_control_ = graph()->NewNode(common()->IfFalse(), branch);
430 MergeState(label, vars...);
432 current_control_ = graph()->NewNode(common()->IfTrue(), branch);
435 template <
typename... Args>
436 Node* GraphAssembler::Call(
const CallDescriptor* call_descriptor,
438 const Operator* op = common()->Call(call_descriptor);
439 return Call(op, args...);
442 template <
typename... Args>
443 Node* GraphAssembler::Call(
const Operator* op, Args... args) {
444 DCHECK_EQ(IrOpcode::kCall, op->opcode());
445 Node* args_array[] = {args..., current_effect_, current_control_};
446 int size =
static_cast<int>(
sizeof...(args)) + op->EffectInputCount() +
447 op->ControlInputCount();
448 Node* call = graph()->NewNode(op, size, args_array);
449 DCHECK_EQ(0, op->ControlOutputCount());
450 current_effect_ = call;
458 #endif // V8_COMPILER_GRAPH_ASSEMBLER_H_