Index: test/cctest/interpreter/test-interpreter.cc |
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc |
index 511e891d4939f0cda370d05496158367ca01dfb8..b4b7280748291047a73fa45641de96104cfd83e3 100644 |
--- a/test/cctest/interpreter/test-interpreter.cc |
+++ b/test/cctest/interpreter/test-interpreter.cc |
@@ -7,6 +7,7 @@ |
#include "src/execution.h" |
#include "src/handles.h" |
#include "src/interpreter/bytecode-array-builder.h" |
+#include "src/interpreter/bytecode-array-iterator.h" |
#include "src/interpreter/interpreter.h" |
#include "test/cctest/cctest.h" |
#include "test/cctest/interpreter/interpreter-tester.h" |
@@ -992,7 +993,6 @@ TEST(InterpreterConditionalJumps) { |
CHECK_EQ(Smi::cast(*return_value)->value(), 7); |
} |
- |
TEST(InterpreterConditionalJumps2) { |
// TODO(oth): Add tests for all conditional jumps near and far. |
HandleAndZoneScope handles; |
@@ -1026,6 +1026,92 @@ TEST(InterpreterConditionalJumps2) { |
CHECK_EQ(Smi::cast(*return_value)->value(), 7); |
} |
+TEST(InterpreterJumpConstantWith16BitOperand) { |
+ HandleAndZoneScope handles; |
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
+ 0, 257); |
+ Register reg(0), scratch(256); |
+ BytecodeLabel done; |
+ |
+ builder.LoadLiteral(Smi::FromInt(0)); |
+ builder.StoreAccumulatorInRegister(reg); |
+ // Consume all 8-bit operands |
+ for (int i = 1; i <= 256; i++) { |
+ builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i)); |
+ builder.BinaryOperation(Token::Value::ADD, reg); |
+ builder.StoreAccumulatorInRegister(reg); |
+ } |
+ builder.Jump(&done); |
+ |
+ // Emit more than 16-bit immediate operands worth of code to jump over. |
+ for (int i = 0; i < 6600; i++) { |
+ builder.LoadLiteral(Smi::FromInt(0)); // 1-byte |
+ builder.BinaryOperation(Token::Value::ADD, scratch); // 4-bytes |
+ builder.StoreAccumulatorInRegister(scratch); // 4-bytes |
+ builder.MoveRegister(scratch, reg); // 6-bytes |
+ } |
+ builder.Bind(&done); |
+ builder.LoadAccumulatorWithRegister(reg); |
+ builder.Return(); |
+ |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ BytecodeArrayIterator iterator(bytecode_array); |
+ |
+ bool found_16bit_constant_jump = false; |
+ while (!iterator.done()) { |
+ if (iterator.current_bytecode() == Bytecode::kJumpConstant && |
+ iterator.current_operand_scale() == OperandScale::kDouble) { |
+ found_16bit_constant_jump = true; |
+ break; |
+ } |
+ iterator.Advance(); |
+ } |
+ CHECK(found_16bit_constant_jump); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array); |
+ auto callable = tester.GetCallable<>(); |
+ Handle<Object> return_value = callable().ToHandleChecked(); |
+ CHECK_EQ(Smi::cast(*return_value)->value(), 256.0 / 2 * (1 + 256)); |
+} |
+ |
+TEST(InterpreterJumpWith32BitOperand) { |
+ HandleAndZoneScope handles; |
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1, |
+ 0, 1); |
+ Register reg(0); |
+ BytecodeLabel done; |
+ |
+ builder.LoadLiteral(Smi::FromInt(0)); |
+ builder.StoreAccumulatorInRegister(reg); |
+ // Consume all 16-bit constant pool entries |
+ for (int i = 1; i <= 65536; i++) { |
+ builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i)); |
+ } |
+ builder.Jump(&done); |
+ builder.LoadLiteral(Smi::FromInt(0)); |
+ builder.Bind(&done); |
+ builder.Return(); |
+ |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ BytecodeArrayIterator iterator(bytecode_array); |
+ |
+ bool found_32bit_jump = false; |
+ while (!iterator.done()) { |
+ if (iterator.current_bytecode() == Bytecode::kJump && |
+ iterator.current_operand_scale() == OperandScale::kQuadruple) { |
+ found_32bit_jump = true; |
+ break; |
+ } |
+ iterator.Advance(); |
+ } |
+ CHECK(found_32bit_jump); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array); |
+ auto callable = tester.GetCallable<>(); |
+ Handle<Object> return_value = callable().ToHandleChecked(); |
+ CHECK_EQ(Smi::cast(*return_value)->value(), 65536.0); |
+} |
+ |
static const Token::Value kComparisonTypes[] = { |
Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT, |
Token::Value::LT, Token::Value::LTE, Token::Value::GT, |