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 "src/interpreter/bytecode-label.h" | 9 #include "src/interpreter/bytecode-label.h" |
10 #include "src/interpreter/bytecode-register-allocator.h" | 10 #include "src/interpreter/bytecode-register-allocator.h" |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 builder.SuspendGenerator(reg) | 358 builder.SuspendGenerator(reg) |
359 .ResumeGenerator(reg); | 359 .ResumeGenerator(reg); |
360 | 360 |
361 // Intrinsics handled by the interpreter. | 361 // Intrinsics handled by the interpreter. |
362 builder.CallRuntime(Runtime::kInlineIsArray, reg_list); | 362 builder.CallRuntime(Runtime::kInlineIsArray, reg_list); |
363 | 363 |
364 // Emit debugger bytecode. | 364 // Emit debugger bytecode. |
365 builder.Debugger(); | 365 builder.Debugger(); |
366 | 366 |
367 // Insert dummy ops to force longer jumps. | 367 // Insert dummy ops to force longer jumps. |
368 for (int i = 0; i < 128; i++) { | 368 for (int i = 0; i < 256; i++) { |
369 builder.LoadTrue(); | 369 builder.Debugger(); |
370 } | 370 } |
371 | 371 |
372 // Bind labels for long jumps at the very end. | 372 // Bind labels for long jumps at the very end. |
373 for (size_t i = 0; i < arraysize(end); i++) { | 373 for (size_t i = 0; i < arraysize(end); i++) { |
374 builder.Bind(&end[i]); | 374 builder.Bind(&end[i]); |
375 } | 375 } |
376 | 376 |
377 // Return must be the last instruction. | 377 // Return must be the last instruction. |
378 builder.Return(); | 378 builder.Return(); |
379 | 379 |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 } | 517 } |
518 | 518 |
519 static Bytecode PeepholeToBoolean(Bytecode jump_bytecode) { | 519 static Bytecode PeepholeToBoolean(Bytecode jump_bytecode) { |
520 return FLAG_ignition_peephole | 520 return FLAG_ignition_peephole |
521 ? Bytecodes::GetJumpWithoutToBoolean(jump_bytecode) | 521 ? Bytecodes::GetJumpWithoutToBoolean(jump_bytecode) |
522 : jump_bytecode; | 522 : jump_bytecode; |
523 } | 523 } |
524 | 524 |
525 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 525 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
526 CanonicalHandleScope canonical(isolate()); | 526 CanonicalHandleScope canonical(isolate()); |
527 static const int kFarJumpDistance = 256; | 527 static const int kFarJumpDistance = 256 + 20; |
528 | 528 |
529 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 529 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
530 | 530 |
531 Register reg(0); | 531 Register reg(0); |
532 BytecodeLabel far0, far1, far2, far3, far4; | 532 BytecodeLabel far0, far1, far2, far3, far4; |
533 BytecodeLabel near0, near1, near2, near3, near4; | 533 BytecodeLabel near0, near1, near2, near3, near4; |
534 BytecodeLabel after_jump0, after_jump1; | 534 BytecodeLabel after_jump0, after_jump1; |
535 | 535 |
536 builder.Jump(&near0) | 536 builder.Jump(&near0) |
537 .Bind(&after_jump0) | 537 .Bind(&after_jump0) |
(...skipping 24 matching lines...) Expand all Loading... |
562 builder.Debugger(); | 562 builder.Debugger(); |
563 } | 563 } |
564 builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4); | 564 builder.Bind(&far0).Bind(&far1).Bind(&far2).Bind(&far3).Bind(&far4); |
565 builder.Return(); | 565 builder.Return(); |
566 | 566 |
567 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); | 567 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); |
568 DCHECK_EQ(array->length(), 44 + kFarJumpDistance - 22 + 1); | 568 DCHECK_EQ(array->length(), 44 + kFarJumpDistance - 22 + 1); |
569 | 569 |
570 BytecodeArrayIterator iterator(array); | 570 BytecodeArrayIterator iterator(array); |
571 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 571 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
572 CHECK_EQ(iterator.GetImmediateOperand(0), 22); | 572 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 22); |
573 iterator.Advance(); | 573 iterator.Advance(); |
574 | 574 |
575 // Ignore compare operation. | 575 // Ignore compare operation. |
576 iterator.Advance(); | 576 iterator.Advance(); |
577 | 577 |
578 CHECK_EQ(iterator.current_bytecode(), | 578 CHECK_EQ(iterator.current_bytecode(), |
579 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue)); | 579 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue)); |
580 CHECK_EQ(iterator.GetImmediateOperand(0), 17); | 580 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 17); |
581 iterator.Advance(); | 581 iterator.Advance(); |
582 | 582 |
583 // Ignore compare operation. | 583 // Ignore compare operation. |
584 iterator.Advance(); | 584 iterator.Advance(); |
585 | 585 |
586 CHECK_EQ(iterator.current_bytecode(), | 586 CHECK_EQ(iterator.current_bytecode(), |
587 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse)); | 587 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse)); |
588 CHECK_EQ(iterator.GetImmediateOperand(0), 12); | 588 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 12); |
589 iterator.Advance(); | 589 iterator.Advance(); |
590 | 590 |
591 // Ignore add operation. | 591 // Ignore add operation. |
592 iterator.Advance(); | 592 iterator.Advance(); |
593 | 593 |
594 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | 594 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); |
595 CHECK_EQ(iterator.GetImmediateOperand(0), 7); | 595 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 7); |
596 iterator.Advance(); | 596 iterator.Advance(); |
597 | 597 |
598 // Ignore add operation. | 598 // Ignore add operation. |
599 iterator.Advance(); | 599 iterator.Advance(); |
600 | 600 |
601 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); | 601 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); |
602 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 602 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2); |
603 iterator.Advance(); | 603 iterator.Advance(); |
604 | 604 |
605 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 605 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
606 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 606 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
607 Smi::FromInt(kFarJumpDistance)); | 607 Smi::FromInt(kFarJumpDistance)); |
608 iterator.Advance(); | 608 iterator.Advance(); |
609 | 609 |
610 // Ignore compare operation. | 610 // Ignore compare operation. |
611 iterator.Advance(); | 611 iterator.Advance(); |
612 | 612 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 } | 663 } |
664 | 664 |
665 builder.JumpLoop(&label0, 0); | 665 builder.JumpLoop(&label0, 0); |
666 BytecodeLabel end; | 666 BytecodeLabel end; |
667 builder.Bind(&end); | 667 builder.Bind(&end); |
668 builder.Return(); | 668 builder.Return(); |
669 | 669 |
670 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); | 670 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); |
671 BytecodeArrayIterator iterator(array); | 671 BytecodeArrayIterator iterator(array); |
672 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); | 672 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
673 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 673 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0); |
674 iterator.Advance(); | 674 iterator.Advance(); |
675 for (int i = 0; i < 42; i++) { | 675 for (unsigned i = 0; i < 42; i++) { |
676 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); | 676 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
677 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); | 677 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); |
678 // offset of 3 (because kJumpLoop takes two immediate operands) | 678 // offset of 3 (because kJumpLoop takes two immediate operands) |
679 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 3 - 3); | 679 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), i * 3 + 3); |
680 iterator.Advance(); | 680 iterator.Advance(); |
681 } | 681 } |
682 // Check padding to force wide backwards jumps. | 682 // Check padding to force wide backwards jumps. |
683 for (int i = 0; i < 256; i++) { | 683 for (int i = 0; i < 256; i++) { |
684 CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger); | 684 CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger); |
685 iterator.Advance(); | 685 iterator.Advance(); |
686 } | 686 } |
687 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); | 687 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
688 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); | 688 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); |
689 CHECK_EQ(iterator.GetImmediateOperand(0), -386); | 689 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 386); |
690 iterator.Advance(); | 690 iterator.Advance(); |
691 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 691 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
692 iterator.Advance(); | 692 iterator.Advance(); |
693 CHECK(iterator.done()); | 693 CHECK(iterator.done()); |
694 } | 694 } |
695 | 695 |
696 | 696 |
697 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { | 697 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { |
698 CanonicalHandleScope canonical(isolate()); | 698 CanonicalHandleScope canonical(isolate()); |
699 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 699 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
700 | 700 |
701 // Labels can only have 1 forward reference, but | 701 // Labels can only have 1 forward reference, but |
702 // can be referred to mulitple times once bound. | 702 // can be referred to mulitple times once bound. |
703 BytecodeLabel label, after_jump0, after_jump1; | 703 BytecodeLabel label, after_jump0, after_jump1; |
704 | 704 |
705 builder.Jump(&label) | 705 builder.Jump(&label) |
706 .Bind(&label) | 706 .Bind(&label) |
707 .JumpLoop(&label, 0) | 707 .JumpLoop(&label, 0) |
708 .Bind(&after_jump0) | 708 .Bind(&after_jump0) |
709 .JumpLoop(&label, 0) | 709 .JumpLoop(&label, 0) |
710 .Bind(&after_jump1) | 710 .Bind(&after_jump1) |
711 .Return(); | 711 .Return(); |
712 | 712 |
713 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); | 713 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); |
714 BytecodeArrayIterator iterator(array); | 714 BytecodeArrayIterator iterator(array); |
715 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 715 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
716 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 716 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2); |
717 iterator.Advance(); | 717 iterator.Advance(); |
718 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); | 718 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
719 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 719 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0); |
720 iterator.Advance(); | 720 iterator.Advance(); |
721 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); | 721 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
722 CHECK_EQ(iterator.GetImmediateOperand(0), -3); | 722 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 3); |
723 iterator.Advance(); | 723 iterator.Advance(); |
724 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 724 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
725 iterator.Advance(); | 725 iterator.Advance(); |
726 CHECK(iterator.done()); | 726 CHECK(iterator.done()); |
727 } | 727 } |
728 | 728 |
729 | 729 |
730 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { | 730 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { |
731 CanonicalHandleScope canonical(isolate()); | 731 CanonicalHandleScope canonical(isolate()); |
732 static const int kRepeats = 3; | 732 static const int kRepeats = 3; |
733 | 733 |
734 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 734 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
735 for (int i = 0; i < kRepeats; i++) { | 735 for (int i = 0; i < kRepeats; i++) { |
736 BytecodeLabel label, after_jump0, after_jump1; | 736 BytecodeLabel label, after_jump0, after_jump1; |
737 builder.Jump(&label) | 737 builder.Jump(&label) |
738 .Bind(&label) | 738 .Bind(&label) |
739 .JumpLoop(&label, 0) | 739 .JumpLoop(&label, 0) |
740 .Bind(&after_jump0) | 740 .Bind(&after_jump0) |
741 .JumpLoop(&label, 0) | 741 .JumpLoop(&label, 0) |
742 .Bind(&after_jump1); | 742 .Bind(&after_jump1); |
743 } | 743 } |
744 builder.Return(); | 744 builder.Return(); |
745 | 745 |
746 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); | 746 Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); |
747 BytecodeArrayIterator iterator(array); | 747 BytecodeArrayIterator iterator(array); |
748 for (int i = 0; i < kRepeats; i++) { | 748 for (int i = 0; i < kRepeats; i++) { |
749 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 749 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
750 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 750 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 2); |
751 iterator.Advance(); | 751 iterator.Advance(); |
752 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); | 752 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
753 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 753 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 0); |
754 iterator.Advance(); | 754 iterator.Advance(); |
755 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); | 755 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpLoop); |
756 CHECK_EQ(iterator.GetImmediateOperand(0), -3); | 756 CHECK_EQ(iterator.GetUnsignedImmediateOperand(0), 3); |
757 iterator.Advance(); | 757 iterator.Advance(); |
758 } | 758 } |
759 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 759 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
760 iterator.Advance(); | 760 iterator.Advance(); |
761 CHECK(iterator.done()); | 761 CHECK(iterator.done()); |
762 } | 762 } |
763 | 763 |
764 } // namespace interpreter | 764 } // namespace interpreter |
765 } // namespace internal | 765 } // namespace internal |
766 } // namespace v8 | 766 } // namespace v8 |
OLD | NEW |