| 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 ed8fe3aa0e77639644f45b06e48c73feeb904d35..07f2103ba49914c35c2f69d5fb12fe7f720888c2 100644
|
| --- a/test/unittests/interpreter/bytecode-array-builder-unittest.cc
|
| +++ b/test/unittests/interpreter/bytecode-array-builder-unittest.cc
|
| @@ -160,6 +160,21 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
| .JumpIfUndefined(&start)
|
| .JumpIfNotHole(&start);
|
|
|
| + // Longer jumps with constant operands
|
| + BytecodeLabel end[8];
|
| + builder.Jump(&end[0])
|
| + .LoadTrue()
|
| + .JumpIfTrue(&end[1])
|
| + .LoadTrue()
|
| + .JumpIfFalse(&end[2])
|
| + .LoadLiteral(Smi::FromInt(0))
|
| + .JumpIfTrue(&end[3])
|
| + .LoadLiteral(Smi::FromInt(0))
|
| + .JumpIfFalse(&end[4])
|
| + .JumpIfNull(&end[5])
|
| + .JumpIfUndefined(&end[6])
|
| + .JumpIfNotHole(&end[7]);
|
| +
|
| // Perform an operation that returns boolean value to
|
| // generate JumpIfTrue/False
|
| builder.CompareOperation(Token::Value::EQ, reg)
|
| @@ -222,9 +237,13 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
| // Emit wide global load / store operations.
|
| builder.LoadGlobal(name, 1024, TypeofMode::NOT_INSIDE_TYPEOF)
|
| .LoadGlobal(name, 1024, TypeofMode::INSIDE_TYPEOF)
|
| + .LoadGlobal(name, 1024, TypeofMode::INSIDE_TYPEOF)
|
| .StoreGlobal(name, 1024, LanguageMode::SLOPPY)
|
| .StoreGlobal(wide_name, 1, LanguageMode::STRICT);
|
|
|
| + // Emit extra wide global load.
|
| + builder.LoadGlobal(name, 1024 * 1024, TypeofMode::NOT_INSIDE_TYPEOF);
|
| +
|
| // Emit wide load / store property operations.
|
| builder.LoadNamedProperty(reg, wide_name, 0)
|
| .LoadKeyedProperty(reg, 2056)
|
| @@ -271,27 +290,38 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
| .JumpIfFalse(&start);
|
|
|
| builder.Debugger();
|
| -
|
| + for (size_t i = 0; i < arraysize(end); i++) {
|
| + builder.Bind(&end[i]);
|
| + }
|
| builder.Return();
|
|
|
| // Generate BytecodeArray.
|
| Handle<BytecodeArray> the_array = builder.ToBytecodeArray();
|
| CHECK_EQ(the_array->frame_size(),
|
| - (builder.fixed_and_temporary_register_count() +
|
| - builder.translation_register_count()) *
|
| - kPointerSize);
|
| + builder.fixed_and_temporary_register_count() * kPointerSize);
|
|
|
| // Build scorecard of bytecodes encountered in the BytecodeArray.
|
| std::vector<int> scorecard(Bytecodes::ToByte(Bytecode::kLast) + 1);
|
| +
|
| Bytecode final_bytecode = Bytecode::kLdaZero;
|
| int i = 0;
|
| while (i < the_array->length()) {
|
| uint8_t code = the_array->get(i);
|
| scorecard[code] += 1;
|
| final_bytecode = Bytecodes::FromByte(code);
|
| - i += Bytecodes::Size(Bytecodes::FromByte(code));
|
| + int operand_scale = Bytecodes::GetPrefixBytecodeScale(final_bytecode);
|
| + if (operand_scale > 1) {
|
| + code = the_array->get(i + 1);
|
| + final_bytecode = Bytecodes::FromByte(code);
|
| + i += 1 + Bytecodes::Size(final_bytecode, operand_scale);
|
| + } else {
|
| + i += Bytecodes::Size(final_bytecode, operand_scale);
|
| + }
|
| }
|
|
|
| + // Insert entry for illegal bytecode as this is never willingly emitted.
|
| + scorecard[Bytecodes::ToByte(Bytecode::kIllegal)] = 1;
|
| +
|
| // Check return occurs at the end and only once in the BytecodeArray.
|
| CHECK_EQ(final_bytecode, Bytecode::kReturn);
|
| CHECK_EQ(scorecard[Bytecodes::ToByte(final_bytecode)], 1);
|
| @@ -329,7 +359,7 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
|
|
|
| TEST_F(BytecodeArrayBuilderTest, RegisterValues) {
|
| int index = 1;
|
| - uint8_t operand = static_cast<uint8_t>(-index);
|
| + int32_t operand = -index;
|
|
|
| Register the_register(index);
|
| CHECK_EQ(the_register.index(), index);
|
| @@ -530,6 +560,12 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
|
| for (int i = 0; i < 63; i++) {
|
| builder.Jump(&label4);
|
| }
|
| +
|
| + // Add padding to force wide backwards jumps.
|
| + for (int i = 0; i < 256; i++) {
|
| + builder.LoadTrue();
|
| + }
|
| +
|
| builder.BinaryOperation(Token::Value::ADD, reg).JumpIfFalse(&label4);
|
| builder.BinaryOperation(Token::Value::ADD, reg).JumpIfTrue(&label3);
|
| builder.CompareOperation(Token::Value::EQ, reg).JumpIfFalse(&label2);
|
| @@ -545,51 +581,65 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) {
|
| // Ignore compare operation.
|
| iterator.Advance();
|
| CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
|
| + CHECK_EQ(iterator.current_operand_scale(), 1);
|
| CHECK_EQ(iterator.GetImmediateOperand(0), -2);
|
| iterator.Advance();
|
| // Ignore compare operation.
|
| iterator.Advance();
|
| CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
|
| + CHECK_EQ(iterator.current_operand_scale(), 1);
|
| CHECK_EQ(iterator.GetImmediateOperand(0), -2);
|
| iterator.Advance();
|
| // Ignore binary operation.
|
| iterator.Advance();
|
| CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue);
|
| + CHECK_EQ(iterator.current_operand_scale(), 1);
|
| CHECK_EQ(iterator.GetImmediateOperand(0), -2);
|
| iterator.Advance();
|
| // Ignore binary operation.
|
| iterator.Advance();
|
| CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse);
|
| + CHECK_EQ(iterator.current_operand_scale(), 1);
|
| CHECK_EQ(iterator.GetImmediateOperand(0), -2);
|
| iterator.Advance();
|
| for (int i = 0; i < 63; i++) {
|
| CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.current_operand_scale(), 1);
|
| CHECK_EQ(iterator.GetImmediateOperand(0), -i * 2 - 4);
|
| iterator.Advance();
|
| }
|
| + // Check padding to force wide backwards jumps.
|
| + for (int i = 0; i < 256; i++) {
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaTrue);
|
| + iterator.Advance();
|
| + }
|
| // Ignore binary operation.
|
| iterator.Advance();
|
| - CHECK_EQ(iterator.current_bytecode(),
|
| - Bytecode::kJumpIfToBooleanFalseConstant);
|
| - CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -132);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanFalse);
|
| + CHECK_EQ(iterator.current_operand_scale(), 2);
|
| + CHECK_EQ(iterator.GetImmediateOperand(0), -389);
|
| iterator.Advance();
|
| // Ignore binary operation.
|
| iterator.Advance();
|
| - CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrueConstant);
|
| - CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -140);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfToBooleanTrue);
|
| + CHECK_EQ(iterator.current_operand_scale(), 2);
|
| + CHECK_EQ(iterator.GetImmediateOperand(0), -399);
|
| iterator.Advance();
|
| // Ignore compare operation.
|
| iterator.Advance();
|
| - CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalseConstant);
|
| - CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -148);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfFalse);
|
| + CHECK_EQ(iterator.current_operand_scale(), 2);
|
| + CHECK_EQ(iterator.GetImmediateOperand(0), -409);
|
| iterator.Advance();
|
| // Ignore compare operation.
|
| iterator.Advance();
|
| - CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrueConstant);
|
| - CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -156);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpIfTrue);
|
| + CHECK_EQ(iterator.current_operand_scale(), 2);
|
| + CHECK_EQ(iterator.GetImmediateOperand(0), -419);
|
| iterator.Advance();
|
| - CHECK_EQ(iterator.current_bytecode(), Bytecode::kJumpConstant);
|
| - CHECK_EQ(Smi::cast(*iterator.GetConstantForIndexOperand(0))->value(), -160);
|
| + CHECK_EQ(iterator.current_bytecode(), Bytecode::kJump);
|
| + CHECK_EQ(iterator.current_operand_scale(), 2);
|
| + CHECK_EQ(iterator.GetImmediateOperand(0), -425);
|
| iterator.Advance();
|
| CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
|
| iterator.Advance();
|
| @@ -651,6 +701,82 @@ TEST_F(BytecodeArrayBuilderTest, LabelAddressReuse) {
|
| CHECK(iterator.done());
|
| }
|
|
|
| +TEST_F(BytecodeArrayBuilderTest, OperandScales) {
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(OperandSize::kByte), 1);
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(OperandSize::kShort), 2);
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(OperandSize::kQuad), 4);
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(
|
| + OperandSize::kShort, OperandSize::kShort, OperandSize::kShort,
|
| + OperandSize::kShort),
|
| + 2);
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(
|
| + OperandSize::kQuad, OperandSize::kShort, OperandSize::kShort,
|
| + OperandSize::kShort),
|
| + 4);
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(
|
| + OperandSize::kShort, OperandSize::kQuad, OperandSize::kShort,
|
| + OperandSize::kShort),
|
| + 4);
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(
|
| + OperandSize::kShort, OperandSize::kShort, OperandSize::kQuad,
|
| + OperandSize::kShort),
|
| + 4);
|
| + CHECK_EQ(BytecodeArrayBuilder::OperandScale(
|
| + OperandSize::kShort, OperandSize::kShort, OperandSize::kShort,
|
| + OperandSize::kQuad),
|
| + 4);
|
| +}
|
| +
|
| +TEST_F(BytecodeArrayBuilderTest, SizesForSignOperands) {
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(0) == OperandSize::kByte);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt8) ==
|
| + OperandSize::kByte);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt8) ==
|
| + OperandSize::kByte);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt8 + 1) ==
|
| + OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt8 - 1) ==
|
| + OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt16) ==
|
| + OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt16) ==
|
| + OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt16 + 1) ==
|
| + OperandSize::kQuad);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt16 - 1) ==
|
| + OperandSize::kQuad);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMaxInt) ==
|
| + OperandSize::kQuad);
|
| + CHECK(BytecodeArrayBuilder::SizeForSignedOperand(kMinInt) ==
|
| + OperandSize::kQuad);
|
| +}
|
| +
|
| +TEST_F(BytecodeArrayBuilderTest, SizesForUnsignOperands) {
|
| + // int overloads
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(0) == OperandSize::kByte);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt8) ==
|
| + OperandSize::kByte);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt8 + 1) ==
|
| + OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt16) ==
|
| + OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(kMaxUInt16 + 1) ==
|
| + OperandSize::kQuad);
|
| + // size_t overloads
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(static_cast<size_t>(0)) ==
|
| + OperandSize::kByte);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
|
| + static_cast<size_t>(kMaxUInt8)) == OperandSize::kByte);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
|
| + static_cast<size_t>(kMaxUInt8 + 1)) == OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
|
| + static_cast<size_t>(kMaxUInt16)) == OperandSize::kShort);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
|
| + static_cast<size_t>(kMaxUInt16 + 1)) == OperandSize::kQuad);
|
| + CHECK(BytecodeArrayBuilder::SizeForUnsignedOperand(
|
| + static_cast<size_t>(kMaxUInt32)) == OperandSize::kQuad);
|
| +}
|
| +
|
| } // namespace interpreter
|
| } // namespace internal
|
| } // namespace v8
|
|
|