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-register-allocator.h" | 10 #include "src/interpreter/bytecode-register-allocator.h" |
10 #include "test/unittests/test-utils.h" | 11 #include "test/unittests/test-utils.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace interpreter { | 15 namespace interpreter { |
15 | 16 |
16 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { | 17 class BytecodeArrayBuilderTest : public TestWithIsolateAndZone { |
17 public: | 18 public: |
18 BytecodeArrayBuilderTest() {} | 19 BytecodeArrayBuilderTest() {} |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 | 271 |
271 // Emit wide context operations. | 272 // Emit wide context operations. |
272 builder.LoadContextSlot(reg, 1024).StoreContextSlot(reg, 1024); | 273 builder.LoadContextSlot(reg, 1024).StoreContextSlot(reg, 1024); |
273 | 274 |
274 // Emit wide load / store lookup slots. | 275 // Emit wide load / store lookup slots. |
275 builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF) | 276 builder.LoadLookupSlot(wide_name, TypeofMode::NOT_INSIDE_TYPEOF) |
276 .LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF) | 277 .LoadLookupSlot(wide_name, TypeofMode::INSIDE_TYPEOF) |
277 .StoreLookupSlot(wide_name, LanguageMode::SLOPPY) | 278 .StoreLookupSlot(wide_name, LanguageMode::SLOPPY) |
278 .StoreLookupSlot(wide_name, LanguageMode::STRICT); | 279 .StoreLookupSlot(wide_name, LanguageMode::STRICT); |
279 | 280 |
| 281 // Emit loads which will be transformed to Ldr equivalents by the peephole |
| 282 // optimizer. |
| 283 builder.LoadNamedProperty(reg, name, 0) |
| 284 .StoreAccumulatorInRegister(reg) |
| 285 .LoadKeyedProperty(reg, 0) |
| 286 .StoreAccumulatorInRegister(reg) |
| 287 .LoadContextSlot(reg, 1) |
| 288 .StoreAccumulatorInRegister(reg) |
| 289 .LoadGlobal(name, 0, TypeofMode::NOT_INSIDE_TYPEOF) |
| 290 .StoreAccumulatorInRegister(reg) |
| 291 .LoadUndefined() |
| 292 .StoreAccumulatorInRegister(reg); |
| 293 |
280 // CreateClosureWide | 294 // CreateClosureWide |
281 Handle<SharedFunctionInfo> shared_info2 = factory->NewSharedFunctionInfo( | 295 Handle<SharedFunctionInfo> shared_info2 = factory->NewSharedFunctionInfo( |
282 factory->NewStringFromStaticChars("function_b"), MaybeHandle<Code>(), | 296 factory->NewStringFromStaticChars("function_b"), MaybeHandle<Code>(), |
283 false); | 297 false); |
284 builder.CreateClosure(shared_info2, NOT_TENURED); | 298 builder.CreateClosure(shared_info2, NOT_TENURED); |
285 | 299 |
286 // Emit wide variant of literal creation operations. | 300 // Emit wide variant of literal creation operations. |
287 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), | 301 builder.CreateRegExpLiteral(factory->NewStringFromStaticChars("wide_literal"), |
288 0, 0) | 302 0, 0) |
289 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) | 303 .CreateArrayLiteral(factory->NewFixedArray(2), 0, 0) |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
345 } | 359 } |
346 i += prefix_offset + Bytecodes::Size(final_bytecode, operand_scale); | 360 i += prefix_offset + Bytecodes::Size(final_bytecode, operand_scale); |
347 } | 361 } |
348 | 362 |
349 // Insert entry for illegal bytecode as this is never willingly emitted. | 363 // Insert entry for illegal bytecode as this is never willingly emitted. |
350 scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1; | 364 scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1; |
351 | 365 |
352 // Insert entry for nop bytecode as this often gets optimized out. | 366 // Insert entry for nop bytecode as this often gets optimized out. |
353 scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1; | 367 scorecard[Bytecodes::ToByte(Bytecode::kNop)] = 1; |
354 | 368 |
355 // Insert entries for bytecodes only emiited by peephole optimizer. | 369 if (!FLAG_ignition_peephole) { |
356 scorecard[Bytecodes::ToByte(Bytecode::kLdrNamedProperty)] = 1; | 370 // Insert entries for bytecodes only emitted by peephole optimizer. |
357 scorecard[Bytecodes::ToByte(Bytecode::kLdrKeyedProperty)] = 1; | 371 scorecard[Bytecodes::ToByte(Bytecode::kLdrNamedProperty)] = 1; |
358 scorecard[Bytecodes::ToByte(Bytecode::kLdrGlobal)] = 1; | 372 scorecard[Bytecodes::ToByte(Bytecode::kLdrKeyedProperty)] = 1; |
359 scorecard[Bytecodes::ToByte(Bytecode::kLdrContextSlot)] = 1; | 373 scorecard[Bytecodes::ToByte(Bytecode::kLdrGlobal)] = 1; |
360 scorecard[Bytecodes::ToByte(Bytecode::kLdrUndefined)] = 1; | 374 scorecard[Bytecodes::ToByte(Bytecode::kLdrContextSlot)] = 1; |
| 375 scorecard[Bytecodes::ToByte(Bytecode::kLdrUndefined)] = 1; |
| 376 scorecard[Bytecodes::ToByte(Bytecode::kLogicalNot)] = 1; |
| 377 scorecard[Bytecodes::ToByte(Bytecode::kJump)] = 1; |
| 378 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrue)] = 1; |
| 379 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalse)] = 1; |
| 380 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfTrueConstant)] = 1; |
| 381 scorecard[Bytecodes::ToByte(Bytecode::kJumpIfFalseConstant)] = 1; |
| 382 } |
361 | 383 |
362 // Check return occurs at the end and only once in the BytecodeArray. | 384 // Check return occurs at the end and only once in the BytecodeArray. |
363 CHECK_EQ(final_bytecode, Bytecode::kReturn); | 385 CHECK_EQ(final_bytecode, Bytecode::kReturn); |
364 CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1); | 386 CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1); |
365 | 387 |
366 #define CHECK_BYTECODE_PRESENT(Name, ...) \ | 388 #define CHECK_BYTECODE_PRESENT(Name, ...) \ |
367 /* Check Bytecode is marked in scorecard, unless it's a debug break */ \ | 389 /* Check Bytecode is marked in scorecard, unless it's a debug break */ \ |
368 if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) { \ | 390 if (!Bytecodes::IsDebugBreak(Bytecode::k##Name)) { \ |
369 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); \ | 391 CHECK_GE(scorecard[Bytecodes::ToByte(Bytecode::k##Name)], 1); \ |
370 } | 392 } |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 .LoadLiteral(heap_num_1) | 485 .LoadLiteral(heap_num_1) |
464 .LoadLiteral(heap_num_1) | 486 .LoadLiteral(heap_num_1) |
465 .LoadLiteral(heap_num_2_copy) | 487 .LoadLiteral(heap_num_2_copy) |
466 .Return(); | 488 .Return(); |
467 | 489 |
468 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 490 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
469 // Should only have one entry for each identical constant. | 491 // Should only have one entry for each identical constant. |
470 CHECK_EQ(array->constant_pool()->length(), 3); | 492 CHECK_EQ(array->constant_pool()->length(), 3); |
471 } | 493 } |
472 | 494 |
| 495 static Bytecode PeepholeToBoolean(Bytecode jump_bytecode) { |
| 496 return FLAG_ignition_peephole |
| 497 ? Bytecodes::GetJumpWithoutToBoolean(jump_bytecode) |
| 498 : jump_bytecode; |
| 499 } |
473 | 500 |
474 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { | 501 TEST_F(BytecodeArrayBuilderTest, ForwardJumps) { |
475 static const int kFarJumpDistance = 256; | 502 static const int kFarJumpDistance = 256; |
476 | 503 |
477 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); | 504 BytecodeArrayBuilder builder(isolate(), zone(), 0, 0, 1); |
478 | 505 |
479 Register reg(0); | 506 Register reg(0); |
480 BytecodeLabel far0, far1, far2, far3, far4; | 507 BytecodeLabel far0, far1, far2, far3, far4; |
481 BytecodeLabel near0, near1, near2, near3, near4; | 508 BytecodeLabel near0, near1, near2, near3, near4; |
482 | 509 |
(...skipping 30 matching lines...) Expand all Loading... |
513 DCHECK_EQ(array->length(), 36 + kFarJumpDistance - 18 + 1); | 540 DCHECK_EQ(array->length(), 36 + kFarJumpDistance - 18 + 1); |
514 | 541 |
515 BytecodeArrayIterator iterator(array); | 542 BytecodeArrayIterator iterator(array); |
516 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 543 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
517 CHECK_EQ(iterator.GetImmediateOperand(0), 18); | 544 CHECK_EQ(iterator.GetImmediateOperand(0), 18); |
518 iterator.Advance(); | 545 iterator.Advance(); |
519 | 546 |
520 // Ignore compare operation. | 547 // Ignore compare operation. |
521 iterator.Advance(); | 548 iterator.Advance(); |
522 | 549 |
523 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 550 CHECK_EQ(iterator.current_bytecode(), |
| 551 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue)); |
524 CHECK_EQ(iterator.GetImmediateOperand(0), 14); | 552 CHECK_EQ(iterator.GetImmediateOperand(0), 14); |
525 iterator.Advance(); | 553 iterator.Advance(); |
526 | 554 |
527 // Ignore compare operation. | 555 // Ignore compare operation. |
528 iterator.Advance(); | 556 iterator.Advance(); |
529 | 557 |
530 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 558 CHECK_EQ(iterator.current_bytecode(), |
| 559 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse)); |
531 CHECK_EQ(iterator.GetImmediateOperand(0), 10); | 560 CHECK_EQ(iterator.GetImmediateOperand(0), 10); |
532 iterator.Advance(); | 561 iterator.Advance(); |
533 | 562 |
534 // Ignore add operation. | 563 // Ignore add operation. |
535 iterator.Advance(); | 564 iterator.Advance(); |
536 | 565 |
537 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | 566 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); |
538 CHECK_EQ(iterator.GetImmediateOperand(0), 6); | 567 CHECK_EQ(iterator.GetImmediateOperand(0), 6); |
539 iterator.Advance(); | 568 iterator.Advance(); |
540 | 569 |
541 // Ignore add operation. | 570 // Ignore add operation. |
542 iterator.Advance(); | 571 iterator.Advance(); |
543 | 572 |
544 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); | 573 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); |
545 CHECK_EQ(iterator.GetImmediateOperand(0), 2); | 574 CHECK_EQ(iterator.GetImmediateOperand(0), 2); |
546 iterator.Advance(); | 575 iterator.Advance(); |
547 | 576 |
548 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 577 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
549 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 578 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
550 Smi::FromInt(kFarJumpDistance)); | 579 Smi::FromInt(kFarJumpDistance)); |
551 iterator.Advance(); | 580 iterator.Advance(); |
552 | 581 |
553 // Ignore compare operation. | 582 // Ignore compare operation. |
554 iterator.Advance(); | 583 iterator.Advance(); |
555 | 584 |
556 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); | 585 CHECK_EQ(iterator.current_bytecode(), |
| 586 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrueConstant)); |
557 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 587 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
558 Smi::FromInt(kFarJumpDistance - 4)); | 588 Smi::FromInt(kFarJumpDistance - 4)); |
559 iterator.Advance(); | 589 iterator.Advance(); |
560 | 590 |
561 // Ignore compare operation. | 591 // Ignore compare operation. |
562 iterator.Advance(); | 592 iterator.Advance(); |
563 | 593 |
564 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); | 594 CHECK_EQ(iterator.current_bytecode(), |
| 595 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalseConstant)); |
565 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 596 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
566 Smi::FromInt(kFarJumpDistance - 8)); | 597 Smi::FromInt(kFarJumpDistance - 8)); |
567 iterator.Advance(); | 598 iterator.Advance(); |
568 | 599 |
569 // Ignore add operation. | 600 // Ignore add operation. |
570 iterator.Advance(); | 601 iterator.Advance(); |
571 | 602 |
572 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); | 603 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); |
573 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), | 604 CHECK_EQ(*iterator.GetConstantForIndexOperand(0), |
574 Smi::FromInt(kFarJumpDistance - 12)); | 605 Smi::FromInt(kFarJumpDistance - 12)); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
621 builder.Jump(&label0); | 652 builder.Jump(&label0); |
622 builder.Return(); | 653 builder.Return(); |
623 | 654 |
624 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 655 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
625 BytecodeArrayIterator iterator(array); | 656 BytecodeArrayIterator iterator(array); |
626 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 657 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
627 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 658 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
628 iterator.Advance(); | 659 iterator.Advance(); |
629 // Ignore compare operation. | 660 // Ignore compare operation. |
630 iterator.Advance(); | 661 iterator.Advance(); |
631 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 662 CHECK_EQ(iterator.current_bytecode(), |
| 663 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue)); |
632 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); | 664 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); |
633 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 665 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
634 iterator.Advance(); | 666 iterator.Advance(); |
635 // Ignore compare operation. | 667 // Ignore compare operation. |
636 iterator.Advance(); | 668 iterator.Advance(); |
637 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 669 CHECK_EQ(iterator.current_bytecode(), |
| 670 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse)); |
638 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); | 671 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); |
639 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 672 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
640 iterator.Advance(); | 673 iterator.Advance(); |
641 // Ignore binary operation. | 674 // Ignore binary operation. |
642 iterator.Advance(); | 675 iterator.Advance(); |
643 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | 676 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); |
644 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); | 677 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); |
645 CHECK_EQ(iterator.GetImmediateOperand(0), -2); | 678 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
646 iterator.Advance(); | 679 iterator.Advance(); |
647 // Ignore binary operation. | 680 // Ignore binary operation. |
(...skipping 20 matching lines...) Expand all Loading... |
668 CHECK_EQ(iterator.GetImmediateOperand(0), -389); | 701 CHECK_EQ(iterator.GetImmediateOperand(0), -389); |
669 iterator.Advance(); | 702 iterator.Advance(); |
670 // Ignore binary operation. | 703 // Ignore binary operation. |
671 iterator.Advance(); | 704 iterator.Advance(); |
672 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | 705 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); |
673 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); | 706 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); |
674 CHECK_EQ(iterator.GetImmediateOperand(0), -399); | 707 CHECK_EQ(iterator.GetImmediateOperand(0), -399); |
675 iterator.Advance(); | 708 iterator.Advance(); |
676 // Ignore compare operation. | 709 // Ignore compare operation. |
677 iterator.Advance(); | 710 iterator.Advance(); |
678 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 711 CHECK_EQ(iterator.current_bytecode(), |
| 712 PeepholeToBoolean(Bytecode::kJumpIfToBooleanFalse)); |
679 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); | 713 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); |
680 CHECK_EQ(iterator.GetImmediateOperand(0), -409); | 714 CHECK_EQ(iterator.GetImmediateOperand(0), -409); |
681 iterator.Advance(); | 715 iterator.Advance(); |
682 // Ignore compare operation. | 716 // Ignore compare operation. |
683 iterator.Advance(); | 717 iterator.Advance(); |
684 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 718 CHECK_EQ(iterator.current_bytecode(), |
| 719 PeepholeToBoolean(Bytecode::kJumpIfToBooleanTrue)); |
685 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); | 720 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); |
686 CHECK_EQ(iterator.GetImmediateOperand(0), -419); | 721 CHECK_EQ(iterator.GetImmediateOperand(0), -419); |
687 iterator.Advance(); | 722 iterator.Advance(); |
688 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 723 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
689 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); | 724 CHECK_EQ(iterator.current_operand_scale(), OperandScale::kDouble); |
690 CHECK_EQ(iterator.GetImmediateOperand(0), -425); | 725 CHECK_EQ(iterator.GetImmediateOperand(0), -425); |
691 iterator.Advance(); | 726 iterator.Advance(); |
692 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 727 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
693 iterator.Advance(); | 728 iterator.Advance(); |
694 CHECK(iterator.done()); | 729 CHECK(iterator.done()); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
745 iterator.Advance(); | 780 iterator.Advance(); |
746 } | 781 } |
747 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 782 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
748 iterator.Advance(); | 783 iterator.Advance(); |
749 CHECK(iterator.done()); | 784 CHECK(iterator.done()); |
750 } | 785 } |
751 | 786 |
752 } // namespace interpreter | 787 } // namespace interpreter |
753 } // namespace internal | 788 } // namespace internal |
754 } // namespace v8 | 789 } // namespace v8 |
OLD | NEW |