Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1035)

Side by Side Diff: test/cctest/compiler/test-scheduler.cc

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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/v8.h"
6 #include "test/cctest/cctest.h"
7
8 #include "src/compiler/common-operator.h"
9 #include "src/compiler/generic-node-inl.h"
10 #include "src/compiler/generic-node.h"
11 #include "src/compiler/graph.h"
12 #include "src/compiler/graph-visualizer.h"
13 #include "src/compiler/js-operator.h"
14 #include "src/compiler/machine-operator.h"
15 #include "src/compiler/node.h"
16 #include "src/compiler/operator.h"
17 #include "src/compiler/schedule.h"
18 #include "src/compiler/scheduler.h"
19
20 using namespace v8::internal;
21 using namespace v8::internal::compiler;
22
23 struct TestLoop {
24 int count;
25 BasicBlock** nodes;
26 BasicBlock* header() { return nodes[0]; }
27 BasicBlock* last() { return nodes[count - 1]; }
28 ~TestLoop() { delete[] nodes; }
29 };
30
31
32 static TestLoop* CreateLoop(Schedule* schedule, int count) {
33 TestLoop* loop = new TestLoop();
34 loop->count = count;
35 loop->nodes = new BasicBlock*[count];
36 for (int i = 0; i < count; i++) {
37 loop->nodes[i] = schedule->NewBasicBlock();
38 if (i > 0) schedule->AddSuccessor(loop->nodes[i-1], loop->nodes[i]);
39 }
40 schedule->AddSuccessor(loop->nodes[count-1], loop->nodes[0]);
41 return loop;
42 }
43
44
45 static void CheckRPONumbers(
46 BasicBlockVector* order, int expected, bool loops_allowed) {
47 CHECK_EQ(expected, static_cast<int>(order->size()));
48 for (int i = 0; i < static_cast<int>(order->size()); i++) {
49 CHECK(order->at(i)->rpo_number_ == i);
50 if (!loops_allowed) CHECK_LT(order->at(i)->loop_end_, 0);
51 }
52 }
53
54
55 static void CheckLoopContains(BasicBlock** blocks, int body_size) {
56 BasicBlock* header = blocks[0];
57 CHECK_GT(header->loop_end_, 0);
58 CHECK_EQ(body_size, (header->loop_end_ - header->rpo_number_));
59 for (int i = 0; i < body_size; i++) {
60 int num = blocks[i]->rpo_number_;
61 CHECK(num >= header->rpo_number_ && num < header->loop_end_);
62 CHECK(header->LoopContains(blocks[i]));
63 CHECK(header->IsLoopHeader() || blocks[i]->loop_header_ == header);
64 }
65 }
66
67
68 TEST(RPODegenerate1) {
69 HandleAndZoneScope scope;
70 Schedule schedule(scope.main_zone());
71 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
72
73 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
74 CheckRPONumbers(order, 1, false);
75 CHECK_EQ(schedule.entry(), order->at(0));
76 }
77
78
79 TEST(RPODegenerate2) {
80 HandleAndZoneScope scope;
81 Schedule schedule(scope.main_zone());
82 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
83
84 schedule.AddGoto(schedule.entry(), schedule.exit());
85 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
86 CheckRPONumbers(order, 2, false);
87 CHECK_EQ(schedule.entry(), order->at(0));
88 CHECK_EQ(schedule.exit(), order->at(1));
89 }
90
91
92 TEST(RPOLine) {
93 HandleAndZoneScope scope;
94
95 for (int i = 0; i < 10; i++) {
96 Schedule schedule(scope.main_zone());
97 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
98
99 BasicBlock* last = schedule.entry();
100 for (int j = 0; j < i; j++) {
101 BasicBlock* block = schedule.NewBasicBlock();
102 schedule.AddGoto(last, block);
103 last = block;
104 }
105 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
106 CheckRPONumbers(order, 1 + i, false);
107
108 Schedule::BasicBlocks blocks(schedule.all_blocks());
109 for (Schedule::BasicBlocks::iterator iter = blocks.begin();
110 iter != blocks.end(); ++iter) {
111 BasicBlock* block = *iter;
112 if (block->rpo_number_ >= 0 && block->SuccessorCount() == 1) {
113 CHECK(block->rpo_number_ + 1 == block->SuccessorAt(0)->rpo_number_);
114 }
115 }
116 }
117 }
118
119
120 TEST(RPOSelfLoop) {
121 HandleAndZoneScope scope;
122 Schedule schedule(scope.main_zone());
123 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
124 schedule.AddSuccessor(schedule.entry(), schedule.entry());
125 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
126 CheckRPONumbers(order, 1, true);
127 BasicBlock* loop[] = { schedule.entry() };
128 CheckLoopContains(loop, 1);
129 }
130
131
132 TEST(RPOEntryLoop) {
133 HandleAndZoneScope scope;
134 Schedule schedule(scope.main_zone());
135 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
136 schedule.AddSuccessor(schedule.entry(), schedule.exit());
137 schedule.AddSuccessor(schedule.exit(), schedule.entry());
138 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
139 CheckRPONumbers(order, 2, true);
140 BasicBlock* loop[] = { schedule.entry(), schedule.exit() };
141 CheckLoopContains(loop, 2);
142 }
143
144
145 TEST(RPOEndLoop) {
146 HandleAndZoneScope scope;
147 Schedule schedule(scope.main_zone());
148 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
149 TestLoop* loop1 = CreateLoop(&schedule, 2);
150 schedule.AddSuccessor(schedule.entry(), loop1->header());
151 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
152 CheckRPONumbers(order, 3, true);
153 CheckLoopContains(loop1->nodes, loop1->count);
154 }
155
156
157 TEST(RPOEndLoopNested) {
158 HandleAndZoneScope scope;
159 Schedule schedule(scope.main_zone());
160 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
161 TestLoop* loop1 = CreateLoop(&schedule, 2);
162 schedule.AddSuccessor(schedule.entry(), loop1->header());
163 schedule.AddSuccessor(loop1->last(), schedule.entry());
164 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
165 CheckRPONumbers(order, 3, true);
166 CheckLoopContains(loop1->nodes, loop1->count);
167 }
168
169
170 TEST(RPODiamond) {
171 HandleAndZoneScope scope;
172 Schedule schedule(scope.main_zone());
173 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
174
175 BasicBlock* A = schedule.entry();
176 BasicBlock* B = schedule.NewBasicBlock();
177 BasicBlock* C = schedule.NewBasicBlock();
178 BasicBlock* D = schedule.exit();
179
180 schedule.AddSuccessor(A, B);
181 schedule.AddSuccessor(A, C);
182 schedule.AddSuccessor(B, D);
183 schedule.AddSuccessor(C, D);
184
185 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
186 CheckRPONumbers(order, 4, false);
187
188 CHECK_EQ(0, A->rpo_number_);
189 CHECK((B->rpo_number_ == 1 && C->rpo_number_ == 2) ||
190 (B->rpo_number_ == 2 && C->rpo_number_ == 1));
191 CHECK_EQ(3, D->rpo_number_);
192 }
193
194
195 TEST(RPOLoop1) {
196 HandleAndZoneScope scope;
197 Schedule schedule(scope.main_zone());
198 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
199
200 BasicBlock* A = schedule.entry();
201 BasicBlock* B = schedule.NewBasicBlock();
202 BasicBlock* C = schedule.NewBasicBlock();
203 BasicBlock* D = schedule.exit();
204
205 schedule.AddSuccessor(A, B);
206 schedule.AddSuccessor(B, C);
207 schedule.AddSuccessor(C, B);
208 schedule.AddSuccessor(C, D);
209
210 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
211 CheckRPONumbers(order, 4, true);
212 BasicBlock* loop[] = { B, C };
213 CheckLoopContains(loop, 2);
214 }
215
216
217 TEST(RPOLoop2) {
218 HandleAndZoneScope scope;
219 Schedule schedule(scope.main_zone());
220 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
221
222 BasicBlock* A = schedule.entry();
223 BasicBlock* B = schedule.NewBasicBlock();
224 BasicBlock* C = schedule.NewBasicBlock();
225 BasicBlock* D = schedule.exit();
226
227 schedule.AddSuccessor(A, B);
228 schedule.AddSuccessor(B, C);
229 schedule.AddSuccessor(C, B);
230 schedule.AddSuccessor(B, D);
231
232 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
233 CheckRPONumbers(order, 4, true);
234 BasicBlock* loop[] = { B, C };
235 CheckLoopContains(loop, 2);
236 }
237
238
239 TEST(RPOLoopN) {
240 HandleAndZoneScope scope;
241
242 for (int i = 0; i < 11; i++) {
243 Schedule schedule(scope.main_zone());
244 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
245 BasicBlock* A = schedule.entry();
246 BasicBlock* B = schedule.NewBasicBlock();
247 BasicBlock* C = schedule.NewBasicBlock();
248 BasicBlock* D = schedule.NewBasicBlock();
249 BasicBlock* E = schedule.NewBasicBlock();
250 BasicBlock* F = schedule.NewBasicBlock();
251 BasicBlock* G = schedule.exit();
252
253 schedule.AddSuccessor(A, B);
254 schedule.AddSuccessor(B, C);
255 schedule.AddSuccessor(C, D);
256 schedule.AddSuccessor(D, E);
257 schedule.AddSuccessor(E, F);
258 schedule.AddSuccessor(F, B);
259 schedule.AddSuccessor(B, G);
260
261 // Throw in extra backedges from time to time.
262 if (i == 1) schedule.AddSuccessor(B, B);
263 if (i == 2) schedule.AddSuccessor(C, B);
264 if (i == 3) schedule.AddSuccessor(D, B);
265 if (i == 4) schedule.AddSuccessor(E, B);
266 if (i == 5) schedule.AddSuccessor(F, B);
267
268 // Throw in extra loop exits from time to time.
269 if (i == 6) schedule.AddSuccessor(B, G);
270 if (i == 7) schedule.AddSuccessor(C, G);
271 if (i == 8) schedule.AddSuccessor(D, G);
272 if (i == 9) schedule.AddSuccessor(E, G);
273 if (i == 10) schedule.AddSuccessor(F, G);
274
275 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
276 CheckRPONumbers(order, 7, true);
277 BasicBlock* loop[] = { B, C, D, E, F };
278 CheckLoopContains(loop, 5);
279 }
280 }
281
282
283 TEST(RPOLoopNest1) {
284 HandleAndZoneScope scope;
285 Schedule schedule(scope.main_zone());
286 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
287
288 BasicBlock* A = schedule.entry();
289 BasicBlock* B = schedule.NewBasicBlock();
290 BasicBlock* C = schedule.NewBasicBlock();
291 BasicBlock* D = schedule.NewBasicBlock();
292 BasicBlock* E = schedule.NewBasicBlock();
293 BasicBlock* F = schedule.exit();
294
295 schedule.AddSuccessor(A, B);
296 schedule.AddSuccessor(B, C);
297 schedule.AddSuccessor(C, D);
298 schedule.AddSuccessor(D, C);
299 schedule.AddSuccessor(D, E);
300 schedule.AddSuccessor(E, B);
301 schedule.AddSuccessor(E, F);
302
303 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
304 CheckRPONumbers(order, 6, true);
305 BasicBlock* loop1[] = { B, C, D, E };
306 CheckLoopContains(loop1, 4);
307
308 BasicBlock* loop2[] = { C, D };
309 CheckLoopContains(loop2, 2);
310 }
311
312
313 TEST(RPOLoopNest2) {
314 HandleAndZoneScope scope;
315 Schedule schedule(scope.main_zone());
316 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
317
318 BasicBlock* A = schedule.entry();
319 BasicBlock* B = schedule.NewBasicBlock();
320 BasicBlock* C = schedule.NewBasicBlock();
321 BasicBlock* D = schedule.NewBasicBlock();
322 BasicBlock* E = schedule.NewBasicBlock();
323 BasicBlock* F = schedule.NewBasicBlock();
324 BasicBlock* G = schedule.NewBasicBlock();
325 BasicBlock* H = schedule.exit();
326
327 schedule.AddSuccessor(A, B);
328 schedule.AddSuccessor(B, C);
329 schedule.AddSuccessor(C, D);
330 schedule.AddSuccessor(D, E);
331 schedule.AddSuccessor(E, F);
332 schedule.AddSuccessor(F, G);
333 schedule.AddSuccessor(G, H);
334
335 schedule.AddSuccessor(E, D);
336 schedule.AddSuccessor(F, C);
337 schedule.AddSuccessor(G, B);
338
339 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
340 CheckRPONumbers(order, 8, true);
341 BasicBlock* loop1[] = { B, C, D, E, F, G };
342 CheckLoopContains(loop1, 6);
343
344 BasicBlock* loop2[] = { C, D, E, F };
345 CheckLoopContains(loop2, 4);
346
347 BasicBlock* loop3[] = { D, E };
348 CheckLoopContains(loop3, 2);
349 }
350
351
352 TEST(RPOLoopFollow1) {
353 HandleAndZoneScope scope;
354 Schedule schedule(scope.main_zone());
355 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
356
357 TestLoop* loop1 = CreateLoop(&schedule, 1);
358 TestLoop* loop2 = CreateLoop(&schedule, 1);
359
360 BasicBlock* A = schedule.entry();
361 BasicBlock* E = schedule.exit();
362
363 schedule.AddSuccessor(A, loop1->header());
364 schedule.AddSuccessor(loop1->header(), loop2->header());
365 schedule.AddSuccessor(loop2->last(), E);
366
367 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
368
369 CheckLoopContains(loop1->nodes, loop1->count);
370
371 CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
372 CheckLoopContains(loop1->nodes, loop1->count);
373 CheckLoopContains(loop2->nodes, loop2->count);
374 delete loop1;
375 delete loop2;
376 }
377
378
379 TEST(RPOLoopFollow2) {
380 HandleAndZoneScope scope;
381 Schedule schedule(scope.main_zone());
382 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
383
384 TestLoop* loop1 = CreateLoop(&schedule, 1);
385 TestLoop* loop2 = CreateLoop(&schedule, 1);
386
387 BasicBlock* A = schedule.entry();
388 BasicBlock* S = schedule.NewBasicBlock();
389 BasicBlock* E = schedule.exit();
390
391 schedule.AddSuccessor(A, loop1->header());
392 schedule.AddSuccessor(loop1->header(), S);
393 schedule.AddSuccessor(S, loop2->header());
394 schedule.AddSuccessor(loop2->last(), E);
395
396 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
397
398 CheckLoopContains(loop1->nodes, loop1->count);
399
400 CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
401 CheckLoopContains(loop1->nodes, loop1->count);
402 CheckLoopContains(loop2->nodes, loop2->count);
403 delete loop1;
404 delete loop2;
405 }
406
407
408 TEST(RPOLoopFollowN) {
409 HandleAndZoneScope scope;
410
411 for (int size = 1; size < 5; size++) {
412 for (int exit = 0; exit < size; exit++) {
413 Schedule schedule(scope.main_zone());
414 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
415 TestLoop* loop1 = CreateLoop(&schedule, size);
416 TestLoop* loop2 = CreateLoop(&schedule, size);
417 BasicBlock* A = schedule.entry();
418 BasicBlock* E = schedule.exit();
419
420 schedule.AddSuccessor(A, loop1->header());
421 schedule.AddSuccessor(loop1->nodes[exit], loop2->header());
422 schedule.AddSuccessor(loop2->nodes[exit], E);
423 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
424 CheckLoopContains(loop1->nodes, loop1->count);
425
426 CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
427 CheckLoopContains(loop1->nodes, loop1->count);
428 CheckLoopContains(loop2->nodes, loop2->count);
429 delete loop1;
430 delete loop2;
431 }
432 }
433 }
434
435
436 TEST(RPONestedLoopFollow1) {
437 HandleAndZoneScope scope;
438 Schedule schedule(scope.main_zone());
439 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
440
441 TestLoop* loop1 = CreateLoop(&schedule, 1);
442 TestLoop* loop2 = CreateLoop(&schedule, 1);
443
444 BasicBlock* A = schedule.entry();
445 BasicBlock* B = schedule.NewBasicBlock();
446 BasicBlock* C = schedule.NewBasicBlock();
447 BasicBlock* E = schedule.exit();
448
449 schedule.AddSuccessor(A, B);
450 schedule.AddSuccessor(B, loop1->header());
451 schedule.AddSuccessor(loop1->header(), loop2->header());
452 schedule.AddSuccessor(loop2->last(), C);
453 schedule.AddSuccessor(C, E);
454 schedule.AddSuccessor(C, B);
455
456 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
457
458 CheckLoopContains(loop1->nodes, loop1->count);
459
460 CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
461 CheckLoopContains(loop1->nodes, loop1->count);
462 CheckLoopContains(loop2->nodes, loop2->count);
463
464 BasicBlock* loop3[] = { B, loop1->nodes[0], loop2->nodes[0], C };
465 CheckLoopContains(loop3, 4);
466 delete loop1;
467 delete loop2;
468 }
469
470
471 TEST(RPOLoopBackedges1) {
472 HandleAndZoneScope scope;
473
474 int size = 8;
475 for (int i = 0; i < size; i++) {
476 for (int j = 0; j < size; j++) {
477 Schedule schedule(scope.main_zone());
478 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
479 BasicBlock* A = schedule.entry();
480 BasicBlock* E = schedule.exit();
481
482 TestLoop* loop1 = CreateLoop(&schedule, size);
483 schedule.AddSuccessor(A, loop1->header());
484 schedule.AddSuccessor(loop1->last(), E);
485
486 schedule.AddSuccessor(loop1->nodes[i], loop1->header());
487 schedule.AddSuccessor(loop1->nodes[j], E);
488
489 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
490 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
491 CheckLoopContains(loop1->nodes, loop1->count);
492 delete loop1;
493 }
494 }
495 }
496
497
498 TEST(RPOLoopOutedges1) {
499 HandleAndZoneScope scope;
500
501 int size = 8;
502 for (int i = 0; i < size; i++) {
503 for (int j = 0; j < size; j++) {
504 Schedule schedule(scope.main_zone());
505 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
506 BasicBlock* A = schedule.entry();
507 BasicBlock* D = schedule.NewBasicBlock();
508 BasicBlock* E = schedule.exit();
509
510 TestLoop* loop1 = CreateLoop(&schedule, size);
511 schedule.AddSuccessor(A, loop1->header());
512 schedule.AddSuccessor(loop1->last(), E);
513
514 schedule.AddSuccessor(loop1->nodes[i], loop1->header());
515 schedule.AddSuccessor(loop1->nodes[j], D);
516 schedule.AddSuccessor(D, E);
517
518 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
519 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
520 CheckLoopContains(loop1->nodes, loop1->count);
521 delete loop1;
522 }
523 }
524 }
525
526
527 TEST(RPOLoopOutedges2) {
528 HandleAndZoneScope scope;
529
530 int size = 8;
531 for (int i = 0; i < size; i++) {
532 Schedule schedule(scope.main_zone());
533 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
534 BasicBlock* A = schedule.entry();
535 BasicBlock* E = schedule.exit();
536
537 TestLoop* loop1 = CreateLoop(&schedule, size);
538 schedule.AddSuccessor(A, loop1->header());
539 schedule.AddSuccessor(loop1->last(), E);
540
541 for (int j = 0; j < size; j++) {
542 BasicBlock* O = schedule.NewBasicBlock();
543 schedule.AddSuccessor(loop1->nodes[j], O);
544 schedule.AddSuccessor(O, E);
545 }
546
547 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
548 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
549 CheckLoopContains(loop1->nodes, loop1->count);
550 delete loop1;
551 }
552 }
553
554
555 TEST(RPOLoopOutloops1) {
556 HandleAndZoneScope scope;
557
558 int size = 8;
559 for (int i = 0; i < size; i++) {
560 Schedule schedule(scope.main_zone());
561 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
562 BasicBlock* A = schedule.entry();
563 BasicBlock* E = schedule.exit();
564 TestLoop* loop1 = CreateLoop(&schedule, size);
565 schedule.AddSuccessor(A, loop1->header());
566 schedule.AddSuccessor(loop1->last(), E);
567
568 TestLoop** loopN = new TestLoop*[size];
569 for (int j = 0; j < size; j++) {
570 loopN[j] = CreateLoop(&schedule, 2);
571 schedule.AddSuccessor(loop1->nodes[j], loopN[j]->header());
572 schedule.AddSuccessor(loopN[j]->last(), E);
573 }
574
575 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
576 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
577 CheckLoopContains(loop1->nodes, loop1->count);
578
579 for (int j = 0; j < size; j++) {
580 CheckLoopContains(loopN[j]->nodes, loopN[j]->count);
581 delete loopN[j];
582 }
583 delete[] loopN;
584 delete loop1;
585 }
586 }
587
588
589 TEST(RPOLoopMultibackedge) {
590 HandleAndZoneScope scope;
591 Schedule schedule(scope.main_zone());
592 Scheduler scheduler(scope.main_zone(), NULL, &schedule);
593
594 BasicBlock* A = schedule.entry();
595 BasicBlock* B = schedule.NewBasicBlock();
596 BasicBlock* C = schedule.NewBasicBlock();
597 BasicBlock* D = schedule.exit();
598 BasicBlock* E = schedule.NewBasicBlock();
599
600 schedule.AddSuccessor(A, B);
601 schedule.AddSuccessor(B, C);
602 schedule.AddSuccessor(B, D);
603 schedule.AddSuccessor(B, E);
604 schedule.AddSuccessor(C, B);
605 schedule.AddSuccessor(D, B);
606 schedule.AddSuccessor(E, B);
607
608 BasicBlockVector* order = scheduler.ComputeSpecialRPO();
609 CheckRPONumbers(order, 5, true);
610
611 BasicBlock* loop1[] = { B, C, D, E };
612 CheckLoopContains(loop1, 4);
613 }
614
615
616 TEST(BuildScheduleEmpty) {
617 HandleAndZoneScope scope;
618 Graph graph(scope.main_zone());
619 CommonOperatorBuilder builder(scope.main_zone());
620 graph.SetStart(graph.NewNode(builder.Start()));
621 graph.SetEnd(graph.NewNode(builder.End(), graph.start()));
622
623 Scheduler scheduler(scope.main_zone());
624 USE(scheduler.NewSchedule(&graph));
625 }
626
627
628 TEST(BuildScheduleOneParameter) {
629 HandleAndZoneScope scope;
630 Graph graph(scope.main_zone());
631 CommonOperatorBuilder builder(scope.main_zone());
632 graph.SetStart(graph.NewNode(builder.Start()));
633
634 Node* p1 = graph.NewNode(builder.Parameter(0));
635 Node* ret = graph.NewNode(builder.Return(), p1, graph.start(),
636 graph.start());
637
638 graph.SetEnd(graph.NewNode(builder.End(), ret));
639
640 Scheduler scheduler(scope.main_zone());
641 USE(scheduler.NewSchedule(&graph));
642 }
643
644
645 static int GetScheduledNodeCount(Schedule* schedule) {
646 int node_count = 0;
647 for (BasicBlockVectorIter i = schedule->rpo_order()->begin();
648 i != schedule->rpo_order()->end(); ++i) {
649 BasicBlock* block = *i;
650 for (BasicBlock::const_iterator j = block->begin();
651 j != block->end(); ++j) {
652 ++node_count;
653 }
654 BasicBlock::Control control = block->control_;
655 if (control != BasicBlock::kNone) {
656 ++node_count;
657 }
658 }
659 return node_count;
660 }
661
662
663 static void PrintGraph(Graph* graph) {
664 OFStream os(stdout);
665 os << AsDOT(*graph);
666 }
667
668
669 static void PrintSchedule(Schedule* schedule) {
670 OFStream os(stdout);
671 os << *schedule << endl;
672 }
673
674
675 TEST(BuildScheduleIfSplit) {
676 HandleAndZoneScope scope;
677 Graph graph(scope.main_zone());
678 CommonOperatorBuilder builder(scope.main_zone());
679 JSOperatorBuilder js_builder(scope.main_zone());
680 graph.SetStart(graph.NewNode(builder.Start()));
681
682 Node* p1 = graph.NewNode(builder.Parameter(0));
683 Node* p2 = graph.NewNode(builder.Parameter(1));
684 Node* p3 = graph.NewNode(builder.Parameter(2));
685 Node* p4 = graph.NewNode(builder.Parameter(3));
686 Node* p5 = graph.NewNode(builder.Parameter(4));
687 Node* cmp = graph.NewNode(js_builder.LessThanOrEqual(), p1, p2, p3,
688 graph.start(), graph.start());
689 Node* branch = graph.NewNode(builder.Branch(), cmp, graph.start());
690 Node* true_branch = graph.NewNode(builder.IfTrue(), branch);
691 Node* false_branch = graph.NewNode(builder.IfFalse(), branch);
692
693 Node* ret1 = graph.NewNode(builder.Return(), p4, graph.start(),
694 true_branch);
695 Node* ret2 = graph.NewNode(builder.Return(), p5, graph.start(),
696 false_branch);
697 Node* merge = graph.NewNode(builder.Merge(2), ret1, ret2);
698 graph.SetEnd(graph.NewNode(builder.End(), merge));
699
700 PrintGraph(&graph);
701
702 Scheduler scheduler(scope.main_zone());
703 Schedule* schedule = scheduler.NewSchedule(&graph);
704
705 PrintSchedule(schedule);
706
707
708 CHECK_EQ(13, GetScheduledNodeCount(schedule));
709 }
710
711
712 TEST(BuildScheduleIfSplitWithEffects) {
713 HandleAndZoneScope scope;
714 Isolate* isolate = scope.main_isolate();
715 Graph graph(scope.main_zone());
716 CommonOperatorBuilder common_builder(scope.main_zone());
717 JSOperatorBuilder js_builder(scope.main_zone());
718 Operator* op;
719
720 Handle<Object> object =
721 Handle<Object>(isolate->heap()->undefined_value(), isolate);
722 PrintableUnique<Object> unique_constant =
723 PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
724
725 // Manually transcripted code for:
726 // function turbo_fan_test(a, b, c, y) {
727 // if (a < b) {
728 // return a + b - c * c - a + y;
729 // } else {
730 // return c * c - a;
731 // }
732 // }
733 Node* nil = graph.NewNode(common_builder.Dead());
734 op = common_builder.End();
735 Node* n23 = graph.NewNode(op, nil); USE(n23);
736 op = common_builder.Merge(2);
737 Node* n22 = graph.NewNode(op, nil, nil); USE(n22);
738 op = common_builder.Return();
739 Node* n16 = graph.NewNode(op, nil, nil, nil); USE(n16);
740 op = js_builder.Add();
741 Node* n15 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n15);
742 op = js_builder.Subtract();
743 Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n14);
744 op = js_builder.Subtract();
745 Node* n13 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n13);
746 op = js_builder.Add();
747 Node* n11 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n11);
748 op = common_builder.Parameter(0);
749 Node* n2 = graph.NewNode(op); USE(n2);
750 n11->ReplaceInput(0, n2);
751 op = common_builder.Parameter(0);
752 Node* n3 = graph.NewNode(op); USE(n3);
753 n11->ReplaceInput(1, n3);
754 op = common_builder.HeapConstant(unique_constant);
755 Node* n7 = graph.NewNode(op); USE(n7);
756 n11->ReplaceInput(2, n7);
757 op = js_builder.LessThan();
758 Node* n8 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n8);
759 n8->ReplaceInput(0, n2);
760 n8->ReplaceInput(1, n3);
761 n8->ReplaceInput(2, n7);
762 op = common_builder.Start();
763 Node* n0 = graph.NewNode(op); USE(n0);
764 n8->ReplaceInput(3, n0);
765 n8->ReplaceInput(4, n0);
766 n11->ReplaceInput(3, n8);
767 op = common_builder.IfTrue();
768 Node* n10 = graph.NewNode(op, nil); USE(n10);
769 op = common_builder.Branch();
770 Node* n9 = graph.NewNode(op, nil, nil); USE(n9);
771 n9->ReplaceInput(0, n8);
772 n9->ReplaceInput(1, n0);
773 n10->ReplaceInput(0, n9);
774 n11->ReplaceInput(4, n10);
775 n13->ReplaceInput(0, n11);
776 op = js_builder.Multiply();
777 Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n12);
778 op = common_builder.Parameter(0);
779 Node* n4 = graph.NewNode(op); USE(n4);
780 n12->ReplaceInput(0, n4);
781 n12->ReplaceInput(1, n4);
782 n12->ReplaceInput(2, n7);
783 n12->ReplaceInput(3, n11);
784 n12->ReplaceInput(4, n10);
785 n13->ReplaceInput(1, n12);
786 n13->ReplaceInput(2, n7);
787 n13->ReplaceInput(3, n12);
788 n13->ReplaceInput(4, n10);
789 n14->ReplaceInput(0, n13);
790 n14->ReplaceInput(1, n2);
791 n14->ReplaceInput(2, n7);
792 n14->ReplaceInput(3, n13);
793 n14->ReplaceInput(4, n10);
794 n15->ReplaceInput(0, n14);
795 op = common_builder.Parameter(0);
796 Node* n5 = graph.NewNode(op); USE(n5);
797 n15->ReplaceInput(1, n5);
798 n15->ReplaceInput(2, n7);
799 n15->ReplaceInput(3, n14);
800 n15->ReplaceInput(4, n10);
801 n16->ReplaceInput(0, n15);
802 n16->ReplaceInput(1, n15);
803 n16->ReplaceInput(2, n10);
804 n22->ReplaceInput(0, n16);
805 op = common_builder.Return();
806 Node* n21 = graph.NewNode(op, nil, nil, nil); USE(n21);
807 op = js_builder.Subtract();
808 Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n20);
809 op = js_builder.Multiply();
810 Node* n19 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n19);
811 n19->ReplaceInput(0, n4);
812 n19->ReplaceInput(1, n4);
813 n19->ReplaceInput(2, n7);
814 n19->ReplaceInput(3, n8);
815 op = common_builder.IfFalse();
816 Node* n18 = graph.NewNode(op, nil); USE(n18);
817 n18->ReplaceInput(0, n9);
818 n19->ReplaceInput(4, n18);
819 n20->ReplaceInput(0, n19);
820 n20->ReplaceInput(1, n2);
821 n20->ReplaceInput(2, n7);
822 n20->ReplaceInput(3, n19);
823 n20->ReplaceInput(4, n18);
824 n21->ReplaceInput(0, n20);
825 n21->ReplaceInput(1, n20);
826 n21->ReplaceInput(2, n18);
827 n22->ReplaceInput(1, n21);
828 n23->ReplaceInput(0, n22);
829
830 graph.SetStart(n0);
831 graph.SetEnd(n23);
832
833 PrintGraph(&graph);
834
835 Scheduler scheduler(scope.main_zone());
836 Schedule* schedule = scheduler.NewSchedule(&graph);
837
838 PrintSchedule(schedule);
839
840 CHECK_EQ(20, GetScheduledNodeCount(schedule));
841 }
842
843
844 TEST(BuildScheduleSimpleLoop) {
845 HandleAndZoneScope scope;
846 Isolate* isolate = scope.main_isolate();
847 Graph graph(scope.main_zone());
848 CommonOperatorBuilder common_builder(scope.main_zone());
849 JSOperatorBuilder js_builder(scope.main_zone());
850 Operator* op;
851
852 Handle<Object> object =
853 Handle<Object>(isolate->heap()->undefined_value(), isolate);
854 PrintableUnique<Object> unique_constant =
855 PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
856
857 // Manually transcripted code for:
858 // function turbo_fan_test(a, b) {
859 // while (a < b) {
860 // a++;
861 // }
862 // return a;
863 // }
864 Node* nil = graph.NewNode(common_builder.Dead());
865 op = common_builder.End();
866 Node* n20 = graph.NewNode(op, nil); USE(n20);
867 op = common_builder.Return();
868 Node* n19 = graph.NewNode(op, nil, nil, nil); USE(n19);
869 op = common_builder.Phi(2);
870 Node* n8 = graph.NewNode(op, nil, nil, nil); USE(n8);
871 op = common_builder.Parameter(0);
872 Node* n2 = graph.NewNode(op); USE(n2);
873 n8->ReplaceInput(0, n2);
874 op = js_builder.Add();
875 Node* n18 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n18);
876 op = js_builder.ToNumber();
877 Node* n16 = graph.NewNode(op, nil, nil, nil, nil); USE(n16);
878 n16->ReplaceInput(0, n8);
879 op = common_builder.HeapConstant(unique_constant);
880 Node* n5 = graph.NewNode(op); USE(n5);
881 n16->ReplaceInput(1, n5);
882 op = js_builder.LessThan();
883 Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n12);
884 n12->ReplaceInput(0, n8);
885 op = common_builder.Phi(2);
886 Node* n9 = graph.NewNode(op, nil, nil, nil); USE(n9);
887 op = common_builder.Parameter(0);
888 Node* n3 = graph.NewNode(op); USE(n3);
889 n9->ReplaceInput(0, n3);
890 n9->ReplaceInput(1, n9);
891 op = common_builder.Loop(2);
892 Node* n6 = graph.NewNode(op, nil, nil); USE(n6);
893 op = common_builder.Start();
894 Node* n0 = graph.NewNode(op); USE(n0);
895 n6->ReplaceInput(0, n0);
896 op = common_builder.IfTrue();
897 Node* n14 = graph.NewNode(op, nil); USE(n14);
898 op = common_builder.Branch();
899 Node* n13 = graph.NewNode(op, nil, nil); USE(n13);
900 n13->ReplaceInput(0, n12);
901 n13->ReplaceInput(1, n6);
902 n14->ReplaceInput(0, n13);
903 n6->ReplaceInput(1, n14);
904 n9->ReplaceInput(2, n6);
905 n12->ReplaceInput(1, n9);
906 n12->ReplaceInput(2, n5);
907 op = common_builder.Phi(2);
908 Node* n10 = graph.NewNode(op, nil, nil, nil); USE(n10);
909 n10->ReplaceInput(0, n0);
910 n10->ReplaceInput(1, n18);
911 n10->ReplaceInput(2, n6);
912 n12->ReplaceInput(3, n10);
913 n12->ReplaceInput(4, n6);
914 n16->ReplaceInput(2, n12);
915 n16->ReplaceInput(3, n14);
916 n18->ReplaceInput(0, n16);
917 op = common_builder.NumberConstant(0);
918 Node* n17 = graph.NewNode(op); USE(n17);
919 n18->ReplaceInput(1, n17);
920 n18->ReplaceInput(2, n5);
921 n18->ReplaceInput(3, n16);
922 n18->ReplaceInput(4, n14);
923 n8->ReplaceInput(1, n18);
924 n8->ReplaceInput(2, n6);
925 n19->ReplaceInput(0, n8);
926 n19->ReplaceInput(1, n12);
927 op = common_builder.IfFalse();
928 Node* n15 = graph.NewNode(op, nil); USE(n15);
929 n15->ReplaceInput(0, n13);
930 n19->ReplaceInput(2, n15);
931 n20->ReplaceInput(0, n19);
932
933 graph.SetStart(n0);
934 graph.SetEnd(n20);
935
936 PrintGraph(&graph);
937
938 Scheduler scheduler(scope.main_zone());
939 Schedule* schedule = scheduler.NewSchedule(&graph);
940
941 PrintSchedule(schedule);
942
943 CHECK_EQ(19, GetScheduledNodeCount(schedule));
944 }
945
946
947 TEST(BuildScheduleComplexLoops) {
948 HandleAndZoneScope scope;
949 Isolate* isolate = scope.main_isolate();
950 Graph graph(scope.main_zone());
951 CommonOperatorBuilder common_builder(scope.main_zone());
952 JSOperatorBuilder js_builder(scope.main_zone());
953 Operator* op;
954
955 Handle<Object> object =
956 Handle<Object>(isolate->heap()->undefined_value(), isolate);
957 PrintableUnique<Object> unique_constant =
958 PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
959
960 // Manually transcripted code for:
961 // function turbo_fan_test(a, b, c) {
962 // while (a < b) {
963 // a++;
964 // while (c < b) {
965 // c++;
966 // }
967 // }
968 // while (a < b) {
969 // a += 2;
970 // }
971 // return a;
972 // }
973 Node* nil = graph.NewNode(common_builder.Dead());
974 op = common_builder.End();
975 Node* n46 = graph.NewNode(op, nil); USE(n46);
976 op = common_builder.Return();
977 Node* n45 = graph.NewNode(op, nil, nil, nil); USE(n45);
978 op = common_builder.Phi(2);
979 Node* n35 = graph.NewNode(op, nil, nil, nil); USE(n35);
980 op = common_builder.Phi(2);
981 Node* n9 = graph.NewNode(op, nil, nil, nil); USE(n9);
982 op = common_builder.Parameter(0);
983 Node* n2 = graph.NewNode(op); USE(n2);
984 n9->ReplaceInput(0, n2);
985 op = common_builder.Phi(2);
986 Node* n23 = graph.NewNode(op, nil, nil, nil); USE(n23);
987 op = js_builder.Add();
988 Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n20);
989 op = js_builder.ToNumber();
990 Node* n18 = graph.NewNode(op, nil, nil, nil, nil); USE(n18);
991 n18->ReplaceInput(0, n9);
992 op = common_builder.HeapConstant(unique_constant);
993 Node* n6 = graph.NewNode(op); USE(n6);
994 n18->ReplaceInput(1, n6);
995 op = js_builder.LessThan();
996 Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n14);
997 n14->ReplaceInput(0, n9);
998 op = common_builder.Phi(2);
999 Node* n10 = graph.NewNode(op, nil, nil, nil); USE(n10);
1000 op = common_builder.Parameter(0);
1001 Node* n3 = graph.NewNode(op); USE(n3);
1002 n10->ReplaceInput(0, n3);
1003 op = common_builder.Phi(2);
1004 Node* n24 = graph.NewNode(op, nil, nil, nil); USE(n24);
1005 n24->ReplaceInput(0, n10);
1006 n24->ReplaceInput(1, n24);
1007 op = common_builder.Loop(2);
1008 Node* n21 = graph.NewNode(op, nil, nil); USE(n21);
1009 op = common_builder.IfTrue();
1010 Node* n16 = graph.NewNode(op, nil); USE(n16);
1011 op = common_builder.Branch();
1012 Node* n15 = graph.NewNode(op, nil, nil); USE(n15);
1013 n15->ReplaceInput(0, n14);
1014 op = common_builder.Loop(2);
1015 Node* n7 = graph.NewNode(op, nil, nil); USE(n7);
1016 op = common_builder.Start();
1017 Node* n0 = graph.NewNode(op); USE(n0);
1018 n7->ReplaceInput(0, n0);
1019 op = common_builder.IfFalse();
1020 Node* n30 = graph.NewNode(op, nil); USE(n30);
1021 op = common_builder.Branch();
1022 Node* n28 = graph.NewNode(op, nil, nil); USE(n28);
1023 op = js_builder.LessThan();
1024 Node* n27 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n27);
1025 op = common_builder.Phi(2);
1026 Node* n25 = graph.NewNode(op, nil, nil, nil); USE(n25);
1027 op = common_builder.Phi(2);
1028 Node* n11 = graph.NewNode(op, nil, nil, nil); USE(n11);
1029 op = common_builder.Parameter(0);
1030 Node* n4 = graph.NewNode(op); USE(n4);
1031 n11->ReplaceInput(0, n4);
1032 n11->ReplaceInput(1, n25);
1033 n11->ReplaceInput(2, n7);
1034 n25->ReplaceInput(0, n11);
1035 op = js_builder.Add();
1036 Node* n32 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n32);
1037 op = js_builder.ToNumber();
1038 Node* n31 = graph.NewNode(op, nil, nil, nil, nil); USE(n31);
1039 n31->ReplaceInput(0, n25);
1040 n31->ReplaceInput(1, n6);
1041 n31->ReplaceInput(2, n27);
1042 op = common_builder.IfTrue();
1043 Node* n29 = graph.NewNode(op, nil); USE(n29);
1044 n29->ReplaceInput(0, n28);
1045 n31->ReplaceInput(3, n29);
1046 n32->ReplaceInput(0, n31);
1047 op = common_builder.NumberConstant(0);
1048 Node* n19 = graph.NewNode(op); USE(n19);
1049 n32->ReplaceInput(1, n19);
1050 n32->ReplaceInput(2, n6);
1051 n32->ReplaceInput(3, n31);
1052 n32->ReplaceInput(4, n29);
1053 n25->ReplaceInput(1, n32);
1054 n25->ReplaceInput(2, n21);
1055 n27->ReplaceInput(0, n25);
1056 n27->ReplaceInput(1, n24);
1057 n27->ReplaceInput(2, n6);
1058 op = common_builder.Phi(2);
1059 Node* n26 = graph.NewNode(op, nil, nil, nil); USE(n26);
1060 n26->ReplaceInput(0, n20);
1061 n26->ReplaceInput(1, n32);
1062 n26->ReplaceInput(2, n21);
1063 n27->ReplaceInput(3, n26);
1064 n27->ReplaceInput(4, n21);
1065 n28->ReplaceInput(0, n27);
1066 n28->ReplaceInput(1, n21);
1067 n30->ReplaceInput(0, n28);
1068 n7->ReplaceInput(1, n30);
1069 n15->ReplaceInput(1, n7);
1070 n16->ReplaceInput(0, n15);
1071 n21->ReplaceInput(0, n16);
1072 n21->ReplaceInput(1, n29);
1073 n24->ReplaceInput(2, n21);
1074 n10->ReplaceInput(1, n24);
1075 n10->ReplaceInput(2, n7);
1076 n14->ReplaceInput(1, n10);
1077 n14->ReplaceInput(2, n6);
1078 op = common_builder.Phi(2);
1079 Node* n12 = graph.NewNode(op, nil, nil, nil); USE(n12);
1080 n12->ReplaceInput(0, n0);
1081 n12->ReplaceInput(1, n27);
1082 n12->ReplaceInput(2, n7);
1083 n14->ReplaceInput(3, n12);
1084 n14->ReplaceInput(4, n7);
1085 n18->ReplaceInput(2, n14);
1086 n18->ReplaceInput(3, n16);
1087 n20->ReplaceInput(0, n18);
1088 n20->ReplaceInput(1, n19);
1089 n20->ReplaceInput(2, n6);
1090 n20->ReplaceInput(3, n18);
1091 n20->ReplaceInput(4, n16);
1092 n23->ReplaceInput(0, n20);
1093 n23->ReplaceInput(1, n23);
1094 n23->ReplaceInput(2, n21);
1095 n9->ReplaceInput(1, n23);
1096 n9->ReplaceInput(2, n7);
1097 n35->ReplaceInput(0, n9);
1098 op = js_builder.Add();
1099 Node* n44 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n44);
1100 n44->ReplaceInput(0, n35);
1101 op = common_builder.NumberConstant(0);
1102 Node* n43 = graph.NewNode(op); USE(n43);
1103 n44->ReplaceInput(1, n43);
1104 n44->ReplaceInput(2, n6);
1105 op = js_builder.LessThan();
1106 Node* n39 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n39);
1107 n39->ReplaceInput(0, n35);
1108 op = common_builder.Phi(2);
1109 Node* n36 = graph.NewNode(op, nil, nil, nil); USE(n36);
1110 n36->ReplaceInput(0, n10);
1111 n36->ReplaceInput(1, n36);
1112 op = common_builder.Loop(2);
1113 Node* n33 = graph.NewNode(op, nil, nil); USE(n33);
1114 op = common_builder.IfFalse();
1115 Node* n17 = graph.NewNode(op, nil); USE(n17);
1116 n17->ReplaceInput(0, n15);
1117 n33->ReplaceInput(0, n17);
1118 op = common_builder.IfTrue();
1119 Node* n41 = graph.NewNode(op, nil); USE(n41);
1120 op = common_builder.Branch();
1121 Node* n40 = graph.NewNode(op, nil, nil); USE(n40);
1122 n40->ReplaceInput(0, n39);
1123 n40->ReplaceInput(1, n33);
1124 n41->ReplaceInput(0, n40);
1125 n33->ReplaceInput(1, n41);
1126 n36->ReplaceInput(2, n33);
1127 n39->ReplaceInput(1, n36);
1128 n39->ReplaceInput(2, n6);
1129 op = common_builder.Phi(2);
1130 Node* n38 = graph.NewNode(op, nil, nil, nil); USE(n38);
1131 n38->ReplaceInput(0, n14);
1132 n38->ReplaceInput(1, n44);
1133 n38->ReplaceInput(2, n33);
1134 n39->ReplaceInput(3, n38);
1135 n39->ReplaceInput(4, n33);
1136 n44->ReplaceInput(3, n39);
1137 n44->ReplaceInput(4, n41);
1138 n35->ReplaceInput(1, n44);
1139 n35->ReplaceInput(2, n33);
1140 n45->ReplaceInput(0, n35);
1141 n45->ReplaceInput(1, n39);
1142 op = common_builder.IfFalse();
1143 Node* n42 = graph.NewNode(op, nil); USE(n42);
1144 n42->ReplaceInput(0, n40);
1145 n45->ReplaceInput(2, n42);
1146 n46->ReplaceInput(0, n45);
1147
1148 graph.SetStart(n0);
1149 graph.SetEnd(n46);
1150
1151 PrintGraph(&graph);
1152
1153 Scheduler scheduler(scope.main_zone());
1154 Schedule* schedule = scheduler.NewSchedule(&graph);
1155
1156 PrintSchedule(schedule);
1157
1158 CHECK_EQ(46, GetScheduledNodeCount(schedule));
1159 }
1160
1161
1162 TEST(BuildScheduleBreakAndContinue) {
1163 HandleAndZoneScope scope;
1164 Isolate* isolate = scope.main_isolate();
1165 Graph graph(scope.main_zone());
1166 CommonOperatorBuilder common_builder(scope.main_zone());
1167 JSOperatorBuilder js_builder(scope.main_zone());
1168 Operator* op;
1169
1170 Handle<Object> object =
1171 Handle<Object>(isolate->heap()->undefined_value(), isolate);
1172 PrintableUnique<Object> unique_constant =
1173 PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
1174
1175 // Manually transcripted code for:
1176 // function turbo_fan_test(a, b, c) {
1177 // var d = 0;
1178 // while (a < b) {
1179 // a++;
1180 // while (c < b) {
1181 // c++;
1182 // if (d == 0) break;
1183 // a++;
1184 // }
1185 // if (a == 1) continue;
1186 // d++;
1187 // }
1188 // return a + d;
1189 // }
1190 Node* nil = graph.NewNode(common_builder.Dead());
1191 op = common_builder.End();
1192 Node* n58 = graph.NewNode(op, nil); USE(n58);
1193 op = common_builder.Return();
1194 Node* n57 = graph.NewNode(op, nil, nil, nil); USE(n57);
1195 op = js_builder.Add();
1196 Node* n56 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n56);
1197 op = common_builder.Phi(2);
1198 Node* n10 = graph.NewNode(op, nil, nil, nil); USE(n10);
1199 op = common_builder.Parameter(0);
1200 Node* n2 = graph.NewNode(op); USE(n2);
1201 n10->ReplaceInput(0, n2);
1202 op = common_builder.Phi(2);
1203 Node* n25 = graph.NewNode(op, nil, nil, nil); USE(n25);
1204 op = js_builder.Add();
1205 Node* n22 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n22);
1206 op = js_builder.ToNumber();
1207 Node* n20 = graph.NewNode(op, nil, nil, nil, nil); USE(n20);
1208 n20->ReplaceInput(0, n10);
1209 op = common_builder.HeapConstant(unique_constant);
1210 Node* n6 = graph.NewNode(op); USE(n6);
1211 n20->ReplaceInput(1, n6);
1212 op = js_builder.LessThan();
1213 Node* n16 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n16);
1214 n16->ReplaceInput(0, n10);
1215 op = common_builder.Phi(2);
1216 Node* n11 = graph.NewNode(op, nil, nil, nil); USE(n11);
1217 op = common_builder.Parameter(0);
1218 Node* n3 = graph.NewNode(op); USE(n3);
1219 n11->ReplaceInput(0, n3);
1220 op = common_builder.Phi(2);
1221 Node* n26 = graph.NewNode(op, nil, nil, nil); USE(n26);
1222 n26->ReplaceInput(0, n11);
1223 n26->ReplaceInput(1, n26);
1224 op = common_builder.Loop(2);
1225 Node* n23 = graph.NewNode(op, nil, nil); USE(n23);
1226 op = common_builder.IfTrue();
1227 Node* n18 = graph.NewNode(op, nil); USE(n18);
1228 op = common_builder.Branch();
1229 Node* n17 = graph.NewNode(op, nil, nil); USE(n17);
1230 n17->ReplaceInput(0, n16);
1231 op = common_builder.Loop(2);
1232 Node* n8 = graph.NewNode(op, nil, nil); USE(n8);
1233 op = common_builder.Start();
1234 Node* n0 = graph.NewNode(op); USE(n0);
1235 n8->ReplaceInput(0, n0);
1236 op = common_builder.Merge(2);
1237 Node* n53 = graph.NewNode(op, nil, nil); USE(n53);
1238 op = common_builder.IfTrue();
1239 Node* n49 = graph.NewNode(op, nil); USE(n49);
1240 op = common_builder.Branch();
1241 Node* n48 = graph.NewNode(op, nil, nil); USE(n48);
1242 op = js_builder.Equal();
1243 Node* n47 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n47);
1244 n47->ReplaceInput(0, n25);
1245 op = common_builder.NumberConstant(0);
1246 Node* n46 = graph.NewNode(op); USE(n46);
1247 n47->ReplaceInput(1, n46);
1248 n47->ReplaceInput(2, n6);
1249 op = common_builder.Phi(2);
1250 Node* n42 = graph.NewNode(op, nil, nil, nil); USE(n42);
1251 op = js_builder.LessThan();
1252 Node* n30 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n30);
1253 op = common_builder.Phi(2);
1254 Node* n27 = graph.NewNode(op, nil, nil, nil); USE(n27);
1255 op = common_builder.Phi(2);
1256 Node* n12 = graph.NewNode(op, nil, nil, nil); USE(n12);
1257 op = common_builder.Parameter(0);
1258 Node* n4 = graph.NewNode(op); USE(n4);
1259 n12->ReplaceInput(0, n4);
1260 op = common_builder.Phi(2);
1261 Node* n41 = graph.NewNode(op, nil, nil, nil); USE(n41);
1262 n41->ReplaceInput(0, n27);
1263 op = js_builder.Add();
1264 Node* n35 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n35);
1265 op = js_builder.ToNumber();
1266 Node* n34 = graph.NewNode(op, nil, nil, nil, nil); USE(n34);
1267 n34->ReplaceInput(0, n27);
1268 n34->ReplaceInput(1, n6);
1269 n34->ReplaceInput(2, n30);
1270 op = common_builder.IfTrue();
1271 Node* n32 = graph.NewNode(op, nil); USE(n32);
1272 op = common_builder.Branch();
1273 Node* n31 = graph.NewNode(op, nil, nil); USE(n31);
1274 n31->ReplaceInput(0, n30);
1275 n31->ReplaceInput(1, n23);
1276 n32->ReplaceInput(0, n31);
1277 n34->ReplaceInput(3, n32);
1278 n35->ReplaceInput(0, n34);
1279 op = common_builder.NumberConstant(0);
1280 Node* n21 = graph.NewNode(op); USE(n21);
1281 n35->ReplaceInput(1, n21);
1282 n35->ReplaceInput(2, n6);
1283 n35->ReplaceInput(3, n34);
1284 n35->ReplaceInput(4, n32);
1285 n41->ReplaceInput(1, n35);
1286 op = common_builder.Merge(2);
1287 Node* n40 = graph.NewNode(op, nil, nil); USE(n40);
1288 op = common_builder.IfFalse();
1289 Node* n33 = graph.NewNode(op, nil); USE(n33);
1290 n33->ReplaceInput(0, n31);
1291 n40->ReplaceInput(0, n33);
1292 op = common_builder.IfTrue();
1293 Node* n39 = graph.NewNode(op, nil); USE(n39);
1294 op = common_builder.Branch();
1295 Node* n38 = graph.NewNode(op, nil, nil); USE(n38);
1296 op = js_builder.Equal();
1297 Node* n37 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n37);
1298 op = common_builder.Phi(2);
1299 Node* n28 = graph.NewNode(op, nil, nil, nil); USE(n28);
1300 op = common_builder.Phi(2);
1301 Node* n13 = graph.NewNode(op, nil, nil, nil); USE(n13);
1302 op = common_builder.NumberConstant(0);
1303 Node* n7 = graph.NewNode(op); USE(n7);
1304 n13->ReplaceInput(0, n7);
1305 op = common_builder.Phi(2);
1306 Node* n54 = graph.NewNode(op, nil, nil, nil); USE(n54);
1307 n54->ReplaceInput(0, n28);
1308 op = js_builder.Add();
1309 Node* n52 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n52);
1310 op = js_builder.ToNumber();
1311 Node* n51 = graph.NewNode(op, nil, nil, nil, nil); USE(n51);
1312 n51->ReplaceInput(0, n28);
1313 n51->ReplaceInput(1, n6);
1314 n51->ReplaceInput(2, n47);
1315 op = common_builder.IfFalse();
1316 Node* n50 = graph.NewNode(op, nil); USE(n50);
1317 n50->ReplaceInput(0, n48);
1318 n51->ReplaceInput(3, n50);
1319 n52->ReplaceInput(0, n51);
1320 n52->ReplaceInput(1, n21);
1321 n52->ReplaceInput(2, n6);
1322 n52->ReplaceInput(3, n51);
1323 n52->ReplaceInput(4, n50);
1324 n54->ReplaceInput(1, n52);
1325 n54->ReplaceInput(2, n53);
1326 n13->ReplaceInput(1, n54);
1327 n13->ReplaceInput(2, n8);
1328 n28->ReplaceInput(0, n13);
1329 n28->ReplaceInput(1, n28);
1330 n28->ReplaceInput(2, n23);
1331 n37->ReplaceInput(0, n28);
1332 op = common_builder.NumberConstant(0);
1333 Node* n36 = graph.NewNode(op); USE(n36);
1334 n37->ReplaceInput(1, n36);
1335 n37->ReplaceInput(2, n6);
1336 n37->ReplaceInput(3, n35);
1337 n37->ReplaceInput(4, n32);
1338 n38->ReplaceInput(0, n37);
1339 n38->ReplaceInput(1, n32);
1340 n39->ReplaceInput(0, n38);
1341 n40->ReplaceInput(1, n39);
1342 n41->ReplaceInput(2, n40);
1343 n12->ReplaceInput(1, n41);
1344 n12->ReplaceInput(2, n8);
1345 n27->ReplaceInput(0, n12);
1346 n27->ReplaceInput(1, n35);
1347 n27->ReplaceInput(2, n23);
1348 n30->ReplaceInput(0, n27);
1349 n30->ReplaceInput(1, n26);
1350 n30->ReplaceInput(2, n6);
1351 op = common_builder.Phi(2);
1352 Node* n29 = graph.NewNode(op, nil, nil, nil); USE(n29);
1353 n29->ReplaceInput(0, n22);
1354 op = js_builder.Add();
1355 Node* n45 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n45);
1356 op = js_builder.ToNumber();
1357 Node* n44 = graph.NewNode(op, nil, nil, nil, nil); USE(n44);
1358 n44->ReplaceInput(0, n25);
1359 n44->ReplaceInput(1, n6);
1360 n44->ReplaceInput(2, n37);
1361 op = common_builder.IfFalse();
1362 Node* n43 = graph.NewNode(op, nil); USE(n43);
1363 n43->ReplaceInput(0, n38);
1364 n44->ReplaceInput(3, n43);
1365 n45->ReplaceInput(0, n44);
1366 n45->ReplaceInput(1, n21);
1367 n45->ReplaceInput(2, n6);
1368 n45->ReplaceInput(3, n44);
1369 n45->ReplaceInput(4, n43);
1370 n29->ReplaceInput(1, n45);
1371 n29->ReplaceInput(2, n23);
1372 n30->ReplaceInput(3, n29);
1373 n30->ReplaceInput(4, n23);
1374 n42->ReplaceInput(0, n30);
1375 n42->ReplaceInput(1, n37);
1376 n42->ReplaceInput(2, n40);
1377 n47->ReplaceInput(3, n42);
1378 n47->ReplaceInput(4, n40);
1379 n48->ReplaceInput(0, n47);
1380 n48->ReplaceInput(1, n40);
1381 n49->ReplaceInput(0, n48);
1382 n53->ReplaceInput(0, n49);
1383 n53->ReplaceInput(1, n50);
1384 n8->ReplaceInput(1, n53);
1385 n17->ReplaceInput(1, n8);
1386 n18->ReplaceInput(0, n17);
1387 n23->ReplaceInput(0, n18);
1388 n23->ReplaceInput(1, n43);
1389 n26->ReplaceInput(2, n23);
1390 n11->ReplaceInput(1, n26);
1391 n11->ReplaceInput(2, n8);
1392 n16->ReplaceInput(1, n11);
1393 n16->ReplaceInput(2, n6);
1394 op = common_builder.Phi(2);
1395 Node* n14 = graph.NewNode(op, nil, nil, nil); USE(n14);
1396 n14->ReplaceInput(0, n0);
1397 op = common_builder.Phi(2);
1398 Node* n55 = graph.NewNode(op, nil, nil, nil); USE(n55);
1399 n55->ReplaceInput(0, n47);
1400 n55->ReplaceInput(1, n52);
1401 n55->ReplaceInput(2, n53);
1402 n14->ReplaceInput(1, n55);
1403 n14->ReplaceInput(2, n8);
1404 n16->ReplaceInput(3, n14);
1405 n16->ReplaceInput(4, n8);
1406 n20->ReplaceInput(2, n16);
1407 n20->ReplaceInput(3, n18);
1408 n22->ReplaceInput(0, n20);
1409 n22->ReplaceInput(1, n21);
1410 n22->ReplaceInput(2, n6);
1411 n22->ReplaceInput(3, n20);
1412 n22->ReplaceInput(4, n18);
1413 n25->ReplaceInput(0, n22);
1414 n25->ReplaceInput(1, n45);
1415 n25->ReplaceInput(2, n23);
1416 n10->ReplaceInput(1, n25);
1417 n10->ReplaceInput(2, n8);
1418 n56->ReplaceInput(0, n10);
1419 n56->ReplaceInput(1, n13);
1420 n56->ReplaceInput(2, n6);
1421 n56->ReplaceInput(3, n16);
1422 op = common_builder.IfFalse();
1423 Node* n19 = graph.NewNode(op, nil); USE(n19);
1424 n19->ReplaceInput(0, n17);
1425 n56->ReplaceInput(4, n19);
1426 n57->ReplaceInput(0, n56);
1427 n57->ReplaceInput(1, n56);
1428 n57->ReplaceInput(2, n19);
1429 n58->ReplaceInput(0, n57);
1430
1431 graph.SetStart(n0);
1432 graph.SetEnd(n58);
1433
1434 PrintGraph(&graph);
1435
1436 Scheduler scheduler(scope.main_zone());
1437 Schedule* schedule = scheduler.NewSchedule(&graph);
1438
1439 PrintSchedule(schedule);
1440
1441 CHECK_EQ(62, GetScheduledNodeCount(schedule));
1442 }
1443
1444
1445 TEST(BuildScheduleSimpleLoopWithCodeMotion) {
1446 HandleAndZoneScope scope;
1447 Isolate* isolate = scope.main_isolate();
1448 Graph graph(scope.main_zone());
1449 CommonOperatorBuilder common_builder(scope.main_zone());
1450 JSOperatorBuilder js_builder(scope.main_zone());
1451 MachineOperatorBuilder machine_builder(scope.main_zone(), kMachineWord32);
1452 Operator* op;
1453
1454 Handle<Object> object =
1455 Handle<Object>(isolate->heap()->undefined_value(), isolate);
1456 PrintableUnique<Object> unique_constant =
1457 PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), object);
1458
1459 // Manually transcripted code for:
1460 // function turbo_fan_test(a, b, c) {
1461 // while (a < b) {
1462 // a += b + c;
1463 // }
1464 // return a;
1465 // }
1466 Node* nil = graph.NewNode(common_builder.Dead());
1467 op = common_builder.End();
1468 Node* n22 = graph.NewNode(op, nil); USE(n22);
1469 op = common_builder.Return();
1470 Node* n21 = graph.NewNode(op, nil, nil, nil); USE(n21);
1471 op = common_builder.Phi(2);
1472 Node* n9 = graph.NewNode(op, nil, nil, nil); USE(n9);
1473 op = common_builder.Parameter(0);
1474 Node* n2 = graph.NewNode(op); USE(n2);
1475 n9->ReplaceInput(0, n2);
1476 op = js_builder.Add();
1477 Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n20);
1478 n20->ReplaceInput(0, n9);
1479 op = machine_builder.Int32Add();
1480 Node* n19 = graph.NewNode(op, nil, nil); USE(n19);
1481 op = common_builder.Phi(2);
1482 Node* n10 = graph.NewNode(op, nil, nil, nil); USE(n10);
1483 op = common_builder.Parameter(0);
1484 Node* n3 = graph.NewNode(op); USE(n3);
1485 n10->ReplaceInput(0, n3);
1486 n10->ReplaceInput(1, n10);
1487 op = common_builder.Loop(2);
1488 Node* n7 = graph.NewNode(op, nil, nil); USE(n7);
1489 op = common_builder.Start();
1490 Node* n0 = graph.NewNode(op); USE(n0);
1491 n7->ReplaceInput(0, n0);
1492 op = common_builder.IfTrue();
1493 Node* n17 = graph.NewNode(op, nil); USE(n17);
1494 op = common_builder.Branch();
1495 Node* n16 = graph.NewNode(op, nil, nil); USE(n16);
1496 op = js_builder.ToBoolean();
1497 Node* n15 = graph.NewNode(op, nil, nil, nil, nil); USE(n15);
1498 op = js_builder.LessThan();
1499 Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); USE(n14);
1500 n14->ReplaceInput(0, n9);
1501 n14->ReplaceInput(1, n10);
1502 op = common_builder.HeapConstant(unique_constant);
1503 Node* n6 = graph.NewNode(op); USE(n6);
1504 n14->ReplaceInput(2, n6);
1505 op = common_builder.Phi(2);
1506 Node* n12 = graph.NewNode(op, nil, nil, nil); USE(n12);
1507 n12->ReplaceInput(0, n0);
1508 n12->ReplaceInput(1, n20);
1509 n12->ReplaceInput(2, n7);
1510 n14->ReplaceInput(3, n12);
1511 n14->ReplaceInput(4, n7);
1512 n15->ReplaceInput(0, n14);
1513 n15->ReplaceInput(1, n6);
1514 n15->ReplaceInput(2, n14);
1515 n15->ReplaceInput(3, n7);
1516 n16->ReplaceInput(0, n15);
1517 n16->ReplaceInput(1, n7);
1518 n17->ReplaceInput(0, n16);
1519 n7->ReplaceInput(1, n17);
1520 n10->ReplaceInput(2, n7);
1521 n19->ReplaceInput(0, n2);
1522 op = common_builder.Phi(2);
1523 Node* n11 = graph.NewNode(op, nil, nil, nil); USE(n11);
1524 op = common_builder.Parameter(0);
1525 Node* n4 = graph.NewNode(op); USE(n4);
1526 n11->ReplaceInput(0, n4);
1527 n11->ReplaceInput(1, n11);
1528 n11->ReplaceInput(2, n7);
1529 n19->ReplaceInput(1, n3);
1530 n20->ReplaceInput(1, n19);
1531 n20->ReplaceInput(2, n6);
1532 n20->ReplaceInput(3, n19);
1533 n20->ReplaceInput(4, n17);
1534 n9->ReplaceInput(1, n20);
1535 n9->ReplaceInput(2, n7);
1536 n21->ReplaceInput(0, n9);
1537 n21->ReplaceInput(1, n15);
1538 op = common_builder.IfFalse();
1539 Node* n18 = graph.NewNode(op, nil); USE(n18);
1540 n18->ReplaceInput(0, n16);
1541 n21->ReplaceInput(2, n18);
1542 n22->ReplaceInput(0, n21);
1543
1544 graph.SetStart(n0);
1545 graph.SetEnd(n22);
1546
1547 PrintGraph(&graph);
1548
1549 Scheduler scheduler(scope.main_zone());
1550 Schedule* schedule = scheduler.NewSchedule(&graph);
1551
1552 PrintSchedule(schedule);
1553
1554 CHECK_EQ(19, GetScheduledNodeCount(schedule));
1555
1556 // Make sure the integer-only add gets hoisted to a different block that the
1557 // JSAdd.
1558 CHECK(schedule->block(n19) != schedule->block(n20));
1559 }
1560
1561
1562 // So we can get a real JS function.
1563 static Handle<JSFunction> Compile(const char* source) {
1564 Isolate* isolate = CcTest::i_isolate();
1565 Handle<String> source_code = isolate->factory()
1566 ->NewStringFromUtf8(CStrVector(source))
1567 .ToHandleChecked();
1568 Handle<SharedFunctionInfo> shared_function =
1569 Compiler::CompileScript(source_code, Handle<String>(), 0, 0, false,
1570 Handle<Context>(isolate->native_context()), NULL,
1571 NULL, v8::ScriptCompiler::kNoCompileOptions,
1572 NOT_NATIVES_CODE);
1573 return isolate->factory()->NewFunctionFromSharedFunctionInfo(
1574 shared_function, isolate->native_context());
1575 }
1576
1577
1578 TEST(BuildScheduleTrivialLazyDeoptCall) {
1579 HandleAndZoneScope scope;
1580 Isolate* isolate = scope.main_isolate();
1581 Graph graph(scope.main_zone());
1582 CommonOperatorBuilder common_builder(scope.main_zone());
1583 JSOperatorBuilder js_builder(scope.main_zone());
1584
1585 InitializedHandleScope handles;
1586 Handle<JSFunction> function = Compile("m()");
1587 CompilationInfoWithZone info(function);
1588 Linkage linkage(&info);
1589
1590 // Manually transcribed code for:
1591 // function turbo_fan_test() {
1592 // m();
1593 // }
1594 // where m can lazy deopt (so it has a deopt block associated with it).
1595
1596
1597 // Start //
1598 // ^ //
1599 // | (EC) //
1600 // | //
1601 // /------> Call <--------------\ //
1602 // / ^ ^ \ //
1603 // / | | \ undef //
1604 // / / \ \ ^ //
1605 // (E) | (C) / \ (C) \ (E) | //
1606 // | Continuation LazyDeoptimization | | //
1607 // \___ ^ ^ / | //
1608 // \ | | ______/ Framestate //
1609 // undef \ | (VC) | (C) / ^ //
1610 // \ \ | | / / //
1611 // Return Deoptimization ----------/ //
1612 // ^ ^ //
1613 // \ / //
1614 // (C) \ / (C) //
1615 // \ / //
1616 // Merge //
1617 // ^ //
1618 // | //
1619 // End //
1620
1621 Handle<Object> undef_object =
1622 Handle<Object>(isolate->heap()->undefined_value(), isolate);
1623 PrintableUnique<Object> undef_constant =
1624 PrintableUnique<Object>::CreateUninitialized(scope.main_zone(),
1625 undef_object);
1626
1627 Node* undef_node = graph.NewNode(common_builder.HeapConstant(undef_constant));
1628
1629 Node* start_node = graph.NewNode(common_builder.Start());
1630
1631 CallDescriptor* descriptor = linkage.GetJSCallDescriptor(0);
1632 Node* call_node = graph.NewNode(common_builder.Call(descriptor),
1633 undef_node, // function
1634 undef_node, // context
1635 start_node, // effect
1636 start_node); // control
1637
1638 Node* cont_node = graph.NewNode(common_builder.Continuation(), call_node);
1639 Node* lazy_deopt_node =
1640 graph.NewNode(common_builder.LazyDeoptimization(), call_node);
1641
1642 FrameStateDescriptor stateDescriptor(BailoutId(1234));
1643 Node* state_node = graph.NewNode(common_builder.FrameState(stateDescriptor));
1644
1645 Node* return_node = graph.NewNode(common_builder.Return(),
1646 undef_node, // return value
1647 call_node, // effect
1648 cont_node); // control
1649 Node* deoptimization_node = graph.NewNode(common_builder.Deoptimize(),
1650 state_node, // deopt environment
1651 call_node, // effect
1652 lazy_deopt_node); // control
1653
1654 Node* merge_node =
1655 graph.NewNode(common_builder.Merge(2), return_node, deoptimization_node);
1656
1657 Node* end_node = graph.NewNode(common_builder.End(), merge_node);
1658
1659 graph.SetStart(start_node);
1660 graph.SetEnd(end_node);
1661
1662 PrintGraph(&graph);
1663
1664 Scheduler scheduler(scope.main_zone());
1665 Schedule* schedule = scheduler.NewSchedule(&graph);
1666
1667 PrintSchedule(schedule);
1668
1669 // Tests:
1670 // Continuation and deopt have basic blocks.
1671 BasicBlock* cont_block = schedule->block(cont_node);
1672 BasicBlock* deopt_block = schedule->block(lazy_deopt_node);
1673 BasicBlock* call_block = schedule->block(call_node);
1674 CHECK_NE(NULL, cont_block);
1675 CHECK_NE(NULL, deopt_block);
1676 CHECK_NE(NULL, call_block);
1677 // The basic blocks are different.
1678 CHECK_NE(cont_block, deopt_block);
1679 CHECK_NE(cont_block, call_block);
1680 CHECK_NE(deopt_block, call_block);
1681 // The call node finishes its own basic block.
1682 CHECK_EQ(BasicBlock::kCall, call_block->control_);
1683 CHECK_EQ(call_node, call_block->control_input_);
1684 // The lazy deopt block is deferred.
1685 CHECK(deopt_block->deferred_);
1686 CHECK(!call_block->deferred_);
1687 CHECK(!cont_block->deferred_);
1688 // The lazy deopt block contains framestate + bailout (and nothing else).
1689 CHECK_EQ(deoptimization_node, deopt_block->control_input_);
1690 CHECK_EQ(2, deopt_block->nodes_.size());
1691 CHECK_EQ(lazy_deopt_node, deopt_block->nodes_[0]);
1692 CHECK_EQ(state_node, deopt_block->nodes_[1]);
1693 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698