| 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 "test/unittests/test-utils.h" | 9 #include "test/unittests/test-utils.h" |
| 10 | 10 |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 .JumpIfTrue(&start) | 178 .JumpIfTrue(&start) |
| 179 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 179 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
| 180 .JumpIfFalse(&start); | 180 .JumpIfFalse(&start); |
| 181 // Perform an operation that returns a non-boolean operation to | 181 // Perform an operation that returns a non-boolean operation to |
| 182 // generate JumpIfToBooleanTrue/False. | 182 // generate JumpIfToBooleanTrue/False. |
| 183 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 183 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
| 184 .JumpIfTrue(&start) | 184 .JumpIfTrue(&start) |
| 185 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 185 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
| 186 .JumpIfFalse(&start); | 186 .JumpIfFalse(&start); |
| 187 | 187 |
| 188 builder.EnterBlock() | 188 // Emit throw in it's own basic block so that the rest of the code isn't |
| 189 .Throw() | 189 // omitted due to being dead. |
| 190 .LeaveBlock(); | 190 BytecodeLabel after_throw; |
| 191 builder.Jump(&after_throw) |
| 192 .Throw() |
| 193 .Bind(&after_throw); |
| 191 | 194 |
| 192 builder.ForInPrepare(reg).ForInDone(reg).ForInNext(reg, reg); | 195 builder.ForInPrepare(reg).ForInDone(reg).ForInNext(reg, reg); |
| 193 | 196 |
| 194 // Wide constant pool loads | 197 // Wide constant pool loads |
| 195 for (int i = 0; i < 256; i++) { | 198 for (int i = 0; i < 256; i++) { |
| 196 // Emit junk in constant pool to force wide constant pool index. | 199 // Emit junk in constant pool to force wide constant pool index. |
| 197 builder.GetConstantPoolEntry(handle(Smi::FromInt(i), isolate())); | 200 builder.GetConstantPoolEntry(handle(Smi::FromInt(i), isolate())); |
| 198 } | 201 } |
| 199 builder.LoadLiteral(Smi::FromInt(20000000)); | 202 builder.LoadLiteral(Smi::FromInt(20000000)); |
| 200 | 203 |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 476 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { | 479 TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { |
| 477 BytecodeArrayBuilder builder(isolate(), zone()); | 480 BytecodeArrayBuilder builder(isolate(), zone()); |
| 478 builder.set_parameter_count(0); | 481 builder.set_parameter_count(0); |
| 479 builder.set_locals_count(1); | 482 builder.set_locals_count(1); |
| 480 builder.set_context_count(0); | 483 builder.set_context_count(0); |
| 481 Register reg(0); | 484 Register reg(0); |
| 482 | 485 |
| 483 BytecodeLabel label0, label1, label2, label3, label4; | 486 BytecodeLabel label0, label1, label2, label3, label4; |
| 484 builder.Bind(&label0) | 487 builder.Bind(&label0) |
| 485 .Jump(&label0) | 488 .Jump(&label0) |
| 489 .Bind(&label1) |
| 486 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 490 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
| 487 .Bind(&label1) | |
| 488 .JumpIfTrue(&label1) | 491 .JumpIfTrue(&label1) |
| 492 .Bind(&label2) |
| 489 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 493 .CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
| 490 .Bind(&label2) | |
| 491 .JumpIfFalse(&label2) | 494 .JumpIfFalse(&label2) |
| 495 .Bind(&label3) |
| 492 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 496 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
| 493 .Bind(&label3) | |
| 494 .JumpIfTrue(&label3) | 497 .JumpIfTrue(&label3) |
| 498 .Bind(&label4) |
| 495 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 499 .BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
| 496 .Bind(&label4) | |
| 497 .JumpIfFalse(&label4); | 500 .JumpIfFalse(&label4); |
| 498 for (int i = 0; i < 64; i++) { | 501 for (int i = 0; i < 63; i++) { |
| 499 builder.Jump(&label4); | 502 builder.Jump(&label4); |
| 500 } | 503 } |
| 501 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 504 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
| 502 .JumpIfFalse(&label4); | 505 .JumpIfFalse(&label4); |
| 503 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) | 506 builder.BinaryOperation(Token::Value::ADD, reg, Strength::WEAK) |
| 504 .JumpIfTrue(&label3); | 507 .JumpIfTrue(&label3); |
| 505 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 508 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
| 506 .JumpIfFalse(&label2); | 509 .JumpIfFalse(&label2); |
| 507 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) | 510 builder.CompareOperation(Token::Value::EQ, reg, Strength::WEAK) |
| 508 .JumpIfTrue(&label1); | 511 .JumpIfTrue(&label1); |
| 509 builder.Jump(&label0); | 512 builder.Jump(&label0); |
| 510 builder.Return(); | 513 builder.Return(); |
| 511 | 514 |
| 512 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 515 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
| 513 BytecodeArrayIterator iterator(array); | 516 BytecodeArrayIterator iterator(array); |
| 514 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 517 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
| 515 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 518 CHECK_EQ(iterator.GetImmediateOperand(0), 0); |
| 516 iterator.Advance(); | 519 iterator.Advance(); |
| 517 // Ignore compare operation. | 520 // Ignore compare operation. |
| 518 iterator.Advance(); | 521 iterator.Advance(); |
| 519 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); | 522 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); |
| 520 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 523 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
| 521 iterator.Advance(); | 524 iterator.Advance(); |
| 522 // Ignore compare operation. | 525 // Ignore compare operation. |
| 523 iterator.Advance(); | 526 iterator.Advance(); |
| 524 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); | 527 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse); |
| 525 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 528 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
| 526 iterator.Advance(); | 529 iterator.Advance(); |
| 527 // Ignore binary operation. | 530 // Ignore binary operation. |
| 528 iterator.Advance(); | 531 iterator.Advance(); |
| 529 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); | 532 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue); |
| 530 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 533 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
| 531 iterator.Advance(); | 534 iterator.Advance(); |
| 532 // Ignore binary operation. | 535 // Ignore binary operation. |
| 533 iterator.Advance(); | 536 iterator.Advance(); |
| 534 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); | 537 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse); |
| 535 CHECK_EQ(iterator.GetImmediateOperand(0), 0); | 538 CHECK_EQ(iterator.GetImmediateOperand(0), -2); |
| 536 iterator.Advance(); | 539 iterator.Advance(); |
| 537 for (int i = 0; i < 64; i++) { | 540 for (int i = 0; i < 63; i++) { |
| 538 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); | 541 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump); |
| 539 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 2); | 542 CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 4); |
| 540 iterator.Advance(); | 543 iterator.Advance(); |
| 541 } | 544 } |
| 542 // Ignore binary operation. | 545 // Ignore binary operation. |
| 543 iterator.Advance(); | 546 iterator.Advance(); |
| 544 CHECK_EQ(iterator.current_bytecode(), | 547 CHECK_EQ(iterator.current_bytecode(), |
| 545 Bytecode::kJumpIfToBooleanFalseConstant); | 548 Bytecode::kJumpIfToBooleanFalseConstant); |
| 546 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -132); | 549 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -132); |
| 547 iterator.Advance(); | 550 iterator.Advance(); |
| 548 // Ignore binary operation. | 551 // Ignore binary operation. |
| 549 iterator.Advance(); | 552 iterator.Advance(); |
| 550 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); | 553 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant); |
| 551 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -140); | 554 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -140); |
| 552 iterator.Advance(); | 555 iterator.Advance(); |
| 553 // Ignore compare operation. | 556 // Ignore compare operation. |
| 554 iterator.Advance(); | 557 iterator.Advance(); |
| 555 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); | 558 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant); |
| 556 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -148); | 559 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -148); |
| 557 iterator.Advance(); | 560 iterator.Advance(); |
| 558 // Ignore compare operation. | 561 // Ignore compare operation. |
| 559 iterator.Advance(); | 562 iterator.Advance(); |
| 560 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); | 563 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant); |
| 561 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -156); | 564 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -156); |
| 562 iterator.Advance(); | 565 iterator.Advance(); |
| 563 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); | 566 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant); |
| 564 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -162); | 567 CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -160); |
| 565 iterator.Advance(); | 568 iterator.Advance(); |
| 566 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 569 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 567 iterator.Advance(); | 570 iterator.Advance(); |
| 568 CHECK(iterator.done()); | 571 CHECK(iterator.done()); |
| 569 } | 572 } |
| 570 | 573 |
| 571 | 574 |
| 572 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { | 575 TEST_F(BytecodeArrayBuilderTest, LabelReuse) { |
| 573 BytecodeArrayBuilder builder(isolate(), zone()); | 576 BytecodeArrayBuilder builder(isolate(), zone()); |
| 574 builder.set_parameter_count(0); | 577 builder.set_parameter_count(0); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 631 CHECK(iterator.done()); | 634 CHECK(iterator.done()); |
| 632 } | 635 } |
| 633 | 636 |
| 634 | 637 |
| 635 TEST_F(BytecodeArrayBuilderTest, ToBoolean) { | 638 TEST_F(BytecodeArrayBuilderTest, ToBoolean) { |
| 636 BytecodeArrayBuilder builder(isolate(), zone()); | 639 BytecodeArrayBuilder builder(isolate(), zone()); |
| 637 builder.set_parameter_count(0); | 640 builder.set_parameter_count(0); |
| 638 builder.set_locals_count(0); | 641 builder.set_locals_count(0); |
| 639 builder.set_context_count(0); | 642 builder.set_context_count(0); |
| 640 | 643 |
| 641 // Check ToBoolean emitted at start of block. | 644 // Check ToBoolean emitted at start of a basic block. |
| 642 builder.EnterBlock().CastAccumulatorToBoolean(); | 645 builder.CastAccumulatorToBoolean(); |
| 643 | 646 |
| 644 // Check ToBoolean emitted preceding bytecode is non-boolean. | 647 // Check ToBoolean emitted preceding bytecode is non-boolean. |
| 645 builder.LoadNull().CastAccumulatorToBoolean(); | 648 builder.LoadNull().CastAccumulatorToBoolean(); |
| 646 | 649 |
| 647 // Check ToBoolean omitted if preceding bytecode is boolean. | 650 // Check ToBoolean omitted if preceding bytecode is boolean. |
| 648 builder.LoadFalse().CastAccumulatorToBoolean(); | 651 builder.LoadFalse().CastAccumulatorToBoolean(); |
| 649 | 652 |
| 650 // Check ToBoolean emitted if it is at the start of the next block. | 653 // Check ToBoolean emitted if it is at the start of a basic block caused by a |
| 654 // bound label. |
| 655 BytecodeLabel label; |
| 651 builder.LoadFalse() | 656 builder.LoadFalse() |
| 652 .LeaveBlock() | 657 .Bind(&label) |
| 653 .EnterBlock() | 658 .CastAccumulatorToBoolean(); |
| 654 .CastAccumulatorToBoolean() | 659 |
| 655 .LeaveBlock(); | 660 // Check ToBoolean emitted if it is at the start of a basic block caused by a |
| 661 // jump. |
| 662 builder.LoadFalse() |
| 663 .JumpIfTrue(&label) |
| 664 .CastAccumulatorToBoolean(); |
| 656 | 665 |
| 657 builder.Return(); | 666 builder.Return(); |
| 658 | 667 |
| 659 Handle<BytecodeArray> array = builder.ToBytecodeArray(); | 668 Handle<BytecodeArray> array = builder.ToBytecodeArray(); |
| 660 BytecodeArrayIterator iterator(array); | 669 BytecodeArrayIterator iterator(array); |
| 661 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); | 670 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 662 iterator.Advance(); | 671 iterator.Advance(); |
| 663 | 672 |
| 664 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaNull); | 673 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaNull); |
| 665 iterator.Advance(); | 674 iterator.Advance(); |
| 666 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); | 675 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 667 iterator.Advance(); | 676 iterator.Advance(); |
| 668 | 677 |
| 669 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); | 678 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
| 670 iterator.Advance(); | 679 iterator.Advance(); |
| 671 | 680 |
| 672 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); | 681 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
| 673 iterator.Advance(); | 682 iterator.Advance(); |
| 674 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); | 683 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 675 iterator.Advance(); | 684 iterator.Advance(); |
| 676 | 685 |
| 686 CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaFalse); |
| 687 iterator.Advance(); |
| 688 CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue); |
| 689 iterator.Advance(); |
| 690 CHECK_EQ(iterator.current_bytecode(), Bytecode::kToBoolean); |
| 691 iterator.Advance(); |
| 692 |
| 677 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); | 693 CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); |
| 678 iterator.Advance(); | 694 iterator.Advance(); |
| 679 CHECK(iterator.done()); | 695 CHECK(iterator.done()); |
| 680 } | 696 } |
| 681 | 697 |
| 682 | 698 |
| 683 } // namespace interpreter | 699 } // namespace interpreter |
| 684 } // namespace internal | 700 } // namespace internal |
| 685 } // namespace v8 | 701 } // namespace v8 |
| OLD | NEW |