OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/interpreter/bytecode-array-builder.h" | 7 #include "src/interpreter/bytecode-array-builder.h" |
8 #include "src/interpreter/bytecode-array-iterator.h" | 8 #include "src/interpreter/bytecode-array-iterator.h" |
9 #include "test/unittests/test-utils.h" | 9 #include "test/unittests/test-utils.h" |
10 | 10 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 .JumpIfTrue(&start) | 178 .JumpIfTrue(&start) |
179 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 179 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
180 .JumpIfFalse(&start); | 180 .JumpIfFalse(&start); |
181 // Perform an operation that returns a non-boolean operation to | 181 // Perform an operation that returns a non-boolean operation to |
182 // generate JumpIfToBooleanTrue/False. | 182 // generate JumpIfToBooleanTrue/False. |
183 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 183 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
184 .JumpIfTrue(&start) | 184 .JumpIfTrue(&start) |
185 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 185 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
186 .JumpIfFalse(&start); | 186 .JumpIfFalse(&start); |
187 | 187 |
188 builder.EnterBlock() | 188 // Emit throw in it's own basic block so that the rest of the code isn't |
189 .Throw() | 189 // omitted due to being dead. |
190 .LeaveBlock(); | 190 BytecodeLabel after_throw; |
| 191 builder.Jump(&after_throw) |
| 192 .Throw() |
| 193 .Bind(&after_throw); |
191 | 194 |
192 builder.ForInPrepare(reg).ForInDone(reg).ForInNext(reg, reg); | 195 builder.ForInPrepare(reg).ForInDone(reg).ForInNext(reg, reg); |
193 | 196 |
194 // Wide constant pool loads | 197 // Wide constant pool loads |
195 for (int i = 0; i < 256; i++) { | 198 for (int i = 0; i < 256; i++) { |
196 // Emit junk in constant pool to force wide constant pool index. | 199 // Emit junk in constant pool to force wide constant pool index. |
197 builder.GetConstantPoolEntry(handle(Smi::FromInt(i), isolate())); | 200 builder.GetConstantPoolEntry(handle(Smi::FromInt(i), isolate())); |
198 } | 201 } |
199 builder.LoadLiteral(Smi::FromInt(20000000)); | 202 builder.LoadLiteral(Smi::FromInt(20000000)); |
200 | 203 |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { | 479 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { |
477 BytecodeArrayBuilder builder(isolate(), zone()); | 480 BytecodeArrayBuilder builder(isolate(), zone()); |
478 builder.set_parameter_count(0); | 481 builder.set_parameter_count(0); |
479 builder.set_locals_count(1); | 482 builder.set_locals_count(1); |
480 builder.set_context_count(0); | 483 builder.set_context_count(0); |
481 Register reg(0); | 484 Register reg(0); |
482 | 485 |
483 BytecodeLabel label0, label1, label2, label3, label4; | 486 BytecodeLabel label0, label1, label2, label3, label4; |
484 builder.Bind(&label0) | 487 builder.Bind(&label0) |
485 .Jump(&label0) | 488 .Jump(&label0) |
| 489 .Bind(&label1) |
486 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 490 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
487 .Bind(&label1) | |
488 .JumpIfTrue(&label1) | 491 .JumpIfTrue(&label1) |
| 492 .Bind(&label2) |
489 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 493 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
490 .Bind(&label2) | |
491 .JumpIfFalse(&label2) | 494 .JumpIfFalse(&label2) |
| 495 .Bind(&label3) |
492 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 496 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
493 .Bind(&label3) | |
494 .JumpIfTrue(&label3) | 497 .JumpIfTrue(&label3) |
| 498 .Bind(&label4) |
495 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 499 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
496 .Bind(&label4) | |
497 .JumpIfFalse(&label4); | 500 .JumpIfFalse(&label4); |
498 for (int i = 0; i < 64; i++) { | 501 for (int i = 0; i < 63; i++) { |
499 builder.Jump(&label4); | 502 builder.Jump(&label4); |
500 } | 503 } |
501 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 504 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
502 .JumpIfFalse(&label4); | 505 .JumpIfFalse(&label4); |
503 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 506 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
504 .JumpIfTrue(&label3); | 507 .JumpIfTrue(&label3); |
505 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 508 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
506 .JumpIfFalse(&label2); | 509 .JumpIfFalse(&label2); |
507 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 510 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
508 .JumpIfTrue(&label1); | 511 .JumpIfTrue(&label1); |
509 builder.Jump(&label0); | 512 builder.Jump(&label0); |
510 builder.Return(); | 513 builder.Return(); |
511 | 514 |
512 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 515 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
513 BytecodeArrayIterator iterator(array); | 516 BytecodeArrayIterator iterator(array); |
514 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 517 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
515 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 518 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
516 iterator.Advance(); | 519 iterator.Advance(); |
517 // Ignore compare operation. | 520 // Ignore compare operation. |
518 iterator.Advance(); | 521 iterator.Advance(); |
519 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 522 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); |
520 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 523 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
521 iterator.Advance(); | 524 iterator.Advance(); |
522 // Ignore compare operation. | 525 // Ignore compare operation. |
523 iterator.Advance(); | 526 iterator.Advance(); |
524 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 527 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); |
525 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 528 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
526 iterator.Advance(); | 529 iterator.Advance(); |
527 // Ignore binary operation. | 530 // Ignore binary operation. |
528 iterator.Advance(); | 531 iterator.Advance(); |
529 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | 532 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); |
530 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 533 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
531 iterator.Advance(); | 534 iterator.Advance(); |
532 // Ignore binary operation. | 535 // Ignore binary operation. |
533 iterator.Advance(); | 536 iterator.Advance(); |
534 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); | 537 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); |
535 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 538 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
536 iterator.Advance(); | 539 iterator.Advance(); |
537 for (int i = 0; i < 64; i++) { | 540 for (int i = 0; i < 63; i++) { |
538 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 541 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
539 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 2); | 542 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 4); |
540 iterator.Advance(); | 543 iterator.Advance(); |
541 } | 544 } |
542 // Ignore binary operation. | 545 // Ignore binary operation. |
543 iterator.Advance(); | 546 iterator.Advance(); |
544 CHECK_EQ(iterator.current_bytecode(), | 547 CHECK_EQ(iterator.current_bytecode(), |
545 Bytecode::kJumpIfToBooleanFalseConstant); | 548 Bytecode::kJumpIfToBooleanFalseConstant); |
546 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -132); | 549 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -132); |
547 iterator.Advance(); | 550 iterator.Advance(); |
548 // Ignore binary operation. | 551 // Ignore binary operation. |
549 iterator.Advance(); | 552 iterator.Advance(); |
550 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); | 553 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); |
551 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -140); | 554 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -140); |
552 iterator.Advance(); | 555 iterator.Advance(); |
553 // Ignore compare operation. | 556 // Ignore compare operation. |
554 iterator.Advance(); | 557 iterator.Advance(); |
555 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); | 558 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); |
556 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -148); | 559 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -148); |
557 iterator.Advance(); | 560 iterator.Advance(); |
558 // Ignore compare operation. | 561 // Ignore compare operation. |
559 iterator.Advance(); | 562 iterator.Advance(); |
560 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); | 563 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); |
561 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -156); | 564 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -156); |
562 iterator.Advance(); | 565 iterator.Advance(); |
563 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 566 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
564 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -162); | 567 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -160); |
565 iterator.Advance(); | 568 iterator.Advance(); |
566 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 569 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
567 iterator.Advance(); | 570 iterator.Advance(); |
568 CHECK(iterator.done()); | 571 CHECK(iterator.done()); |
569 } | 572 } |
570 | 573 |
571 | 574 |
572 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { | 575 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { |
573 BytecodeArrayBuilder builder(isolate(), zone()); | 576 BytecodeArrayBuilder builder(isolate(), zone()); |
574 builder.set_parameter_count(0); | 577 builder.set_parameter_count(0); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 CHECK(iterator.done()); | 634 CHECK(iterator.done()); |
632 } | 635 } |
633 | 636 |
634 | 637 |
635 TEST_F(BytecodeArrayBuilderTest, ToBoolean) { | 638 TEST_F(BytecodeArrayBuilderTest, ToBoolean) { |
636 BytecodeArrayBuilder builder(isolate(), zone()); | 639 BytecodeArrayBuilder builder(isolate(), zone()); |
637 builder.set_parameter_count(0); | 640 builder.set_parameter_count(0); |
638 builder.set_locals_count(0); | 641 builder.set_locals_count(0); |
639 builder.set_context_count(0); | 642 builder.set_context_count(0); |
640 | 643 |
641 // Check ToBoolean emitted at start of block. | 644 // Check ToBoolean emitted at start of a basic block. |
642 builder.EnterBlock().CastAccumulatorToBoolean(); | 645 builder.CastAccumulatorToBoolean(); |
643 | 646 |
644 // Check ToBoolean emitted preceding bytecode is non-boolean. | 647 // Check ToBoolean emitted preceding bytecode is non-boolean. |
645 builder.LoadNull().CastAccumulatorToBoolean(); | 648 builder.LoadNull().CastAccumulatorToBoolean(); |
646 | 649 |
647 // Check ToBoolean omitted if preceding bytecode is boolean. | 650 // Check ToBoolean omitted if preceding bytecode is boolean. |
648 builder.LoadFalse().CastAccumulatorToBoolean(); | 651 builder.LoadFalse().CastAccumulatorToBoolean(); |
649 | 652 |
650 // Check ToBoolean emitted if it is at the start of the next block. | 653 // Check ToBoolean emitted if it is at the start of a basic block caused by a |
| 654 // bound label. |
| 655 BytecodeLabel label; |
651 builder.LoadFalse() | 656 builder.LoadFalse() |
652 .LeaveBlock() | 657 .Bind(&label) |
653 .EnterBlock() | 658 .CastAccumulatorToBoolean(); |
654 .CastAccumulatorToBoolean() | 659 |
655 .LeaveBlock(); | 660 // Check ToBoolean emitted if it is at the start of a basic block caused by a |
| 661 // jump. |
| 662 builder.LoadFalse() |
| 663 .JumpIfTrue(&label) |
| 664 .CastAccumulatorToBoolean(); |
656 | 665 |
657 builder.Return(); | 666 builder.Return(); |
658 | 667 |
659 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 668 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
660 BytecodeArrayIterator iterator(array); | 669 BytecodeArrayIterator iterator(array); |
661 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); | 670 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
662 iterator.Advance(); | 671 iterator.Advance(); |
663 | 672 |
664 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaNull); | 673 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaNull); |
665 iterator.Advance(); | 674 iterator.Advance(); |
666 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); | 675 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
667 iterator.Advance(); | 676 iterator.Advance(); |
668 | 677 |
669 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); | 678 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
670 iterator.Advance(); | 679 iterator.Advance(); |
671 | 680 |
672 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); | 681 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
673 iterator.Advance(); | 682 iterator.Advance(); |
674 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); | 683 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
675 iterator.Advance(); | 684 iterator.Advance(); |
676 | 685 |
| 686 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
| 687 iterator.Advance(); |
| 688 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); |
| 689 iterator.Advance(); |
| 690 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 691 iterator.Advance(); |
| 692 |
677 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 693 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
678 iterator.Advance(); | 694 iterator.Advance(); |
679 CHECK(iterator.done()); | 695 CHECK(iterator.done()); |
680 } | 696 } |
681 | 697 |
682 | 698 |
683 } // namespace interpreter | 699 } // namespace interpreter |
684 } // namespace internal | 700 } // namespace internal |
685 } // namespace v8 | 701 } // namespace v8 |
OLD | NEW |