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/node-properties.h"
8 : #include "src/compiler/pipeline.h"
9 : #include "src/compiler/scheduler.h"
10 : #include "src/factory-inl.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace compiler {
15 :
16 269019 : RawMachineAssembler::RawMachineAssembler(
17 522061 : Isolate* isolate, Graph* graph, CallDescriptor* call_descriptor,
18 : MachineRepresentation word, MachineOperatorBuilder::Flags flags,
19 1329118 : MachineOperatorBuilder::AlignmentRequirements alignment_requirements)
20 : : isolate_(isolate),
21 : graph_(graph),
22 269019 : schedule_(new (zone()) Schedule(zone())),
23 : machine_(zone(), word, flags, alignment_requirements),
24 : common_(zone()),
25 : call_descriptor_(call_descriptor),
26 : parameters_(parameter_count(), zone()),
27 1345095 : current_block_(schedule()->start()) {
28 269019 : int param_count = static_cast<int>(parameter_count());
29 : // Add an extra input for the JSFunction parameter to the start node.
30 269019 : graph->SetStart(graph->NewNode(common_.Start(param_count + 1)));
31 1582160 : for (size_t i = 0; i < parameter_count(); ++i) {
32 522061 : parameters_[i] =
33 1044122 : AddNode(common()->Parameter(static_cast<int>(i)), graph->start());
34 : }
35 269019 : graph->SetEnd(graph->NewNode(common_.End(0)));
36 269019 : }
37 :
38 0 : Node* RawMachineAssembler::NullConstant() {
39 0 : return HeapConstant(isolate()->factory()->null_value());
40 : }
41 :
42 5 : Node* RawMachineAssembler::UndefinedConstant() {
43 5 : return HeapConstant(isolate()->factory()->undefined_value());
44 : }
45 :
46 276 : Node* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value,
47 : RelocInfo::Mode rmode) {
48 : return kPointerSize == 8
49 : ? RelocatableInt64Constant(value, rmode)
50 276 : : RelocatableInt32Constant(static_cast<int>(value), rmode);
51 : }
52 :
53 265724 : Schedule* RawMachineAssembler::Export() {
54 : // Compute the correct codegen order.
55 : DCHECK(schedule_->rpo_order()->empty());
56 265724 : OFStream os(stdout);
57 265724 : if (FLAG_trace_turbo_scheduler) {
58 0 : PrintF("--- RAW SCHEDULE -------------------------------------------\n");
59 0 : os << *schedule_;
60 : }
61 265724 : schedule_->EnsureCFGWellFormedness();
62 531448 : Scheduler::ComputeSpecialRPO(zone(), schedule_);
63 265724 : schedule_->PropagateDeferredMark();
64 265724 : if (FLAG_trace_turbo_scheduler) {
65 0 : PrintF("--- EDGE SPLIT AND PROPAGATED DEFERRED SCHEDULE ------------\n");
66 0 : os << *schedule_;
67 : }
68 : // Invalidate RawMachineAssembler.
69 265724 : Schedule* schedule = schedule_;
70 265724 : schedule_ = nullptr;
71 265724 : return schedule;
72 : }
73 :
74 :
75 264070 : Node* RawMachineAssembler::Parameter(size_t index) {
76 : DCHECK(index < parameter_count());
77 528140 : return parameters_[index];
78 : }
79 :
80 :
81 826302 : void RawMachineAssembler::Goto(RawMachineLabel* label) {
82 : DCHECK(current_block_ != schedule()->end());
83 413151 : schedule()->AddGoto(CurrentBlock(), Use(label));
84 413151 : current_block_ = nullptr;
85 413151 : }
86 :
87 :
88 589197 : void RawMachineAssembler::Branch(Node* condition, RawMachineLabel* true_val,
89 589197 : RawMachineLabel* false_val) {
90 : DCHECK(current_block_ != schedule()->end());
91 589197 : Node* branch = MakeNode(common()->Branch(), 1, &condition);
92 589197 : schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
93 589197 : current_block_ = nullptr;
94 589197 : }
95 :
96 1791 : void RawMachineAssembler::Continuations(Node* call, RawMachineLabel* if_success,
97 1791 : RawMachineLabel* if_exception) {
98 : DCHECK_NOT_NULL(schedule_);
99 : DCHECK_NOT_NULL(current_block_);
100 1791 : schedule()->AddCall(CurrentBlock(), call, Use(if_success), Use(if_exception));
101 1791 : current_block_ = nullptr;
102 1791 : }
103 :
104 4254 : void RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label,
105 : const int32_t* case_values,
106 : RawMachineLabel** case_labels,
107 155066 : size_t case_count) {
108 : DCHECK_NE(schedule()->end(), current_block_);
109 4254 : size_t succ_count = case_count + 1;
110 4254 : Node* switch_node = AddNode(common()->Switch(succ_count), index);
111 : BasicBlock** succ_blocks = zone()->NewArray<BasicBlock*>(succ_count);
112 37703 : for (size_t index = 0; index < case_count; ++index) {
113 33449 : int32_t case_value = case_values[index];
114 33449 : BasicBlock* case_block = schedule()->NewBasicBlock();
115 : Node* case_node =
116 33449 : graph()->NewNode(common()->IfValue(case_value), switch_node);
117 33449 : schedule()->AddNode(case_block, case_node);
118 66898 : schedule()->AddGoto(case_block, Use(case_labels[index]));
119 33449 : succ_blocks[index] = case_block;
120 : }
121 4254 : BasicBlock* default_block = schedule()->NewBasicBlock();
122 4254 : Node* default_node = graph()->NewNode(common()->IfDefault(), switch_node);
123 4254 : schedule()->AddNode(default_block, default_node);
124 4254 : schedule()->AddGoto(default_block, Use(default_label));
125 4254 : succ_blocks[case_count] = default_block;
126 4254 : schedule()->AddSwitch(CurrentBlock(), switch_node, succ_blocks, succ_count);
127 4254 : current_block_ = nullptr;
128 4254 : }
129 :
130 554210 : void RawMachineAssembler::Return(Node* value) {
131 277105 : Node* values[] = {Int32Constant(0), value};
132 277105 : Node* ret = MakeNode(common()->Return(1), 2, values);
133 277105 : schedule()->AddReturn(CurrentBlock(), ret);
134 277105 : current_block_ = nullptr;
135 277105 : }
136 :
137 :
138 0 : void RawMachineAssembler::Return(Node* v1, Node* v2) {
139 0 : Node* values[] = {Int32Constant(0), v1, v2};
140 0 : Node* ret = MakeNode(common()->Return(2), 3, values);
141 0 : schedule()->AddReturn(CurrentBlock(), ret);
142 0 : current_block_ = nullptr;
143 0 : }
144 :
145 :
146 12 : void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
147 6 : Node* values[] = {Int32Constant(0), v1, v2, v3};
148 6 : Node* ret = MakeNode(common()->Return(3), 4, values);
149 6 : schedule()->AddReturn(CurrentBlock(), ret);
150 6 : current_block_ = nullptr;
151 6 : }
152 :
153 12982 : void RawMachineAssembler::PopAndReturn(Node* pop, Node* value) {
154 6491 : Node* values[] = {pop, value};
155 6491 : Node* ret = MakeNode(common()->Return(1), 2, values);
156 6491 : schedule()->AddReturn(CurrentBlock(), ret);
157 6491 : current_block_ = nullptr;
158 6491 : }
159 :
160 0 : void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2) {
161 0 : Node* values[] = {pop, v1, v2};
162 0 : Node* ret = MakeNode(common()->Return(2), 3, values);
163 0 : schedule()->AddReturn(CurrentBlock(), ret);
164 0 : current_block_ = nullptr;
165 0 : }
166 :
167 0 : void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2,
168 0 : Node* v3) {
169 0 : Node* values[] = {pop, v1, v2, v3};
170 0 : Node* ret = MakeNode(common()->Return(3), 4, values);
171 0 : schedule()->AddReturn(CurrentBlock(), ret);
172 0 : current_block_ = nullptr;
173 0 : }
174 :
175 0 : void RawMachineAssembler::DebugAbort(Node* message) {
176 0 : AddNode(machine()->DebugAbort(), message);
177 0 : }
178 :
179 22554 : void RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); }
180 :
181 22492 : void RawMachineAssembler::Unreachable() {
182 11246 : Node* ret = MakeNode(common()->Throw(), 0, nullptr);
183 11246 : schedule()->AddThrow(CurrentBlock(), ret);
184 11246 : current_block_ = nullptr;
185 11246 : }
186 :
187 0 : void RawMachineAssembler::Comment(const char* msg) {
188 0 : AddNode(machine()->Comment(msg));
189 0 : }
190 :
191 139534 : Node* RawMachineAssembler::CallN(CallDescriptor* desc, int input_count,
192 : Node* const* inputs) {
193 : DCHECK(!desc->NeedsFrameState());
194 : // +1 is for target.
195 : DCHECK_EQ(input_count, desc->ParameterCount() + 1);
196 139534 : return AddNode(common()->Call(desc), input_count, inputs);
197 : }
198 :
199 3 : Node* RawMachineAssembler::CallNWithFrameState(CallDescriptor* desc,
200 : int input_count,
201 : Node* const* inputs) {
202 : DCHECK(desc->NeedsFrameState());
203 : // +2 is for target and frame state.
204 : DCHECK_EQ(input_count, desc->ParameterCount() + 2);
205 3 : return AddNode(common()->Call(desc), input_count, inputs);
206 : }
207 :
208 30023 : Node* RawMachineAssembler::TailCallN(CallDescriptor* desc, int input_count,
209 30023 : Node* const* inputs) {
210 : // +1 is for target.
211 : DCHECK_EQ(input_count, desc->ParameterCount() + 1);
212 30023 : Node* tail_call = MakeNode(common()->TailCall(desc), input_count, inputs);
213 30023 : schedule()->AddTailCall(CurrentBlock(), tail_call);
214 30023 : current_block_ = nullptr;
215 30023 : return tail_call;
216 : }
217 :
218 5 : Node* RawMachineAssembler::CallCFunction0(MachineType return_type,
219 : Node* function) {
220 : MachineSignature::Builder builder(zone(), 1, 0);
221 : builder.AddReturn(return_type);
222 : const CallDescriptor* descriptor =
223 10 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
224 :
225 10 : return AddNode(common()->Call(descriptor), function);
226 : }
227 :
228 :
229 201 : Node* RawMachineAssembler::CallCFunction1(MachineType return_type,
230 : MachineType arg0_type, Node* function,
231 : Node* arg0) {
232 : MachineSignature::Builder builder(zone(), 1, 1);
233 : builder.AddReturn(return_type);
234 : builder.AddParam(arg0_type);
235 : const CallDescriptor* descriptor =
236 402 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
237 :
238 402 : return AddNode(common()->Call(descriptor), function, arg0);
239 : }
240 :
241 124 : Node* RawMachineAssembler::CallCFunction1WithCallerSavedRegisters(
242 : MachineType return_type, MachineType arg0_type, Node* function, Node* arg0,
243 : SaveFPRegsMode mode) {
244 : MachineSignature::Builder builder(zone(), 1, 1);
245 : builder.AddReturn(return_type);
246 : builder.AddParam(arg0_type);
247 : CallDescriptor* descriptor =
248 248 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
249 :
250 : descriptor->set_save_fp_mode(mode);
251 :
252 : return AddNode(common()->CallWithCallerSavedRegisters(descriptor), function,
253 248 : arg0);
254 : }
255 :
256 1447 : Node* RawMachineAssembler::CallCFunction2(MachineType return_type,
257 : MachineType arg0_type,
258 : MachineType arg1_type, Node* function,
259 : Node* arg0, Node* arg1) {
260 : MachineSignature::Builder builder(zone(), 1, 2);
261 : builder.AddReturn(return_type);
262 : builder.AddParam(arg0_type);
263 : builder.AddParam(arg1_type);
264 : const CallDescriptor* descriptor =
265 2894 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
266 :
267 2894 : return AddNode(common()->Call(descriptor), function, arg0, arg1);
268 : }
269 :
270 217 : Node* RawMachineAssembler::CallCFunction3(MachineType return_type,
271 : MachineType arg0_type,
272 : MachineType arg1_type,
273 : MachineType arg2_type, Node* function,
274 : Node* arg0, Node* arg1, Node* arg2) {
275 : MachineSignature::Builder builder(zone(), 1, 3);
276 : builder.AddReturn(return_type);
277 : builder.AddParam(arg0_type);
278 : builder.AddParam(arg1_type);
279 : builder.AddParam(arg2_type);
280 : const CallDescriptor* descriptor =
281 434 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
282 :
283 434 : return AddNode(common()->Call(descriptor), function, arg0, arg1, arg2);
284 : }
285 :
286 68 : Node* RawMachineAssembler::CallCFunction3WithCallerSavedRegisters(
287 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
288 : MachineType arg2_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
289 : SaveFPRegsMode mode) {
290 : MachineSignature::Builder builder(zone(), 1, 3);
291 : builder.AddReturn(return_type);
292 : builder.AddParam(arg0_type);
293 : builder.AddParam(arg1_type);
294 : builder.AddParam(arg2_type);
295 : CallDescriptor* descriptor =
296 136 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
297 :
298 : descriptor->set_save_fp_mode(mode);
299 :
300 : return AddNode(common()->CallWithCallerSavedRegisters(descriptor), function,
301 136 : arg0, arg1, arg2);
302 : }
303 :
304 372 : Node* RawMachineAssembler::CallCFunction6(
305 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
306 : MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
307 : MachineType arg5_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
308 : Node* arg3, Node* arg4, Node* arg5) {
309 : MachineSignature::Builder builder(zone(), 1, 6);
310 : builder.AddReturn(return_type);
311 : builder.AddParam(arg0_type);
312 : builder.AddParam(arg1_type);
313 : builder.AddParam(arg2_type);
314 : builder.AddParam(arg3_type);
315 : builder.AddParam(arg4_type);
316 : builder.AddParam(arg5_type);
317 : const CallDescriptor* descriptor =
318 744 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
319 :
320 : return AddNode(common()->Call(descriptor), function, arg0, arg1, arg2, arg3,
321 744 : arg4, arg5);
322 : }
323 :
324 5 : Node* RawMachineAssembler::CallCFunction8(
325 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
326 : MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
327 : MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
328 : Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
329 : Node* arg5, Node* arg6, Node* arg7) {
330 : MachineSignature::Builder builder(zone(), 1, 8);
331 : builder.AddReturn(return_type);
332 : builder.AddParam(arg0_type);
333 : builder.AddParam(arg1_type);
334 : builder.AddParam(arg2_type);
335 : builder.AddParam(arg3_type);
336 : builder.AddParam(arg4_type);
337 : builder.AddParam(arg5_type);
338 : builder.AddParam(arg6_type);
339 : builder.AddParam(arg7_type);
340 5 : Node* args[] = {function, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7};
341 : const CallDescriptor* descriptor =
342 10 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
343 5 : return AddNode(common()->Call(descriptor), arraysize(args), args);
344 : }
345 :
346 321 : Node* RawMachineAssembler::CallCFunction9(
347 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
348 : MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
349 : MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
350 : MachineType arg8_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
351 : Node* arg3, Node* arg4, Node* arg5, Node* arg6, Node* arg7, Node* arg8) {
352 : MachineSignature::Builder builder(zone(), 1, 9);
353 : builder.AddReturn(return_type);
354 : builder.AddParam(arg0_type);
355 : builder.AddParam(arg1_type);
356 : builder.AddParam(arg2_type);
357 : builder.AddParam(arg3_type);
358 : builder.AddParam(arg4_type);
359 : builder.AddParam(arg5_type);
360 : builder.AddParam(arg6_type);
361 : builder.AddParam(arg7_type);
362 : builder.AddParam(arg8_type);
363 : Node* args[] = {function, arg0, arg1, arg2, arg3,
364 321 : arg4, arg5, arg6, arg7, arg8};
365 : const CallDescriptor* descriptor =
366 642 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
367 321 : return AddNode(common()->Call(descriptor), arraysize(args), args);
368 : }
369 :
370 0 : BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
371 1632830 : label->used_ = true;
372 0 : return EnsureBlock(label);
373 : }
374 :
375 1067800 : BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
376 2700630 : if (label->block_ == nullptr) {
377 1067800 : label->block_ = schedule()->NewBasicBlock();
378 : }
379 2700630 : return label->block_;
380 : }
381 :
382 1067800 : void RawMachineAssembler::Bind(RawMachineLabel* label) {
383 : DCHECK_NULL(current_block_);
384 : DCHECK(!label->bound_);
385 1067800 : label->bound_ = true;
386 1067800 : current_block_ = EnsureBlock(label);
387 1067800 : current_block_->set_deferred(label->deferred_);
388 1067800 : }
389 :
390 : #if DEBUG
391 : void RawMachineAssembler::Bind(RawMachineLabel* label,
392 : AssemblerDebugInfo info) {
393 : if (current_block_ != nullptr) {
394 : std::stringstream str;
395 : str << "Binding label without closing previous block:"
396 : << "\n# label: " << info
397 : << "\n# previous block: " << *current_block_;
398 : FATAL(str.str().c_str());
399 : }
400 : Bind(label);
401 : current_block_->set_debug_info(info);
402 : }
403 :
404 : void RawMachineAssembler::PrintCurrentBlock(std::ostream& os) {
405 : os << CurrentBlock();
406 : }
407 :
408 : void RawMachineAssembler::SetInitialDebugInformation(
409 : AssemblerDebugInfo debug_info) {
410 : CurrentBlock()->set_debug_info(debug_info);
411 : }
412 : #endif // DEBUG
413 :
414 0 : BasicBlock* RawMachineAssembler::CurrentBlock() {
415 : DCHECK(current_block_);
416 10662970 : return current_block_;
417 : }
418 :
419 315263 : Node* RawMachineAssembler::Phi(MachineRepresentation rep, int input_count,
420 315263 : Node* const* inputs) {
421 315263 : Node** buffer = new (zone()->New(sizeof(Node*) * (input_count + 1)))
422 315263 : Node*[input_count + 1];
423 315263 : std::copy(inputs, inputs + input_count, buffer);
424 630526 : buffer[input_count] = graph()->start();
425 315263 : return AddNode(common()->Phi(rep, input_count), input_count + 1, buffer);
426 : }
427 :
428 123974 : void RawMachineAssembler::AppendPhiInput(Node* phi, Node* new_input) {
429 : const Operator* op = phi->op();
430 123974 : const Operator* new_op = common()->ResizeMergeOrPhi(op, phi->InputCount());
431 247948 : phi->InsertInput(zone(), phi->InputCount() - 1, new_input);
432 123974 : NodeProperties::ChangeOp(phi, new_op);
433 123974 : }
434 :
435 9329706 : Node* RawMachineAssembler::AddNode(const Operator* op, int input_count,
436 9329706 : Node* const* inputs) {
437 : DCHECK_NOT_NULL(schedule_);
438 : DCHECK_NOT_NULL(current_block_);
439 : Node* node = MakeNode(op, input_count, inputs);
440 9329706 : schedule()->AddNode(CurrentBlock(), node);
441 9329706 : return node;
442 : }
443 :
444 0 : Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
445 10243774 : Node* const* inputs) {
446 : // The raw machine assembler nodes do not have effect and control inputs,
447 : // so we disable checking input counts here.
448 10243774 : return graph()->NewNodeUnchecked(op, input_count, inputs);
449 : }
450 :
451 1083660 : RawMachineLabel::~RawMachineLabel() {
452 : #if DEBUG
453 : if (bound_ == used_) return;
454 : std::stringstream str;
455 : if (bound_) {
456 : str << "A label has been bound but it's not used."
457 : << "\n# label: " << *block_;
458 : } else {
459 : str << "A label has been used but it's not bound.";
460 : }
461 : FATAL(str.str().c_str());
462 : #endif // DEBUG
463 1083660 : }
464 :
465 : } // namespace compiler
466 : } // namespace internal
467 : } // namespace v8
|