| 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" |
| 11 #include "test/unittests/test-utils.h" | 11 #include "test/unittests/test-utils.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 namespace interpreter { | 15 namespace interpreter { |
| 16 | 16 |
| 17 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { | 17 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { |
| 18 public: | 18 public: |
| 19 BytecodeArrayBuilderTest() {} | 19 BytecodeArrayBuilderTest() {} |
| 20 ~BytecodeArrayBuilderTest() override {} | 20 ~BytecodeArrayBuilderTest() override {} |
| 21 }; | 21 }; |
| 22 | 22 |
| 23 | 23 |
| 24 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { | 24 TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { |
| 25 CanonicalHandleScope canonical(isolate()); |
| 25 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); | 26 BytecodeArrayBuilder builder(isolate(), zone(), 0, 1, 131); |
| 26 Factory* factory = isolate()->factory(); | 27 Factory* factory = isolate()->factory(); |
| 27 | 28 |
| 28 CHECK_EQ(builder.locals_count(), 131); | 29 CHECK_EQ(builder.locals_count(), 131); |
| 29 CHECK_EQ(builder.context_count(), 1); | 30 CHECK_EQ(builder.context_count(), 1); |
| 30 CHECK_EQ(builder.fixed_register_count(), 132); | 31 CHECK_EQ(builder.fixed_register_count(), 132); |
| 31 | 32 |
| 32 Register reg(0); | 33 Register reg(0); |
| 33 Register other(reg.index() + 1); | 34 Register other(reg.index() + 1); |
| 34 Register wide(128); | 35 Register wide(128); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 /* Check Bytecode is marked in scorecard, unless it's a debug break */ \ | 432 /* Check Bytecode is marked in scorecard, unless it's a debug break */ \ |
| 432 if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) { \ | 433 if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) { \ |
| 433 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); \ | 434 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); \ |
| 434 } | 435 } |
| 435 BYTECODE_LIST(CHECK_BYTECODE_PRESENT) | 436 BYTECODE_LIST(CHECK_BYTECODE_PRESENT) |
| 436 #undef CHECK_BYTECODE_PRESENT | 437 #undef CHECK_BYTECODE_PRESENT |
| 437 } | 438 } |
| 438 | 439 |
| 439 | 440 |
| 440 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { | 441 TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) { |
| 442 CanonicalHandleScope canonical(isolate()); |
| 441 for (int locals = 0; locals < 5; locals++) { | 443 for (int locals = 0; locals < 5; locals++) { |
| 442 for (int contexts = 0; contexts < 4; contexts++) { | 444 for (int contexts = 0; contexts < 4; contexts++) { |
| 443 for (int temps = 0; temps < 3; temps++) { | 445 for (int temps = 0; temps < 3; temps++) { |
| 444 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); | 446 BytecodeArrayBuilder builder(isolate(), zone(), 0, contexts, locals); |
| 445 BytecodeRegisterAllocator temporaries( | 447 BytecodeRegisterAllocator temporaries( |
| 446 zone(), builder.temporary_register_allocator()); | 448 zone(), builder.temporary_register_allocator()); |
| 447 for (int i = 0; i < locals + contexts; i++) { | 449 for (int i = 0; i < locals + contexts; i++) { |
| 448 builder.LoadLiteral(Smi::FromInt(0)); | 450 builder.LoadLiteral(Smi::FromInt(0)); |
| 449 builder.StoreAccumulatorInRegister(Register(i)); | 451 builder.StoreAccumulatorInRegister(Register(i)); |
| 450 } | 452 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 463 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); | 465 Handle<BytecodeArray> the_array = builder.ToBytecodeArray(); |
| 464 int total_registers = locals + contexts + temps; | 466 int total_registers = locals + contexts + temps; |
| 465 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); | 467 CHECK_EQ(the_array->frame_size(), total_registers * kPointerSize); |
| 466 } | 468 } |
| 467 } | 469 } |
| 468 } | 470 } |
| 469 } | 471 } |
| 470 | 472 |
| 471 | 473 |
| 472 TEST_F(BytecodeArrayBuilderTest, RegisterValues) { | 474 TEST_F(BytecodeArrayBuilderTest, RegisterValues) { |
| 475 CanonicalHandleScope canonical(isolate()); |
| 473 int index = 1; | 476 int index = 1; |
| 474 | 477 |
| 475 Register the_register(index); | 478 Register the_register(index); |
| 476 CHECK_EQ(the_register.index(), index); | 479 CHECK_EQ(the_register.index(), index); |
| 477 | 480 |
| 478 int actual_operand = the_register.ToOperand(); | 481 int actual_operand = the_register.ToOperand(); |
| 479 int actual_index = Register::FromOperand(actual_operand).index(); | 482 int actual_index = Register::FromOperand(actual_operand).index(); |
| 480 CHECK_EQ(actual_index, index); | 483 CHECK_EQ(actual_index, index); |
| 481 } | 484 } |
| 482 | 485 |
| 483 | 486 |
| 484 TEST_F(BytecodeArrayBuilderTest, Parameters) { | 487 TEST_F(BytecodeArrayBuilderTest, Parameters) { |
| 488 CanonicalHandleScope canonical(isolate()); |
| 485 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); | 489 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 0); |
| 486 | 490 |
| 487 Register param0(builder.Parameter(0)); | 491 Register param0(builder.Parameter(0)); |
| 488 Register param9(builder.Parameter(9)); | 492 Register param9(builder.Parameter(9)); |
| 489 CHECK_EQ(param9.index() - param0.index(), 9); | 493 CHECK_EQ(param9.index() - param0.index(), 9); |
| 490 } | 494 } |
| 491 | 495 |
| 492 | 496 |
| 493 TEST_F(BytecodeArrayBuilderTest, RegisterType) { | 497 TEST_F(BytecodeArrayBuilderTest, RegisterType) { |
| 498 CanonicalHandleScope canonical(isolate()); |
| 494 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); | 499 BytecodeArrayBuilder builder(isolate(), zone(), 10, 0, 3); |
| 495 BytecodeRegisterAllocator register_allocator( | 500 BytecodeRegisterAllocator register_allocator( |
| 496 zone(), builder.temporary_register_allocator()); | 501 zone(), builder.temporary_register_allocator()); |
| 497 Register temp0 = register_allocator.NewRegister(); | 502 Register temp0 = register_allocator.NewRegister(); |
| 498 Register param0(builder.Parameter(0)); | 503 Register param0(builder.Parameter(0)); |
| 499 Register param9(builder.Parameter(9)); | 504 Register param9(builder.Parameter(9)); |
| 500 Register temp1 = register_allocator.NewRegister(); | 505 Register temp1 = register_allocator.NewRegister(); |
| 501 Register reg0(0); | 506 Register reg0(0); |
| 502 Register reg1(1); | 507 Register reg1(1); |
| 503 Register reg2(2); | 508 Register reg2(2); |
| 504 Register temp2 = register_allocator.NewRegister(); | 509 Register temp2 = register_allocator.NewRegister(); |
| 505 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp0), false); | 510 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp0), false); |
| 506 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp1), false); | 511 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp1), false); |
| 507 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp2), false); | 512 CHECK_EQ(builder.RegisterIsParameterOrLocal(temp2), false); |
| 508 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); | 513 CHECK_EQ(builder.RegisterIsParameterOrLocal(param0), true); |
| 509 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); | 514 CHECK_EQ(builder.RegisterIsParameterOrLocal(param9), true); |
| 510 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); | 515 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg0), true); |
| 511 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); | 516 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg1), true); |
| 512 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); | 517 CHECK_EQ(builder.RegisterIsParameterOrLocal(reg2), true); |
| 513 } | 518 } |
| 514 | 519 |
| 515 | 520 |
| 516 TEST_F(BytecodeArrayBuilderTest, Constants) { | 521 TEST_F(BytecodeArrayBuilderTest, Constants) { |
| 522 CanonicalHandleScope canonical(isolate()); |
| 517 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 523 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
| 518 | 524 |
| 519 Factory* factory = isolate()->factory(); | 525 Factory* factory = isolate()->factory(); |
| 520 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); | 526 Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(3.14); |
| 521 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); | 527 Handle<HeapObject> heap_num_2 = factory->NewHeapNumber(5.2); |
| 522 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); | 528 Handle<Object> large_smi(Smi::FromInt(0x12345678), isolate()); |
| 523 Handle<HeapObject> heap_num_2_copy(*heap_num_2); | 529 Handle<HeapObject> heap_num_2_copy(*heap_num_2); |
| 524 builder.LoadLiteral(heap_num_1) | 530 builder.LoadLiteral(heap_num_1) |
| 525 .LoadLiteral(heap_num_2) | 531 .LoadLiteral(heap_num_2) |
| 526 .LoadLiteral(large_smi) | 532 .LoadLiteral(large_smi) |
| 527 .LoadLiteral(heap_num_1) | 533 .LoadLiteral(heap_num_1) |
| 528 .LoadLiteral(heap_num_1) | 534 .LoadLiteral(heap_num_1) |
| 529 .LoadLiteral(heap_num_2_copy) | 535 .LoadLiteral(heap_num_2_copy) |
| 530 .Return(); | 536 .Return(); |
| 531 | 537 |
| 532 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 538 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
| 533 // Should only have one entry for each identical constant. | 539 // Should only have one entry for each identical constant. |
| 534 CHECK_EQ(array->constant_pool()->length(), 3); | 540 CHECK_EQ(array->constant_pool()->length(), 3); |
| 535 } | 541 } |
| 536 | 542 |
| 537 static Bytecode PeepholeToBoolean(Bytecode jump_bytecode) { | 543 static Bytecode PeepholeToBoolean(Bytecode jump_bytecode) { |
| 538 return FLAG_ignition_peephole | 544 return FLAG_ignition_peephole |
| 539 ? Bytecodes::GetJumpWithoutToBoolean(jump_bytecode) | 545 ? Bytecodes::GetJumpWithoutToBoolean(jump_bytecode) |
| 540 : jump_bytecode; | 546 : jump_bytecode; |
| 541 } | 547 } |
| 542 | 548 |
| 543 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 549 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
| 550 CanonicalHandleScope canonical(isolate()); |
| 544 static const int kFarJumpDistance = 256; | 551 static const int kFarJumpDistance = 256; |
| 545 | 552 |
| 546 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 553 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
| 547 | 554 |
| 548 Register reg(0); | 555 Register reg(0); |
| 549 BytecodeLabel far0, far1, far2, far3, far4; | 556 BytecodeLabel far0, far1, far2, far3, far4; |
| 550 BytecodeLabel near0, near1, near2, near3, near4; | 557 BytecodeLabel near0, near1, near2, near3, near4; |
| 551 BytecodeLabel after_jump0, after_jump1; | 558 BytecodeLabel after_jump0, after_jump1; |
| 552 | 559 |
| 553 builder.Jump(&near0) | 560 builder.Jump(&near0) |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 | 662 |
| 656 CHECK_EQ(iterator.current_bytecode(), | 663 CHECK_EQ(iterator.current_bytecode(), |
| 657 Bytecode::kJumpIfToBooleanFalseConstant); | 664 Bytecode::kJumpIfToBooleanFalseConstant); |
| 658 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 665 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
| 659 Smi::FromInt(kFarJumpDistance - 16)); | 666 Smi::FromInt(kFarJumpDistance - 16)); |
| 660 iterator.Advance(); | 667 iterator.Advance(); |
| 661 } | 668 } |
| 662 | 669 |
| 663 | 670 |
| 664 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { | 671 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { |
| 672 CanonicalHandleScope canonical(isolate()); |
| 665 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 673 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
| 666 | 674 |
| 667 Register reg(0); | 675 Register reg(0); |
| 668 | 676 |
| 669 BytecodeLabel label0, label1, label2, label3, label4; | 677 BytecodeLabel label0, label1, label2, label3, label4; |
| 670 builder.Bind(&label0) | 678 builder.Bind(&label0) |
| 671 .Jump(&label0) | 679 .Jump(&label0) |
| 672 .Bind(&label1) | 680 .Bind(&label1) |
| 673 .CompareOperation(Token::Value::EQ, reg) | 681 .CompareOperation(Token::Value::EQ, reg) |
| 674 .JumpIfTrue(&label1) | 682 .JumpIfTrue(&label1) |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 772 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); | 780 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); |
| 773 CHECK_EQ(iterator.GetImmediateOperand(0), -425); | 781 CHECK_EQ(iterator.GetImmediateOperand(0), -425); |
| 774 iterator.Advance(); | 782 iterator.Advance(); |
| 775 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 783 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 776 iterator.Advance(); | 784 iterator.Advance(); |
| 777 CHECK(iterator.done()); | 785 CHECK(iterator.done()); |
| 778 } | 786 } |
| 779 | 787 |
| 780 | 788 |
| 781 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { | 789 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { |
| 790 CanonicalHandleScope canonical(isolate()); |
| 782 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 791 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
| 783 | 792 |
| 784 // Labels can only have 1 forward reference, but | 793 // Labels can only have 1 forward reference, but |
| 785 // can be referred to mulitple times once bound. | 794 // can be referred to mulitple times once bound. |
| 786 BytecodeLabel label, after_jump0, after_jump1; | 795 BytecodeLabel label, after_jump0, after_jump1; |
| 787 | 796 |
| 788 builder.Jump(&label) | 797 builder.Jump(&label) |
| 789 .Bind(&label) | 798 .Bind(&label) |
| 790 .Jump(&label) | 799 .Jump(&label) |
| 791 .Bind(&after_jump0) | 800 .Bind(&after_jump0) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 804 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 813 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
| 805 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 814 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
| 806 iterator.Advance(); | 815 iterator.Advance(); |
| 807 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 816 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 808 iterator.Advance(); | 817 iterator.Advance(); |
| 809 CHECK(iterator.done()); | 818 CHECK(iterator.done()); |
| 810 } | 819 } |
| 811 | 820 |
| 812 | 821 |
| 813 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { | 822 TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) { |
| 823 CanonicalHandleScope canonical(isolate()); |
| 814 static const int kRepeats = 3; | 824 static const int kRepeats = 3; |
| 815 | 825 |
| 816 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); | 826 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 0); |
| 817 for (int i = 0; i < kRepeats; i++) { | 827 for (int i = 0; i < kRepeats; i++) { |
| 818 BytecodeLabel label, after_jump0, after_jump1; | 828 BytecodeLabel label, after_jump0, after_jump1; |
| 819 builder.Jump(&label) | 829 builder.Jump(&label) |
| 820 .Bind(&label) | 830 .Bind(&label) |
| 821 .Jump(&label) | 831 .Jump(&label) |
| 822 .Bind(&after_jump0) | 832 .Bind(&after_jump0) |
| 823 .Jump(&label) | 833 .Jump(&label) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 839 iterator.Advance(); | 849 iterator.Advance(); |
| 840 } | 850 } |
| 841 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 851 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 842 iterator.Advance(); | 852 iterator.Advance(); |
| 843 CHECK(iterator.done()); | 853 CHECK(iterator.done()); |
| 844 } | 854 } |
| 845 | 855 |
| 846 } // namespace interpreter | 856 } // namespace interpreter |
| 847 } // namespace internal | 857 } // namespace internal |
| 848 } // namespace v8 | 858 } // namespace v8 |
| OLD | NEW |