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/objects-inl.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 : namespace compiler {
15 :
16 351926 : RawMachineAssembler::RawMachineAssembler(
17 841367 : Isolate* isolate, Graph* graph, CallDescriptor* call_descriptor,
18 : MachineRepresentation word, MachineOperatorBuilder::Flags flags,
19 1897139 : MachineOperatorBuilder::AlignmentRequirements alignment_requirements)
20 : : isolate_(isolate),
21 : graph_(graph),
22 351926 : 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 1759626 : current_block_(schedule()->start()) {
28 351923 : int param_count = static_cast<int>(parameter_count());
29 : // Add an extra input for the JSFunction parameter to the start node.
30 351923 : graph->SetStart(graph->NewNode(common_.Start(param_count + 1)));
31 2386586 : for (size_t i = 0; i < parameter_count(); ++i) {
32 841367 : parameters_[i] =
33 1682734 : AddNode(common()->Parameter(static_cast<int>(i)), graph->start());
34 : }
35 351926 : graph->SetEnd(graph->NewNode(common_.End(0)));
36 351926 : }
37 :
38 378 : Node* RawMachineAssembler::RelocatableIntPtrConstant(intptr_t value,
39 : RelocInfo::Mode rmode) {
40 : return kPointerSize == 8
41 : ? RelocatableInt64Constant(value, rmode)
42 378 : : RelocatableInt32Constant(static_cast<int>(value), rmode);
43 : }
44 :
45 347840 : Schedule* RawMachineAssembler::Export() {
46 : // Compute the correct codegen order.
47 : DCHECK(schedule_->rpo_order()->empty());
48 347840 : OFStream os(stdout);
49 347839 : if (FLAG_trace_turbo_scheduler) {
50 0 : PrintF("--- RAW SCHEDULE -------------------------------------------\n");
51 0 : os << *schedule_;
52 : }
53 347839 : schedule_->EnsureCFGWellFormedness();
54 695680 : Scheduler::ComputeSpecialRPO(zone(), schedule_);
55 347840 : schedule_->PropagateDeferredMark();
56 347840 : if (FLAG_trace_turbo_scheduler) {
57 0 : PrintF("--- EDGE SPLIT AND PROPAGATED DEFERRED SCHEDULE ------------\n");
58 0 : os << *schedule_;
59 : }
60 : // Invalidate RawMachineAssembler.
61 347840 : Schedule* schedule = schedule_;
62 347840 : schedule_ = nullptr;
63 347840 : return schedule;
64 : }
65 :
66 :
67 609303 : Node* RawMachineAssembler::Parameter(size_t index) {
68 : DCHECK(index < parameter_count());
69 1218606 : return parameters_[index];
70 : }
71 :
72 :
73 1335002 : void RawMachineAssembler::Goto(RawMachineLabel* label) {
74 : DCHECK(current_block_ != schedule()->end());
75 667501 : schedule()->AddGoto(CurrentBlock(), Use(label));
76 667501 : current_block_ = nullptr;
77 667501 : }
78 :
79 :
80 951274 : void RawMachineAssembler::Branch(Node* condition, RawMachineLabel* true_val,
81 951275 : RawMachineLabel* false_val) {
82 : DCHECK(current_block_ != schedule()->end());
83 951274 : Node* branch = MakeNode(common()->Branch(), 1, &condition);
84 951275 : schedule()->AddBranch(CurrentBlock(), branch, Use(true_val), Use(false_val));
85 951274 : current_block_ = nullptr;
86 951274 : }
87 :
88 845 : void RawMachineAssembler::Continuations(Node* call, RawMachineLabel* if_success,
89 845 : RawMachineLabel* if_exception) {
90 : DCHECK_NOT_NULL(schedule_);
91 : DCHECK_NOT_NULL(current_block_);
92 845 : schedule()->AddCall(CurrentBlock(), call, Use(if_success), Use(if_exception));
93 845 : current_block_ = nullptr;
94 845 : }
95 :
96 4904 : void RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label,
97 : const int32_t* case_values,
98 : RawMachineLabel** case_labels,
99 275128 : size_t case_count) {
100 : DCHECK_NE(schedule()->end(), current_block_);
101 4904 : size_t succ_count = case_count + 1;
102 4904 : Node* switch_node = AddNode(common()->Switch(succ_count), index);
103 : BasicBlock** succ_blocks = zone()->NewArray<BasicBlock*>(succ_count);
104 67556 : for (size_t index = 0; index < case_count; ++index) {
105 62652 : int32_t case_value = case_values[index];
106 62652 : BasicBlock* case_block = schedule()->NewBasicBlock();
107 : Node* case_node =
108 62652 : graph()->NewNode(common()->IfValue(case_value), switch_node);
109 62652 : schedule()->AddNode(case_block, case_node);
110 125304 : schedule()->AddGoto(case_block, Use(case_labels[index]));
111 62652 : succ_blocks[index] = case_block;
112 : }
113 4904 : BasicBlock* default_block = schedule()->NewBasicBlock();
114 4904 : Node* default_node = graph()->NewNode(common()->IfDefault(), switch_node);
115 4904 : schedule()->AddNode(default_block, default_node);
116 4904 : schedule()->AddGoto(default_block, Use(default_label));
117 4904 : succ_blocks[case_count] = default_block;
118 4904 : schedule()->AddSwitch(CurrentBlock(), switch_node, succ_blocks, succ_count);
119 4904 : current_block_ = nullptr;
120 4904 : }
121 :
122 622874 : void RawMachineAssembler::Return(Node* value) {
123 311437 : Node* values[] = {Int32Constant(0), value};
124 311437 : Node* ret = MakeNode(common()->Return(1), 2, values);
125 311437 : schedule()->AddReturn(CurrentBlock(), ret);
126 311437 : current_block_ = nullptr;
127 311437 : }
128 :
129 :
130 0 : void RawMachineAssembler::Return(Node* v1, Node* v2) {
131 0 : Node* values[] = {Int32Constant(0), v1, v2};
132 0 : Node* ret = MakeNode(common()->Return(2), 3, values);
133 0 : schedule()->AddReturn(CurrentBlock(), ret);
134 0 : current_block_ = nullptr;
135 0 : }
136 :
137 :
138 186 : void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
139 93 : Node* values[] = {Int32Constant(0), v1, v2, v3};
140 93 : Node* ret = MakeNode(common()->Return(3), 4, values);
141 93 : schedule()->AddReturn(CurrentBlock(), ret);
142 93 : current_block_ = nullptr;
143 93 : }
144 :
145 1834 : void RawMachineAssembler::PopAndReturn(Node* pop, Node* value) {
146 917 : Node* values[] = {pop, value};
147 917 : Node* ret = MakeNode(common()->Return(1), 2, values);
148 917 : schedule()->AddReturn(CurrentBlock(), ret);
149 917 : current_block_ = nullptr;
150 917 : }
151 :
152 0 : void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2) {
153 0 : Node* values[] = {pop, v1, v2};
154 0 : Node* ret = MakeNode(common()->Return(2), 3, values);
155 0 : schedule()->AddReturn(CurrentBlock(), ret);
156 0 : current_block_ = nullptr;
157 0 : }
158 :
159 0 : void RawMachineAssembler::PopAndReturn(Node* pop, Node* v1, Node* v2,
160 0 : Node* v3) {
161 0 : Node* values[] = {pop, v1, v2, v3};
162 0 : Node* ret = MakeNode(common()->Return(3), 4, values);
163 0 : schedule()->AddReturn(CurrentBlock(), ret);
164 0 : current_block_ = nullptr;
165 0 : }
166 :
167 18174 : void RawMachineAssembler::DebugBreak() { AddNode(machine()->DebugBreak()); }
168 :
169 18088 : void RawMachineAssembler::Unreachable() {
170 9044 : Node* ret = MakeNode(common()->Throw(), 0, nullptr);
171 9044 : schedule()->AddThrow(CurrentBlock(), ret);
172 9044 : current_block_ = nullptr;
173 9044 : }
174 :
175 0 : void RawMachineAssembler::Comment(const char* msg) {
176 0 : AddNode(machine()->Comment(msg));
177 0 : }
178 :
179 210438 : Node* RawMachineAssembler::CallN(CallDescriptor* desc, int input_count,
180 : Node* const* inputs) {
181 : DCHECK(!desc->NeedsFrameState());
182 : // +1 is for target.
183 : DCHECK_EQ(input_count, desc->ParameterCount() + 1);
184 210438 : return AddNode(common()->Call(desc), input_count, inputs);
185 : }
186 :
187 3 : Node* RawMachineAssembler::CallNWithFrameState(CallDescriptor* desc,
188 : int input_count,
189 : Node* const* inputs) {
190 : DCHECK(desc->NeedsFrameState());
191 : // +2 is for target and frame state.
192 : DCHECK_EQ(input_count, desc->ParameterCount() + 2);
193 3 : return AddNode(common()->Call(desc), input_count, inputs);
194 : }
195 :
196 148873 : Node* RawMachineAssembler::TailCallN(CallDescriptor* desc, int input_count,
197 148873 : Node* const* inputs) {
198 : // +1 is for target.
199 : DCHECK_EQ(input_count, desc->ParameterCount() + 1);
200 148873 : Node* tail_call = MakeNode(common()->TailCall(desc), input_count, inputs);
201 148873 : schedule()->AddTailCall(CurrentBlock(), tail_call);
202 148873 : current_block_ = nullptr;
203 148873 : return tail_call;
204 : }
205 :
206 6 : Node* RawMachineAssembler::CallCFunction0(MachineType return_type,
207 : Node* function) {
208 : MachineSignature::Builder builder(zone(), 1, 0);
209 : builder.AddReturn(return_type);
210 : const CallDescriptor* descriptor =
211 12 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
212 :
213 12 : return AddNode(common()->Call(descriptor), function);
214 : }
215 :
216 :
217 176 : Node* RawMachineAssembler::CallCFunction1(MachineType return_type,
218 : MachineType arg0_type, Node* function,
219 : Node* arg0) {
220 : MachineSignature::Builder builder(zone(), 1, 1);
221 : builder.AddReturn(return_type);
222 : builder.AddParam(arg0_type);
223 : const CallDescriptor* descriptor =
224 352 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
225 :
226 352 : return AddNode(common()->Call(descriptor), function, arg0);
227 : }
228 :
229 :
230 828 : Node* RawMachineAssembler::CallCFunction2(MachineType return_type,
231 : MachineType arg0_type,
232 : MachineType arg1_type, Node* function,
233 : Node* arg0, Node* arg1) {
234 : MachineSignature::Builder builder(zone(), 1, 2);
235 : builder.AddReturn(return_type);
236 : builder.AddParam(arg0_type);
237 : builder.AddParam(arg1_type);
238 : const CallDescriptor* descriptor =
239 1656 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
240 :
241 1656 : return AddNode(common()->Call(descriptor), function, arg0, arg1);
242 : }
243 :
244 172 : Node* RawMachineAssembler::CallCFunction3(MachineType return_type,
245 : MachineType arg0_type,
246 : MachineType arg1_type,
247 : MachineType arg2_type, Node* function,
248 : Node* arg0, Node* arg1, Node* arg2) {
249 : MachineSignature::Builder builder(zone(), 1, 3);
250 : builder.AddReturn(return_type);
251 : builder.AddParam(arg0_type);
252 : builder.AddParam(arg1_type);
253 : builder.AddParam(arg2_type);
254 : const CallDescriptor* descriptor =
255 344 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
256 :
257 344 : return AddNode(common()->Call(descriptor), function, arg0, arg1, arg2);
258 : }
259 :
260 344 : Node* RawMachineAssembler::CallCFunction6(
261 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
262 : MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
263 : MachineType arg5_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
264 : Node* arg3, Node* arg4, Node* arg5) {
265 : MachineSignature::Builder builder(zone(), 1, 6);
266 : builder.AddReturn(return_type);
267 : builder.AddParam(arg0_type);
268 : builder.AddParam(arg1_type);
269 : builder.AddParam(arg2_type);
270 : builder.AddParam(arg3_type);
271 : builder.AddParam(arg4_type);
272 : builder.AddParam(arg5_type);
273 : const CallDescriptor* descriptor =
274 688 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
275 :
276 : return AddNode(common()->Call(descriptor), function, arg0, arg1, arg2, arg3,
277 688 : arg4, arg5);
278 : }
279 :
280 6 : Node* RawMachineAssembler::CallCFunction8(
281 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
282 : MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
283 : MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
284 : Node* function, Node* arg0, Node* arg1, Node* arg2, Node* arg3, Node* arg4,
285 : Node* arg5, Node* arg6, Node* arg7) {
286 : MachineSignature::Builder builder(zone(), 1, 8);
287 : builder.AddReturn(return_type);
288 : builder.AddParam(arg0_type);
289 : builder.AddParam(arg1_type);
290 : builder.AddParam(arg2_type);
291 : builder.AddParam(arg3_type);
292 : builder.AddParam(arg4_type);
293 : builder.AddParam(arg5_type);
294 : builder.AddParam(arg6_type);
295 : builder.AddParam(arg7_type);
296 6 : Node* args[] = {function, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7};
297 : const CallDescriptor* descriptor =
298 12 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
299 6 : return AddNode(common()->Call(descriptor), arraysize(args), args);
300 : }
301 :
302 443 : Node* RawMachineAssembler::CallCFunction9(
303 : MachineType return_type, MachineType arg0_type, MachineType arg1_type,
304 : MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
305 : MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
306 : MachineType arg8_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
307 : Node* arg3, Node* arg4, Node* arg5, Node* arg6, Node* arg7, Node* arg8) {
308 : MachineSignature::Builder builder(zone(), 1, 9);
309 : builder.AddReturn(return_type);
310 : builder.AddParam(arg0_type);
311 : builder.AddParam(arg1_type);
312 : builder.AddParam(arg2_type);
313 : builder.AddParam(arg3_type);
314 : builder.AddParam(arg4_type);
315 : builder.AddParam(arg5_type);
316 : builder.AddParam(arg6_type);
317 : builder.AddParam(arg7_type);
318 : builder.AddParam(arg8_type);
319 : Node* args[] = {function, arg0, arg1, arg2, arg3,
320 443 : arg4, arg5, arg6, arg7, arg8};
321 : const CallDescriptor* descriptor =
322 886 : Linkage::GetSimplifiedCDescriptor(zone(), builder.Build());
323 443 : return AddNode(common()->Call(descriptor), arraysize(args), args);
324 : }
325 :
326 0 : BasicBlock* RawMachineAssembler::Use(RawMachineLabel* label) {
327 2639297 : label->used_ = true;
328 0 : return EnsureBlock(label);
329 : }
330 :
331 1747192 : BasicBlock* RawMachineAssembler::EnsureBlock(RawMachineLabel* label) {
332 4386488 : if (label->block_ == nullptr) {
333 1747192 : label->block_ = schedule()->NewBasicBlock();
334 : }
335 4386488 : return label->block_;
336 : }
337 :
338 1747191 : void RawMachineAssembler::Bind(RawMachineLabel* label) {
339 : DCHECK(current_block_ == nullptr);
340 : DCHECK(!label->bound_);
341 1747191 : label->bound_ = true;
342 1747191 : current_block_ = EnsureBlock(label);
343 1747191 : current_block_->set_deferred(label->deferred_);
344 1747191 : }
345 :
346 : #if DEBUG
347 : void RawMachineAssembler::Bind(RawMachineLabel* label,
348 : AssemblerDebugInfo info) {
349 : if (current_block_ != nullptr) {
350 : std::stringstream str;
351 : str << "Binding label without closing previous block:"
352 : << "\n# label: " << info
353 : << "\n# previous block: " << *current_block_;
354 : FATAL(str.str().c_str());
355 : }
356 : Bind(label);
357 : current_block_->set_debug_info(info);
358 : }
359 :
360 : void RawMachineAssembler::PrintCurrentBlock(std::ostream& os) {
361 : os << CurrentBlock();
362 : }
363 :
364 : void RawMachineAssembler::SetInitialDebugInformation(
365 : AssemblerDebugInfo debug_info) {
366 : CurrentBlock()->set_debug_info(debug_info);
367 : }
368 : #endif // DEBUG
369 :
370 0 : BasicBlock* RawMachineAssembler::CurrentBlock() {
371 : DCHECK(current_block_);
372 17549728 : return current_block_;
373 : }
374 :
375 402067 : Node* RawMachineAssembler::Phi(MachineRepresentation rep, int input_count,
376 402067 : Node* const* inputs) {
377 402067 : Node** buffer = new (zone()->New(sizeof(Node*) * (input_count + 1)))
378 402067 : Node*[input_count + 1];
379 402067 : std::copy(inputs, inputs + input_count, buffer);
380 804134 : buffer[input_count] = graph()->start();
381 402067 : return AddNode(common()->Phi(rep, input_count), input_count + 1, buffer);
382 : }
383 :
384 142555 : void RawMachineAssembler::AppendPhiInput(Node* phi, Node* new_input) {
385 : const Operator* op = phi->op();
386 142555 : const Operator* new_op = common()->ResizeMergeOrPhi(op, phi->InputCount());
387 285110 : phi->InsertInput(zone(), phi->InputCount() - 1, new_input);
388 142555 : NodeProperties::ChangeOp(phi, new_op);
389 142555 : }
390 :
391 15454825 : Node* RawMachineAssembler::AddNode(const Operator* op, int input_count,
392 15454839 : Node* const* inputs) {
393 : DCHECK_NOT_NULL(schedule_);
394 : DCHECK_NOT_NULL(current_block_);
395 : Node* node = MakeNode(op, input_count, inputs);
396 15454839 : schedule()->AddNode(CurrentBlock(), node);
397 15454824 : return node;
398 : }
399 :
400 0 : Node* RawMachineAssembler::MakeNode(const Operator* op, int input_count,
401 16876462 : Node* const* inputs) {
402 : // The raw machine assembler nodes do not have effect and control inputs,
403 : // so we disable checking input counts here.
404 16876462 : return graph()->NewNodeUnchecked(op, input_count, inputs);
405 : }
406 :
407 1760126 : RawMachineLabel::~RawMachineLabel() {
408 : // If this DCHECK fails, it means that the label has been bound but it's not
409 : // used, or the opposite. This would cause the register allocator to crash.
410 : DCHECK_EQ(bound_, used_);
411 1760126 : }
412 :
413 : } // namespace compiler
414 : } // namespace internal
415 : } // namespace v8
|