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