| Index: test/unittests/interpreter/bytecode-array-builder-unittest.cc
|
| diff --git a/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
|
| index 357aa673c5d723b11da94c8915b89d37b5810355..4d21dee240c28e747b0b4e81140d69f96ee93c56 100644
|
| --- a/test/unittests/interpreter/bytecode-array-builder-unittest.cc
|
| +++ b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
|
| @@ -5,6 +5,7 @@
|
| #include "src/v8.h"
|
|
|
| #include "src/interpreter/bytecode-array-builder.h"
|
| +#include "src/interpreter/bytecode-array-iterator.h"
|
| #include "test/unittests/test-utils.h"
|
|
|
| namespace v8 {
|
| @@ -48,14 +49,39 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
| // Call operations.
|
| builder.Call(reg, reg, 0);
|
|
|
| - // Emit binary operators invocations.
|
| + // Emit binary operator invocations.
|
| builder.BinaryOperation(Token::Value::ADD, reg)
|
| .BinaryOperation(Token::Value::SUB, reg)
|
| .BinaryOperation(Token::Value::MUL, reg)
|
| .BinaryOperation(Token::Value::DIV, reg)
|
| .BinaryOperation(Token::Value::MOD, reg);
|
|
|
| + // Emit test operator invocations.
|
| + builder.CompareOperation(Token::Value::EQ, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::NE, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::EQ_STRICT, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::NE_STRICT, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::LT, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::GT, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::LTE, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::GTE, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::INSTANCEOF, reg, LanguageMode::SLOPPY)
|
| + .CompareOperation(Token::Value::IN, reg, LanguageMode::SLOPPY);
|
| +
|
| + // Emit cast operator invocations.
|
| + builder.LoadNull().CastAccumulatorToBoolean();
|
| +
|
| // Emit control flow. Return must be the last instruction.
|
| + BytecodeLabel start;
|
| + builder.Bind(&start);
|
| + // Short jumps with Imm8 operands
|
| + builder.Jump(&start).JumpIfTrue(&start).JumpIfFalse(&start);
|
| + // Insert dummy ops to force longer jumps
|
| + for (int i = 0; i < 128; i++) {
|
| + builder.LoadTrue();
|
| + }
|
| + // Longer jumps requiring Constant operand
|
| + builder.Jump(&start).JumpIfTrue(&start).JumpIfFalse(&start);
|
| builder.Return();
|
|
|
| // Generate BytecodeArray.
|
| @@ -180,6 +206,189 @@ TEST_F(BytecodeArrayBuilderTest, Constants) {
|
| CHECK_EQ(array->constant_pool()->length(), 3);
|
| }
|
|
|
| +
|
| +TEST_F(BytecodeArrayBuilderTest, ForwardJumps) {
|
| + static const int kFarJumpDistance = 256;
|
| +
|
| + BytecodeArrayBuilder builder(isolate(), zone());
|
| + builder.set_parameter_count(0);
|
| + builder.set_locals_count(0);
|
| +
|
| + BytecodeLabel far0, far1, far2;
|
| + BytecodeLabel near0, near1, near2;
|
| +
|
| + builder.Jump(&near0)
|
| + .JumpIfTrue(&near1)
|
| + .JumpIfFalse(&near2)
|
| + .Bind(&near0)
|
| + .Bind(&near1)
|
| + .Bind(&near2)
|
| + .Jump(&far0)
|
| + .JumpIfTrue(&far1)
|
| + .JumpIfFalse(&far2);
|
| + for (int i = 0; i < kFarJumpDistance - 6; i++) {
|
| + builder.LoadUndefined();
|
| + }
|
| + builder.Bind(&far0).Bind(&far1).Bind(&far2);
|
| + builder.Return();
|
| +
|
| + Handle<BytecodeArray> array = builder.ToBytecodeArray();
|
| + DCHECK_EQ(array->length(), 12 + kFarJumpDistance - 6 + 1);
|
| +
|
| + BytecodeArrayIterator iterator(array);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 6);
|
| + iterator.Advance();
|
| +
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 4);
|
| + iterator.Advance();
|
| +
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 2);
|
| + iterator.Advance();
|
| +
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
|
| + CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
|
| + Smi::FromInt(kFarJumpDistance));
|
| + CHECK_EQ(
|
| + array->get(iterator.current_offset() +
|
| + Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()),
|
| + Bytecodes::ToByte(Bytecode::kReturn));
|
| + iterator.Advance();
|
| +
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant);
|
| + CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
|
| + Smi::FromInt(kFarJumpDistance - 2));
|
| + CHECK_EQ(
|
| + array->get(iterator.current_offset() +
|
| + Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()),
|
| + Bytecodes::ToByte(Bytecode::kReturn));
|
| + iterator.Advance();
|
| +
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant);
|
| + CHECK_EQ(*iterator.GetConstantForIndexOperand(0),
|
| + Smi::FromInt(kFarJumpDistance - 4));
|
| + CHECK_EQ(
|
| + array->get(iterator.current_offset() +
|
| + Smi::cast(*iterator.GetConstantForIndexOperand(0))->value()),
|
| + Bytecodes::ToByte(Bytecode::kReturn));
|
| + iterator.Advance();
|
| +}
|
| +
|
| +
|
| +TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
|
| + BytecodeArrayBuilder builder(isolate(), zone());
|
| + builder.set_parameter_count(0);
|
| + builder.set_locals_count(0);
|
| +
|
| + BytecodeLabel label0, label1, label2;
|
| + builder.Bind(&label0)
|
| + .Jump(&label0)
|
| + .Bind(&label1)
|
| + .JumpIfTrue(&label1)
|
| + .Bind(&label2)
|
| + .JumpIfFalse(&label2);
|
| + for (int i = 0; i < 64; i++) {
|
| + builder.Jump(&label2);
|
| + }
|
| + builder.JumpIfFalse(&label2);
|
| + builder.JumpIfTrue(&label1);
|
| + builder.Jump(&label0);
|
| + builder.Return();
|
| +
|
| + Handle<BytecodeArray> array = builder.ToBytecodeArray();
|
| + BytecodeArrayIterator iterator(array);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 0);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 0);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 0);
|
| + iterator.Advance();
|
| + for (int i = 0; i < 64; i++) {
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), -i * 2 - 2);
|
| + iterator.Advance();
|
| + }
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant);
|
| + CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -130);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant);
|
| + CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -134);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
|
| + CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -138);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
|
| + iterator.Advance();
|
| + CHECK(iterator.done());
|
| +}
|
| +
|
| +
|
| +TEST_F(BytecodeArrayBuilderTest, LabelReuse) {
|
| + BytecodeArrayBuilder builder(isolate(), zone());
|
| + builder.set_parameter_count(0);
|
| + builder.set_locals_count(0);
|
| +
|
| + // Labels can only have 1 forward reference, but
|
| + // can be referred to mulitple times once bound.
|
| + BytecodeLabel label;
|
| +
|
| + builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label).Return();
|
| +
|
| + Handle<BytecodeArray> array = builder.ToBytecodeArray();
|
| + BytecodeArrayIterator iterator(array);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 2);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 0);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), -2);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
|
| + iterator.Advance();
|
| + CHECK(iterator.done());
|
| +}
|
| +
|
| +
|
| +TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
|
| + static const int kRepeats = 3;
|
| +
|
| + BytecodeArrayBuilder builder(isolate(), zone());
|
| + builder.set_parameter_count(0);
|
| + builder.set_locals_count(0);
|
| +
|
| + for (int i = 0; i < kRepeats; i++) {
|
| + BytecodeLabel label;
|
| + builder.Jump(&label).Bind(&label).Jump(&label).Jump(&label);
|
| + }
|
| +
|
| + builder.Return();
|
| +
|
| + Handle<BytecodeArray> array = builder.ToBytecodeArray();
|
| + BytecodeArrayIterator iterator(array);
|
| + for (int i = 0; i < kRepeats; i++) {
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 2);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), 0);
|
| + iterator.Advance();
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.GetSmi8Operand(0), -2);
|
| + iterator.Advance();
|
| + }
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
|
| + iterator.Advance();
|
| + CHECK(iterator.done());
|
| +}
|
| +
|
| +
|
| } // namespace interpreter
|
| } // namespace internal
|
| } // namespace v8
|
|
|