| 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 |