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 |