V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
raw-machine-assembler.cc
1 // Copyright 2014 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 #include "src/compiler/raw-machine-assembler.h"
6 
7 #include "src/compiler/node-properties.h"
8 #include "src/compiler/pipeline.h"
9 #include "src/compiler/scheduler.h"
10 #include "src/heap/factory-inl.h"
11 
12 namespace v8 {
13 namespace internal {
14 namespace compiler {
15 
16 RawMachineAssembler::RawMachineAssembler(
17  Isolate* isolate, Graph* graph, CallDescriptor* call_descriptor,
18  MachineRepresentation word, MachineOperatorBuilder::Flags flags,
19  MachineOperatorBuilder::AlignmentRequirements alignment_requirements,
20  PoisoningMitigationLevel poisoning_level)
21  : isolate_(isolate),
22  graph_(graph),
23  schedule_(new (zone()) Schedule(zone())),
24  machine_(zone(), word, flags, alignment_requirements),
25  common_(zone()),
26  call_descriptor_(call_descriptor),
27  target_parameter_(nullptr),
28  parameters_(parameter_count(), zone()),
29  current_block_(schedule()->start()),
30  poisoning_level_(poisoning_level) {
31  int param_count = static_cast<int>(parameter_count());
32  // Add an extra input for the JSFunction parameter to the start node.
33  graph->SetStart(graph->NewNode(common_.Start(param_count + 1)));
34  if (call_descriptor->IsJSFunctionCall()) {
35  target_parameter_ = AddNode(
36  common()->Parameter(Linkage::kJSCallClosureParamIndex), graph->start());
37  }
38  for (size_t i = 0; i < parameter_count(); ++i) {
39  parameters_[i] =
40  AddNode(common()->Parameter(static_cast<int>(i)), graph->start());
41  }
42  graph->SetEnd(graph->NewNode(common_.End(0)));
43 }
44 
45 Node* RawMachineAssembler::NullConstant() {
46  return HeapConstant(isolate()->factory()->null_value());
47 }
48 
49 Node* RawMachineAssembler::UndefinedConstant() {
50  return HeapConstant(isolate()->factory()->undefined_value());
51 }
52 
53 Node* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value,
54  RelocInfo::Mode rmode) {
55  return kPointerSize == 8
56  ? RelocatableInt64Constant(value, rmode)
57  : RelocatableInt32Constant(static_cast<int>(value), rmode);
58 }
59 
60 Schedule* RawMachineAssembler::Export() {
61  // Compute the correct codegen order.
62  DCHECK(schedule_->rpo_order()->empty());
63  if (FLAG_trace_turbo_scheduler) {
64  PrintF("--- RAW SCHEDULE -------------------------------------------\n");
65  StdoutStream{} << *schedule_;
66  }
67  schedule_->EnsureCFGWellFormedness();
68  Scheduler::ComputeSpecialRPO(zone(), schedule_);
69  schedule_->PropagateDeferredMark();
70  if (FLAG_trace_turbo_scheduler) {
71  PrintF("--- EDGE SPLIT AND PROPAGATED DEFERRED SCHEDULE ------------\n");
72  StdoutStream{} << *schedule_;
73  }
74  // Invalidate RawMachineAssembler.
75  Schedule* schedule = schedule_;
76  schedule_ = nullptr;
77  return schedule;
78 }
79 
80 Graph* RawMachineAssembler::ExportForOptimization() {
81  // Compute the correct codegen order.
82  DCHECK(schedule_->rpo_order()->empty());
83  if (FLAG_trace_turbo_scheduler) {
84  PrintF("--- RAW SCHEDULE -------------------------------------------\n");
85  StdoutStream{} << *schedule_;
86  }
87  schedule_->EnsureCFGWellFormedness();
88  Scheduler::ComputeSpecialRPO(zone(), schedule_);
89  if (FLAG_trace_turbo_scheduler) {
90  PrintF("--- SCHEDULE BEFORE GRAPH CREATION -------------------------\n");
91  StdoutStream{} << *schedule_;
92  }
93  MakeReschedulable();
94  // Invalidate RawMachineAssembler.
95  schedule_ = nullptr;
96  return graph();
97 }
98 
99 void RawMachineAssembler::MakeReschedulable() {
100  std::vector<Node*> block_final_control(schedule_->all_blocks_.size());
101  std::vector<Node*> block_final_effect(schedule_->all_blocks_.size());
102 
103  struct LoopHeader {
104  BasicBlock* block;
105  Node* loop_node;
106  Node* effect_phi;
107  };
108  std::vector<LoopHeader> loop_headers;
109 
110  // These are hoisted outside of the loop to avoid re-allocation.
111  std::vector<Node*> merge_inputs;
112  std::vector<Node*> effect_phi_inputs;
113 
114  for (BasicBlock* block : *schedule_->rpo_order()) {
115  Node* current_control;
116  Node* current_effect;
117  if (block == schedule_->start()) {
118  current_control = current_effect = graph()->start();
119  } else if (block == schedule_->end()) {
120  for (size_t i = 0; i < block->PredecessorCount(); ++i) {
121  NodeProperties::MergeControlToEnd(
122  graph(), common(), block->PredecessorAt(i)->control_input());
123  }
124  } else if (block->IsLoopHeader()) {
125  // The graph()->start() inputs are just placeholders until we computed the
126  // real back-edges and re-structure the control flow so the loop has
127  // exactly two predecessors.
128  current_control = graph()->NewNode(common()->Loop(2), graph()->start(),
129  graph()->start());
130  current_effect =
131  graph()->NewNode(common()->EffectPhi(2), graph()->start(),
132  graph()->start(), current_control);
133 
134  Node* terminate = graph()->NewNode(common()->Terminate(), current_effect,
135  current_control);
136  NodeProperties::MergeControlToEnd(graph(), common(), terminate);
137  loop_headers.push_back(
138  LoopHeader{block, current_control, current_effect});
139  } else if (block->PredecessorCount() == 1) {
140  BasicBlock* predecessor = block->PredecessorAt(0);
141  DCHECK_LT(predecessor->rpo_number(), block->rpo_number());
142  current_effect = block_final_effect[predecessor->id().ToSize()];
143  current_control = block_final_control[predecessor->id().ToSize()];
144  } else {
145  // Create control merge nodes and effect phis for all predecessor blocks.
146  merge_inputs.clear();
147  effect_phi_inputs.clear();
148  int predecessor_count = static_cast<int>(block->PredecessorCount());
149  for (int i = 0; i < predecessor_count; ++i) {
150  BasicBlock* predecessor = block->PredecessorAt(i);
151  DCHECK_LT(predecessor->rpo_number(), block->rpo_number());
152  merge_inputs.push_back(block_final_control[predecessor->id().ToSize()]);
153  effect_phi_inputs.push_back(
154  block_final_effect[predecessor->id().ToSize()]);
155  }
156  current_control = graph()->NewNode(common()->Merge(predecessor_count),
157  static_cast<int>(merge_inputs.size()),
158  merge_inputs.data());
159  effect_phi_inputs.push_back(current_control);
160  current_effect = graph()->NewNode(
161  common()->EffectPhi(predecessor_count),
162  static_cast<int>(effect_phi_inputs.size()), effect_phi_inputs.data());
163  }
164 
165  auto update_current_control_and_effect = [&](Node* node) {
166  bool existing_effect_and_control =
167  IrOpcode::IsIfProjectionOpcode(node->opcode()) ||
168  IrOpcode::IsPhiOpcode(node->opcode());
169  if (node->op()->EffectInputCount() > 0) {
170  DCHECK_EQ(1, node->op()->EffectInputCount());
171  if (existing_effect_and_control) {
172  NodeProperties::ReplaceEffectInput(node, current_effect);
173  } else {
174  node->AppendInput(graph()->zone(), current_effect);
175  }
176  }
177  if (node->op()->ControlInputCount() > 0) {
178  DCHECK_EQ(1, node->op()->ControlInputCount());
179  if (existing_effect_and_control) {
180  NodeProperties::ReplaceControlInput(node, current_control);
181  } else {
182  node->AppendInput(graph()->zone(), current_control);
183  }
184  }
185  if (node->op()->EffectOutputCount() > 0) {
186  DCHECK_EQ(1, node->op()->EffectOutputCount());
187  current_effect = node;
188  }
189  if (node->op()->ControlOutputCount() > 0) {
190  current_control = node;
191  }
192  };
193 
194  for (Node* node : *block) {
195  update_current_control_and_effect(node);
196  }
197  if (block->deferred()) MarkControlDeferred(current_control);
198 
199  if (Node* block_terminator = block->control_input()) {
200  update_current_control_and_effect(block_terminator);
201  }
202 
203  block_final_effect[block->id().ToSize()] = current_effect;
204  block_final_control[block->id().ToSize()] = current_control;
205  }
206 
207  // Fix-up loop backedges and re-structure control flow so that loop nodes have
208  // exactly two control predecessors.
209  for (const LoopHeader& loop_header : loop_headers) {
210  BasicBlock* block = loop_header.block;
211  std::vector<BasicBlock*> loop_entries;
212  std::vector<BasicBlock*> loop_backedges;
213  for (size_t i = 0; i < block->PredecessorCount(); ++i) {
214  BasicBlock* predecessor = block->PredecessorAt(i);
215  if (block->LoopContains(predecessor)) {
216  loop_backedges.push_back(predecessor);
217  } else {
218  DCHECK(loop_backedges.empty());
219  loop_entries.push_back(predecessor);
220  }
221  }
222  DCHECK(!loop_entries.empty());
223  DCHECK(!loop_backedges.empty());
224 
225  int entrance_count = static_cast<int>(loop_entries.size());
226  int backedge_count = static_cast<int>(loop_backedges.size());
227  Node* control_loop_entry = CreateNodeFromPredecessors(
228  loop_entries, block_final_control, common()->Merge(entrance_count), {});
229  Node* control_backedge =
230  CreateNodeFromPredecessors(loop_backedges, block_final_control,
231  common()->Merge(backedge_count), {});
232  Node* effect_loop_entry = CreateNodeFromPredecessors(
233  loop_entries, block_final_effect, common()->EffectPhi(entrance_count),
234  {control_loop_entry});
235  Node* effect_backedge = CreateNodeFromPredecessors(
236  loop_backedges, block_final_effect, common()->EffectPhi(backedge_count),
237  {control_backedge});
238 
239  loop_header.loop_node->ReplaceInput(0, control_loop_entry);
240  loop_header.loop_node->ReplaceInput(1, control_backedge);
241  loop_header.effect_phi->ReplaceInput(0, effect_loop_entry);
242  loop_header.effect_phi->ReplaceInput(1, effect_backedge);
243 
244  for (Node* node : *block) {
245  if (node->opcode() == IrOpcode::kPhi) {
246  MakePhiBinary(node, static_cast<int>(loop_entries.size()),
247  control_loop_entry, control_backedge);
248  }
249  }
250  }
251 }
252 
253 Node* RawMachineAssembler::CreateNodeFromPredecessors(
254  const std::vector<BasicBlock*>& predecessors,
255  const std::vector<Node*>& sidetable, const Operator* op,
256  const std::vector<Node*>& additional_inputs) {
257  if (predecessors.size() == 1) {
258  return sidetable[predecessors.front()->id().ToSize()];
259  }
260  std::vector<Node*> inputs;
261  for (BasicBlock* predecessor : predecessors) {
262  inputs.push_back(sidetable[predecessor->id().ToSize()]);
263  }
264  for (Node* additional_input : additional_inputs) {
265  inputs.push_back(additional_input);
266  }
267  return graph()->NewNode(op, static_cast<int>(inputs.size()), inputs.data());
268 }
269 
270 void RawMachineAssembler::MakePhiBinary(Node* phi, int split_point,
271  Node* left_control,
272  Node* right_control) {
273  int value_count = phi->op()->ValueInputCount();
274  if (value_count == 2) return;
275  DCHECK_LT(split_point, value_count);
276  DCHECK_GT(split_point, 0);
277 
278  MachineRepresentation rep = PhiRepresentationOf(phi->op());
279  int left_input_count = split_point;
280  int right_input_count = value_count - split_point;
281 
282  Node* left_input;
283  if (left_input_count == 1) {
284  left_input = NodeProperties::GetValueInput(phi, 0);
285  } else {
286  std::vector<Node*> inputs;
287  for (int i = 0; i < left_input_count; ++i) {
288  inputs.push_back(NodeProperties::GetValueInput(phi, i));
289  }
290  inputs.push_back(left_control);
291  left_input =
292  graph()->NewNode(common()->Phi(rep, static_cast<int>(left_input_count)),
293  static_cast<int>(inputs.size()), inputs.data());
294  }
295 
296  Node* right_input;
297  if (right_input_count == 1) {
298  right_input = NodeProperties::GetValueInput(phi, split_point);
299  } else {
300  std::vector<Node*> inputs;
301  for (int i = split_point; i < value_count; ++i) {
302  inputs.push_back(NodeProperties::GetValueInput(phi, i));
303  }
304  inputs.push_back(right_control);
305  right_input = graph()->NewNode(
306  common()->Phi(rep, static_cast<int>(right_input_count)),
307  static_cast<int>(inputs.size()), inputs.data());
308  }
309 
310  Node* control = NodeProperties::GetControlInput(phi);
311  phi->TrimInputCount(3);
312  phi->ReplaceInput(0, left_input);
313  phi->ReplaceInput(1, right_input);
314  phi->ReplaceInput(2, control);
315  NodeProperties::ChangeOp(phi, common()->Phi(rep, 2));
316 }
317 
318 void RawMachineAssembler::MarkControlDeferred(Node* control_node) {
319  BranchHint new_branch_hint;
320  Node* responsible_branch = nullptr;
321  while (responsible_branch == nullptr) {
322  switch (control_node->opcode()) {
323  case IrOpcode::kIfException:
324  // IfException projections are deferred by default.
325  return;
326  case IrOpcode::kIfSuccess:
327  control_node = NodeProperties::GetControlInput(control_node);
328  continue;
329  case IrOpcode::kIfValue:
330  case IrOpcode::kIfDefault:
331  // Marking switch cases as deferred is currently impossible.
332  return;
333  case IrOpcode::kIfTrue: {
334  Node* branch = NodeProperties::GetControlInput(control_node);
335  BranchHint hint = BranchOperatorInfoOf(branch->op()).hint;
336  if (hint == BranchHint::kTrue) {
337  // The other possibility is also deferred, so the responsible branch
338  // has to be before.
339  control_node = NodeProperties::GetControlInput(branch);
340  continue;
341  }
342  new_branch_hint = BranchHint::kFalse;
343  responsible_branch = branch;
344  break;
345  }
346  case IrOpcode::kIfFalse: {
347  Node* branch = NodeProperties::GetControlInput(control_node);
348  BranchHint hint = BranchOperatorInfoOf(branch->op()).hint;
349  if (hint == BranchHint::kFalse) {
350  // The other possibility is also deferred, so the responsible branch
351  // has to be before.
352  control_node = NodeProperties::GetControlInput(branch);
353  continue;
354  }
355  new_branch_hint = BranchHint::kTrue;
356  responsible_branch = branch;
357  break;
358  }
359  case IrOpcode::kMerge:
360  for (int i = 0; i < control_node->op()->ControlInputCount(); ++i) {
361  MarkControlDeferred(NodeProperties::GetControlInput(control_node, i));
362  }
363  return;
364  case IrOpcode::kLoop:
365  control_node = NodeProperties::GetControlInput(control_node, 0);
366  continue;
367  case IrOpcode::kBranch:
368  case IrOpcode::kSwitch:
369  UNREACHABLE();
370  case IrOpcode::kStart:
371  return;
372  default:
373  DCHECK_EQ(1, control_node->op()->ControlInputCount());
374  control_node = NodeProperties::GetControlInput(control_node);
375  continue;
376  }
377  }
378 
379  BranchOperatorInfo info = BranchOperatorInfoOf(responsible_branch->op());
380  if (info.hint == new_branch_hint) return;
381  NodeProperties::ChangeOp(
382  responsible_branch,
383  common()->Branch(new_branch_hint, info.is_safety_check));
384 }
385 
386 Node* RawMachineAssembler::TargetParameter() {
387  DCHECK_NOT_NULL(target_parameter_);
388  return target_parameter_;
389 }
390 
391 Node* RawMachineAssembler::Parameter(size_t index) {
392  DCHECK(index < parameter_count());
393  return parameters_[index];
394 }
395 
396 
397 void RawMachineAssembler::Goto(RawMachineLabel* label) {
398  DCHECK(current_block_ != schedule()->end());
399  schedule()->AddGoto(CurrentBlock(), Use(label));
400  current_block_ = nullptr;
401 }
402 
403 
404 void RawMachineAssembler::Branch(Node* condition, RawMachineLabel* true_val,
405  RawMachineLabel* false_val) {
406  DCHECK(current_block_ != schedule()->end());
407  Node* branch = MakeNode(
408  common()->Branch(BranchHint::kNone, IsSafetyCheck::kNoSafetyCheck), 1,
409  &condition);
410  BasicBlock* true_block = schedule()->NewBasicBlock();
411  BasicBlock* false_block = schedule()->NewBasicBlock();
412  schedule()->AddBranch(CurrentBlock(), branch, true_block, false_block);
413 
414  true_block->AddNode(MakeNode(common()->IfTrue(), 1, &branch));
415  schedule()->AddGoto(true_block, Use(true_val));
416 
417  false_block->AddNode(MakeNode(common()->IfFalse(), 1, &branch));
418  schedule()->AddGoto(false_block, Use(false_val));
419 
420  current_block_ = nullptr;
421 }
422 
423 void RawMachineAssembler::Continuations(Node* call, RawMachineLabel* if_success,
424  RawMachineLabel* if_exception) {
425  DCHECK_NOT_NULL(schedule_);
426  DCHECK_NOT_NULL(current_block_);
427  schedule()->AddCall(CurrentBlock(), call, Use(if_success), Use(if_exception));
428  current_block_ = nullptr;
429 }
430 
431 void RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label,
432  const int32_t* case_values,
433  RawMachineLabel** case_labels,
434  size_t case_count) {
435  DCHECK_NE(schedule()->end(), current_block_);
436  size_t succ_count = case_count + 1;
437  Node* switch_node = MakeNode(common()->Switch(succ_count), 1, &index);
438  BasicBlock** succ_blocks = zone()->NewArray<BasicBlock*>(succ_count);
439  for (size_t index = 0; index < case_count; ++index) {
440  int32_t case_value = case_values[index];
441  BasicBlock* case_block = schedule()->NewBasicBlock();
442  Node* case_node =
443  graph()->NewNode(common()->IfValue(case_value), switch_node);
444  schedule()->AddNode(case_block, case_node);
445  schedule()->AddGoto(case_block, Use(case_labels[index]));
446  succ_blocks[index] = case_block;
447  }
448  BasicBlock* default_block = schedule()->NewBasicBlock();
449  Node* default_node = graph()->NewNode(common()->IfDefault(), switch_node);
450  schedule()->AddNode(default_block, default_node);
451  schedule()->AddGoto(default_block, Use(default_label));
452  succ_blocks[case_count] = default_block;
453  schedule()->AddSwitch(CurrentBlock(), switch_node, succ_blocks, succ_count);
454  current_block_ = nullptr;
455 }
456 
457 void RawMachineAssembler::Return(Node* value) {
458  Node* values[] = {Int32Constant(0), value};
459  Node* ret = MakeNode(common()->Return(1), 2, values);
460  schedule()->AddReturn(CurrentBlock(), ret);
461  current_block_ = nullptr;
462 }
463 
464 void RawMachineAssembler::Return(Node* v1, Node* v2) {
465  Node* values[] = {Int32Constant(0), v1, v2};
466  Node* ret = MakeNode(common()->Return(2), 3, values);
467  schedule()->AddReturn(CurrentBlock(), ret);
468  current_block_ = nullptr;
469 }
470 
471 void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
472  Node* values[] = {Int32Constant(0), v1, v2, v3};
473  Node* ret = MakeNode(common()->Return(3), 4, values);
474  schedule()->AddReturn(CurrentBlock(), ret);
475  current_block_ = nullptr;
476 }
477 
478 void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3, Node* v4) {
479  Node* values[] = {Int32Constant(0), v1, v2, v3, v4};
480  Node* ret = MakeNode(common()->Return(4), 5, values);
481  schedule()->AddReturn(CurrentBlock(), ret);
482  current_block_ = nullptr;
483 }
484 
485 void RawMachineAssembler::Return(int count, Node* vs[]) {
486  typedef Node* Node_ptr;
487  Node** values = new Node_ptr[count + 1];
488  values[0] = Int32Constant(0);
489  for (int i = 0; i < count; ++i) values[i + 1] = vs[i];
490  Node* ret = MakeNode(common()->Return(count), count + 1, values);
491  schedule()->AddReturn(CurrentBlock(), ret);
492  current_block_ = nullptr;
493  delete[] values;
494 }
495 
496 void RawMachineAssembler::PopAndReturn(Node* pop, Node* value) {
497  Node* values[] = {pop, value};
498  Node* ret = MakeNode(common()->Return(1), 2, values);
499  schedule()->AddReturn(CurrentBlock(), ret);
500  current_block_ = nullptr;
501 }
502 
503 void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2) {
504  Node* values[] = {pop, v1, v2};
505  Node* ret = MakeNode(common()->Return(2), 3, values);
506  schedule()->AddReturn(CurrentBlock(), ret);
507  current_block_ = nullptr;
508 }
509 
510 void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2,
511  Node* v3) {
512  Node* values[] = {pop, v1, v2, v3};
513  Node* ret = MakeNode(common()->Return(3), 4, values);
514  schedule()->AddReturn(CurrentBlock(), ret);
515  current_block_ = nullptr;
516 }
517 
518 void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2, Node* v3,
519  Node* v4) {
520  Node* values[] = {pop, v1, v2, v3, v4};
521  Node* ret = MakeNode(common()->Return(4), 5, values);
522  schedule()->AddReturn(CurrentBlock(), ret);
523  current_block_ = nullptr;
524 }
525 
526 void RawMachineAssembler::DebugAbort(Node* message) {
527  AddNode(machine()->DebugAbort(), message);
528 }
529 
530 void RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); }
531 
532 void RawMachineAssembler::Unreachable() {
533  Node* ret = MakeNode(common()->Throw(), 0, nullptr);
534  schedule()->AddThrow(CurrentBlock(), ret);
535  current_block_ = nullptr;
536 }
537 
538 void RawMachineAssembler::Comment(const char* msg) {
539  AddNode(machine()->Comment(msg));
540 }
541 
542 Node* RawMachineAssembler::CallN(CallDescriptor* call_descriptor,
543  int input_count, Node* const* inputs) {
544  DCHECK(!call_descriptor->NeedsFrameState());
545  // +1 is for target.
546  DCHECK_EQ(input_count, call_descriptor->ParameterCount() + 1);
547  return AddNode(common()->Call(call_descriptor), input_count, inputs);
548 }
549 
550 Node* RawMachineAssembler::CallNWithFrameState(CallDescriptor* call_descriptor,
551  int input_count,
552  Node* const* inputs) {
553  DCHECK(call_descriptor->NeedsFrameState());
554  // +2 is for target and frame state.
555  DCHECK_EQ(input_count, call_descriptor->ParameterCount() + 2);
556  return AddNode(common()->Call(call_descriptor), input_count, inputs);
557 }
558 
559 Node* RawMachineAssembler::TailCallN(CallDescriptor* call_descriptor,
560  int input_count, Node* const* inputs) {
561  // +1 is for target.
562  DCHECK_EQ(input_count, call_descriptor->ParameterCount() + 1);
563  Node* tail_call =
564  MakeNode(common()->TailCall(call_descriptor), input_count, inputs);
565  schedule()->AddTailCall(CurrentBlock(), tail_call);
566  current_block_ = nullptr;
567  return tail_call;
568 }
569 
570 Node* RawMachineAssembler::CallCFunction0(MachineType return_type,
571  Node* function) {
572  MachineSignature::Builder builder(zone(), 1, 0);
573  builder.AddReturn(return_type);
574  auto call_descriptor =
575  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
576 
577  return AddNode(common()->Call(call_descriptor), function);
578 }
579 
580 
581 Node* RawMachineAssembler::CallCFunction1(MachineType return_type,
582  MachineType arg0_type, Node* function,
583  Node* arg0) {
584  MachineSignature::Builder builder(zone(), 1, 1);
585  builder.AddReturn(return_type);
586  builder.AddParam(arg0_type);
587  auto call_descriptor =
588  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
589 
590  return AddNode(common()->Call(call_descriptor), function, arg0);
591 }
592 
593 Node* RawMachineAssembler::CallCFunction1WithCallerSavedRegisters(
594  MachineType return_type, MachineType arg0_type, Node* function, Node* arg0,
595  SaveFPRegsMode mode) {
596  MachineSignature::Builder builder(zone(), 1, 1);
597  builder.AddReturn(return_type);
598  builder.AddParam(arg0_type);
599  auto call_descriptor =
600  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
601 
602  call_descriptor->set_save_fp_mode(mode);
603 
604  return AddNode(common()->CallWithCallerSavedRegisters(call_descriptor),
605  function, arg0);
606 }
607 
608 Node* RawMachineAssembler::CallCFunction2(MachineType return_type,
609  MachineType arg0_type,
610  MachineType arg1_type, Node* function,
611  Node* arg0, Node* arg1) {
612  MachineSignature::Builder builder(zone(), 1, 2);
613  builder.AddReturn(return_type);
614  builder.AddParam(arg0_type);
615  builder.AddParam(arg1_type);
616  auto call_descriptor =
617  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
618 
619  return AddNode(common()->Call(call_descriptor), function, arg0, arg1);
620 }
621 
622 Node* RawMachineAssembler::CallCFunction3(MachineType return_type,
623  MachineType arg0_type,
624  MachineType arg1_type,
625  MachineType arg2_type, Node* function,
626  Node* arg0, Node* arg1, Node* arg2) {
627  MachineSignature::Builder builder(zone(), 1, 3);
628  builder.AddReturn(return_type);
629  builder.AddParam(arg0_type);
630  builder.AddParam(arg1_type);
631  builder.AddParam(arg2_type);
632  auto call_descriptor =
633  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
634 
635  return AddNode(common()->Call(call_descriptor), function, arg0, arg1, arg2);
636 }
637 
638 Node* RawMachineAssembler::CallCFunction3WithCallerSavedRegisters(
639  MachineType return_type, MachineType arg0_type, MachineType arg1_type,
640  MachineType arg2_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
641  SaveFPRegsMode mode) {
642  MachineSignature::Builder builder(zone(), 1, 3);
643  builder.AddReturn(return_type);
644  builder.AddParam(arg0_type);
645  builder.AddParam(arg1_type);
646  builder.AddParam(arg2_type);
647  auto call_descriptor =
648  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
649 
650  call_descriptor->set_save_fp_mode(mode);
651 
652  return AddNode(common()->CallWithCallerSavedRegisters(call_descriptor),
653  function, arg0, arg1, arg2);
654 }
655 
656 Node* RawMachineAssembler::CallCFunction4(
657  MachineType return_type, MachineType arg0_type, MachineType arg1_type,
658  MachineType arg2_type, MachineType arg3_type, Node* function, Node* arg0,
659  Node* arg1, Node* arg2, Node* arg3) {
660  MachineSignature::Builder builder(zone(), 1, 4);
661  builder.AddReturn(return_type);
662  builder.AddParam(arg0_type);
663  builder.AddParam(arg1_type);
664  builder.AddParam(arg2_type);
665  builder.AddParam(arg3_type);
666  auto call_descriptor =
667  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
668 
669  return AddNode(common()->Call(call_descriptor), function, arg0, arg1, arg2,
670  arg3);
671 }
672 
673 Node* RawMachineAssembler::CallCFunction5(
674  MachineType return_type, MachineType arg0_type, MachineType arg1_type,
675  MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
676  Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3,
677  Node* arg4) {
678  MachineSignature::Builder builder(zone(), 1, 5);
679  builder.AddReturn(return_type);
680  builder.AddParam(arg0_type);
681  builder.AddParam(arg1_type);
682  builder.AddParam(arg2_type);
683  builder.AddParam(arg3_type);
684  builder.AddParam(arg4_type);
685  auto call_descriptor =
686  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
687 
688  return AddNode(common()->Call(call_descriptor), function, arg0, arg1, arg2,
689  arg3, arg4);
690 }
691 
692 Node* RawMachineAssembler::CallCFunction6(
693  MachineType return_type, MachineType arg0_type, MachineType arg1_type,
694  MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
695  MachineType arg5_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
696  Node* arg3, Node* arg4, Node* arg5) {
697  MachineSignature::Builder builder(zone(), 1, 6);
698  builder.AddReturn(return_type);
699  builder.AddParam(arg0_type);
700  builder.AddParam(arg1_type);
701  builder.AddParam(arg2_type);
702  builder.AddParam(arg3_type);
703  builder.AddParam(arg4_type);
704  builder.AddParam(arg5_type);
705  auto call_descriptor =
706  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
707 
708  return AddNode(common()->Call(call_descriptor), function, arg0, arg1, arg2,
709  arg3, arg4, arg5);
710 }
711 
712 Node* RawMachineAssembler::CallCFunction8(
713  MachineType return_type, MachineType arg0_type, MachineType arg1_type,
714  MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
715  MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
716  Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
717  Node* arg5, Node* arg6, Node* arg7) {
718  MachineSignature::Builder builder(zone(), 1, 8);
719  builder.AddReturn(return_type);
720  builder.AddParam(arg0_type);
721  builder.AddParam(arg1_type);
722  builder.AddParam(arg2_type);
723  builder.AddParam(arg3_type);
724  builder.AddParam(arg4_type);
725  builder.AddParam(arg5_type);
726  builder.AddParam(arg6_type);
727  builder.AddParam(arg7_type);
728  Node* args[] = {function, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7};
729  auto call_descriptor =
730  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
731  return AddNode(common()->Call(call_descriptor), arraysize(args), args);
732 }
733 
734 Node* RawMachineAssembler::CallCFunction9(
735  MachineType return_type, MachineType arg0_type, MachineType arg1_type,
736  MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
737  MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
738  MachineType arg8_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
739  Node* arg3, Node* arg4, Node* arg5, Node* arg6, Node* arg7, Node* arg8) {
740  MachineSignature::Builder builder(zone(), 1, 9);
741  builder.AddReturn(return_type);
742  builder.AddParam(arg0_type);
743  builder.AddParam(arg1_type);
744  builder.AddParam(arg2_type);
745  builder.AddParam(arg3_type);
746  builder.AddParam(arg4_type);
747  builder.AddParam(arg5_type);
748  builder.AddParam(arg6_type);
749  builder.AddParam(arg7_type);
750  builder.AddParam(arg8_type);
751  Node* args[] = {function, arg0, arg1, arg2, arg3,
752  arg4, arg5, arg6, arg7, arg8};
753  auto call_descriptor =
754  Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
755  return AddNode(common()->Call(call_descriptor), arraysize(args), args);
756 }
757 
758 BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
759  label->used_ = true;
760  return EnsureBlock(label);
761 }
762 
763 BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
764  if (label->block_ == nullptr) {
765  label->block_ = schedule()->NewBasicBlock();
766  }
767  return label->block_;
768 }
769 
770 void RawMachineAssembler::Bind(RawMachineLabel* label) {
771  DCHECK_NULL(current_block_);
772  DCHECK(!label->bound_);
773  label->bound_ = true;
774  current_block_ = EnsureBlock(label);
775  current_block_->set_deferred(label->deferred_);
776 }
777 
778 #if DEBUG
779 void RawMachineAssembler::Bind(RawMachineLabel* label,
780  AssemblerDebugInfo info) {
781  if (current_block_ != nullptr) {
782  std::stringstream str;
783  str << "Binding label without closing previous block:"
784  << "\n# label: " << info
785  << "\n# previous block: " << *current_block_;
786  FATAL("%s", str.str().c_str());
787  }
788  Bind(label);
789  current_block_->set_debug_info(info);
790 }
791 
792 void RawMachineAssembler::PrintCurrentBlock(std::ostream& os) {
793  os << CurrentBlock();
794 }
795 
796 void RawMachineAssembler::SetInitialDebugInformation(
797  AssemblerDebugInfo debug_info) {
798  CurrentBlock()->set_debug_info(debug_info);
799 }
800 #endif // DEBUG
801 
802 bool RawMachineAssembler::InsideBlock() { return current_block_ != nullptr; }
803 
804 BasicBlock* RawMachineAssembler::CurrentBlock() {
805  DCHECK(current_block_);
806  return current_block_;
807 }
808 
809 Node* RawMachineAssembler::Phi(MachineRepresentation rep, int input_count,
810  Node* const* inputs) {
811  Node** buffer = new (zone()->New(sizeof(Node*) * (input_count + 1)))
812  Node*[input_count + 1];
813  std::copy(inputs, inputs + input_count, buffer);
814  buffer[input_count] = graph()->start();
815  return AddNode(common()->Phi(rep, input_count), input_count + 1, buffer);
816 }
817 
818 void RawMachineAssembler::AppendPhiInput(Node* phi, Node* new_input) {
819  const Operator* op = phi->op();
820  const Operator* new_op = common()->ResizeMergeOrPhi(op, phi->InputCount());
821  phi->InsertInput(zone(), phi->InputCount() - 1, new_input);
822  NodeProperties::ChangeOp(phi, new_op);
823 }
824 
825 Node* RawMachineAssembler::AddNode(const Operator* op, int input_count,
826  Node* const* inputs) {
827  DCHECK_NOT_NULL(schedule_);
828  DCHECK_NOT_NULL(current_block_);
829  Node* node = MakeNode(op, input_count, inputs);
830  schedule()->AddNode(CurrentBlock(), node);
831  return node;
832 }
833 
834 Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
835  Node* const* inputs) {
836  // The raw machine assembler nodes do not have effect and control inputs,
837  // so we disable checking input counts here.
838  return graph()->NewNodeUnchecked(op, input_count, inputs);
839 }
840 
841 RawMachineLabel::~RawMachineLabel() {
842 #if DEBUG
843  if (bound_ == used_) return;
844  std::stringstream str;
845  if (bound_) {
846  str << "A label has been bound but it's not used."
847  << "\n# label: " << *block_;
848  } else {
849  str << "A label has been used but it's not bound.";
850  }
851  FATAL("%s", str.str().c_str());
852 #endif // DEBUG
853 }
854 
855 } // namespace compiler
856 } // namespace internal
857 } // namespace v8
Definition: libplatform.h:13