Commit 0c32e98e authored by oth's avatar oth Committed by Commit bot

[interpreter] A few code coverage improvements.

Improves code coverage of bytecode array builder and constant
array builder.

Fixes initial index for constant pool slice for kQuad operands.

BUG=v8:4280,chromium:599000
LOG=N
TBR=rmcilroy@chromium.org

Review URL: https://codereview.chromium.org/1845313002

Cr-Commit-Position: refs/heads/master@{#35201}
parent 942f255f
...@@ -344,16 +344,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { ...@@ -344,16 +344,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBooleanConstant(bool value) {
if (value) {
LoadTrue();
} else {
LoadFalse();
}
return *this;
}
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
Register reg) { Register reg) {
if (!IsRegisterInAccumulator(reg)) { if (!IsRegisterInAccumulator(reg)) {
......
...@@ -82,7 +82,6 @@ class BytecodeArrayBuilder final : public ZoneObject { ...@@ -82,7 +82,6 @@ class BytecodeArrayBuilder final : public ZoneObject {
BytecodeArrayBuilder& LoadTheHole(); BytecodeArrayBuilder& LoadTheHole();
BytecodeArrayBuilder& LoadTrue(); BytecodeArrayBuilder& LoadTrue();
BytecodeArrayBuilder& LoadFalse(); BytecodeArrayBuilder& LoadFalse();
BytecodeArrayBuilder& LoadBooleanConstant(bool value);
// Global loads to the accumulator and stores from the accumulator. // Global loads to the accumulator and stores from the accumulator.
BytecodeArrayBuilder& LoadGlobal(const Handle<String> name, int feedback_slot, BytecodeArrayBuilder& LoadGlobal(const Handle<String> name, int feedback_slot,
......
...@@ -59,7 +59,7 @@ ConstantArrayBuilder::ConstantArrayBuilder(Isolate* isolate, Zone* zone) ...@@ -59,7 +59,7 @@ ConstantArrayBuilder::ConstantArrayBuilder(Isolate* isolate, Zone* zone)
idx_slice_[1] = new (zone) ConstantArraySlice( idx_slice_[1] = new (zone) ConstantArraySlice(
zone, k8BitCapacity, k16BitCapacity, OperandSize::kShort); zone, k8BitCapacity, k16BitCapacity, OperandSize::kShort);
idx_slice_[2] = new (zone) ConstantArraySlice( idx_slice_[2] = new (zone) ConstantArraySlice(
zone, k16BitCapacity, k32BitCapacity, OperandSize::kQuad); zone, k8BitCapacity + k16BitCapacity, k32BitCapacity, OperandSize::kQuad);
} }
size_t ConstantArrayBuilder::size() const { size_t ConstantArrayBuilder::size() const {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "src/execution.h" #include "src/execution.h"
#include "src/handles.h" #include "src/handles.h"
#include "src/interpreter/bytecode-array-builder.h" #include "src/interpreter/bytecode-array-builder.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/interpreter.h" #include "src/interpreter/interpreter.h"
#include "test/cctest/cctest.h" #include "test/cctest/cctest.h"
#include "test/cctest/interpreter/interpreter-tester.h" #include "test/cctest/interpreter/interpreter-tester.h"
...@@ -992,7 +993,6 @@ TEST(InterpreterConditionalJumps) { ...@@ -992,7 +993,6 @@ TEST(InterpreterConditionalJumps) {
CHECK_EQ(Smi::cast(*return_value)->value(), 7); CHECK_EQ(Smi::cast(*return_value)->value(), 7);
} }
TEST(InterpreterConditionalJumps2) { TEST(InterpreterConditionalJumps2) {
// TODO(oth): Add tests for all conditional jumps near and far. // TODO(oth): Add tests for all conditional jumps near and far.
HandleAndZoneScope handles; HandleAndZoneScope handles;
...@@ -1026,6 +1026,92 @@ TEST(InterpreterConditionalJumps2) { ...@@ -1026,6 +1026,92 @@ TEST(InterpreterConditionalJumps2) {
CHECK_EQ(Smi::cast(*return_value)->value(), 7); 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[] = { static const Token::Value kComparisonTypes[] = {
Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT, Token::Value::EQ, Token::Value::NE, Token::Value::EQ_STRICT,
Token::Value::LT, Token::Value::LTE, Token::Value::GT, Token::Value::LT, Token::Value::LTE, Token::Value::GT,
......
...@@ -22,7 +22,7 @@ class BytecodeArrayIteratorTest : public TestWithIsolateAndZone { ...@@ -22,7 +22,7 @@ class BytecodeArrayIteratorTest : public TestWithIsolateAndZone {
TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
// Use a builder to create an array with containing multiple bytecodes // Use a builder to create an array with containing multiple bytecodes
// with 0, 1 and 2 operands. // with 0, 1 and 2 operands.
BytecodeArrayBuilder builder(isolate(), zone(), 3, 2, 0); BytecodeArrayBuilder builder(isolate(), zone(), 3, 3, 0);
Factory* factory = isolate()->factory(); Factory* factory = isolate()->factory();
Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718); Handle<HeapObject> heap_num_0 = factory->NewHeapNumber(2.718);
Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647); Handle<HeapObject> heap_num_1 = factory->NewHeapNumber(2147483647);
...@@ -31,7 +31,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { ...@@ -31,7 +31,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
Smi* smi_1 = Smi::FromInt(-65536); Smi* smi_1 = Smi::FromInt(-65536);
Register reg_0(0); Register reg_0(0);
Register reg_1(1); Register reg_1(1);
Register reg_2 = Register::FromParameterIndex(2, builder.parameter_count()); Register param = Register::FromParameterIndex(2, builder.parameter_count());
Handle<String> name = factory->NewStringFromStaticChars("abc"); Handle<String> name = factory->NewStringFromStaticChars("abc");
int name_index = 2; int name_index = 2;
int feedback_slot = 97; int feedback_slot = 97;
...@@ -43,7 +43,9 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { ...@@ -43,7 +43,9 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
.LoadLiteral(smi_1) .LoadLiteral(smi_1)
.LoadAccumulatorWithRegister(reg_0) .LoadAccumulatorWithRegister(reg_0)
.LoadNamedProperty(reg_1, name, feedback_slot) .LoadNamedProperty(reg_1, name, feedback_slot)
.StoreAccumulatorInRegister(reg_2) .StoreAccumulatorInRegister(param)
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, param, 1, reg_0)
.ForInPrepare(reg_0)
.CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1) .CallRuntime(Runtime::kLoadIC_Miss, reg_0, 1)
.Debugger() .Debugger()
.LoadGlobal(name, 0x10000000, TypeofMode::NOT_INSIDE_TYPEOF) .LoadGlobal(name, 0x10000000, TypeofMode::NOT_INSIDE_TYPEOF)
...@@ -51,76 +53,128 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { ...@@ -51,76 +53,128 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
// Test iterator sees the expected output from the builder. // Test iterator sees the expected output from the builder.
BytecodeArrayIterator iterator(builder.ToBytecodeArray()); BytecodeArrayIterator iterator(builder.ToBytecodeArray());
const int kPrefixByteSize = 1;
int offset = 0;
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK(iterator.GetConstantForIndexOperand(0).is_identical_to(heap_num_0)); CHECK(iterator.GetConstantForIndexOperand(0).is_identical_to(heap_num_0));
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaConstant);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK(iterator.GetConstantForIndexOperand(0).is_identical_to(heap_num_1)); CHECK(iterator.GetConstantForIndexOperand(0).is_identical_to(heap_num_1));
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaZero); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaZero);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_0); CHECK_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_0);
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
CHECK_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1); CHECK_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1);
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) +
kPrefixByteSize;
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdar); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdar);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadIC); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLoadIC);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index());
CHECK_EQ(iterator.GetIndexOperand(1), name_index); CHECK_EQ(iterator.GetIndexOperand(1), name_index);
CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot); CHECK_EQ(iterator.GetIndexOperand(2), feedback_slot);
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kLoadIC, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar); CHECK_EQ(iterator.current_bytecode(), Bytecode::kStar);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), param.index());
CHECK_EQ(iterator.GetRegisterOperandRange(0), 1);
CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_2.index()); CHECK_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall);
CHECK_EQ(iterator.GetRegisterOperand(1).index(), param.index());
CHECK_EQ(iterator.GetRegisterOperandRange(1), 1);
CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
CHECK_EQ(iterator.GetRegisterOperand(3).index(), reg_0.index());
CHECK_EQ(iterator.GetRegisterOperandRange(3), 2);
CHECK(!iterator.done());
offset +=
Bytecodes::Size(Bytecode::kCallRuntimeForPair, OperandScale::kSingle);
iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kForInPrepare);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index());
CHECK_EQ(iterator.GetRegisterOperandRange(0), 3);
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kForInPrepare, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime); CHECK_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK_EQ(static_cast<Runtime::FunctionId>(iterator.GetRuntimeIdOperand(0)), CHECK_EQ(static_cast<Runtime::FunctionId>(iterator.GetRuntimeIdOperand(0)),
Runtime::kLoadIC_Miss); Runtime::kLoadIC_Miss);
CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index()); CHECK_EQ(iterator.GetRegisterOperand(1).index(), reg_0.index());
CHECK_EQ(iterator.GetRegisterCountOperand(2), 1); CHECK_EQ(iterator.GetRegisterCountOperand(2), 1);
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kCallRuntime, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger); CHECK_EQ(iterator.current_bytecode(), Bytecode::kDebugger);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK(!iterator.done()); CHECK(!iterator.done());
offset += Bytecodes::Size(Bytecode::kDebugger, OperandScale::kSingle);
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaGlobal); CHECK_EQ(iterator.current_bytecode(), Bytecode::kLdaGlobal);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple);
CHECK_EQ(iterator.current_bytecode_size(), 10); CHECK_EQ(iterator.current_bytecode_size(), 10);
CHECK_EQ(iterator.GetIndexOperand(1), 0x10000000); CHECK_EQ(iterator.GetIndexOperand(1), 0x10000000);
offset += Bytecodes::Size(Bytecode::kLdaGlobal, OperandScale::kQuadruple) +
kPrefixByteSize;
iterator.Advance(); iterator.Advance();
CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn); CHECK_EQ(iterator.current_bytecode(), Bytecode::kReturn);
CHECK_EQ(iterator.current_offset(), offset);
CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle); CHECK_EQ(iterator.current_operand_scale(), OperandScale::kSingle);
CHECK(!iterator.done()); CHECK(!iterator.done());
iterator.Advance(); iterator.Advance();
......
...@@ -39,7 +39,6 @@ TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) { ...@@ -39,7 +39,6 @@ TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) {
} }
} }
TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx8Reservations) { TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx8Reservations) {
for (size_t reserved = 1; reserved < k8BitCapacity; reserved *= 3) { for (size_t reserved = 1; reserved < k8BitCapacity; reserved *= 3) {
ConstantArrayBuilder builder(isolate(), zone()); ConstantArrayBuilder builder(isolate(), zone());
...@@ -201,7 +200,6 @@ TEST_F(ConstantArrayBuilderTest, GapFilledWhenLowReservationCommitted) { ...@@ -201,7 +200,6 @@ TEST_F(ConstantArrayBuilderTest, GapFilledWhenLowReservationCommitted) {
} }
} }
TEST_F(ConstantArrayBuilderTest, GapNotFilledWhenLowReservationDiscarded) { TEST_F(ConstantArrayBuilderTest, GapNotFilledWhenLowReservationDiscarded) {
ConstantArrayBuilder builder(isolate(), zone()); ConstantArrayBuilder builder(isolate(), zone());
for (size_t i = 0; i < k8BitCapacity; i++) { for (size_t i = 0; i < k8BitCapacity; i++) {
...@@ -228,6 +226,63 @@ TEST_F(ConstantArrayBuilderTest, GapNotFilledWhenLowReservationDiscarded) { ...@@ -228,6 +226,63 @@ TEST_F(ConstantArrayBuilderTest, GapNotFilledWhenLowReservationDiscarded) {
} }
} }
TEST_F(ConstantArrayBuilderTest, HolesWithUnusedReservations) {
static int kNumberOfHoles = 128;
ConstantArrayBuilder builder(isolate(), zone());
for (int i = 0; i < kNumberOfHoles; ++i) {
CHECK_EQ(builder.CreateReservedEntry(), OperandSize::kByte);
}
for (int i = 0; i < 128; ++i) {
CHECK_EQ(builder.Insert(isolate()->factory()->NewNumber(i)), i);
}
CHECK_EQ(builder.Insert(isolate()->factory()->NewNumber(256)), 256);
Handle<FixedArray> constant_array = builder.ToFixedArray();
CHECK_EQ(constant_array->length(), 257);
for (int i = 128; i < 256; i++) {
CHECK(constant_array->get(i)->SameValue(
*isolate()->factory()->the_hole_value()));
}
CHECK(!constant_array->get(127)->SameValue(
*isolate()->factory()->the_hole_value()));
CHECK(!constant_array->get(256)->SameValue(
*isolate()->factory()->the_hole_value()));
}
TEST_F(ConstantArrayBuilderTest, ReservationsAtAllScales) {
ConstantArrayBuilder builder(isolate(), zone());
for (int i = 0; i < 256; i++) {
CHECK_EQ(builder.CreateReservedEntry(), OperandSize::kByte);
}
for (int i = 256; i < 65536; ++i) {
CHECK_EQ(builder.CreateReservedEntry(), OperandSize::kShort);
}
for (int i = 65536; i < 131072; ++i) {
CHECK_EQ(builder.CreateReservedEntry(), OperandSize::kQuad);
}
CHECK_EQ(builder.CommitReservedEntry(OperandSize::kByte,
isolate()->factory()->NewNumber(1)),
0);
CHECK_EQ(builder.CommitReservedEntry(OperandSize::kShort,
isolate()->factory()->NewNumber(2)),
256);
CHECK_EQ(builder.CommitReservedEntry(OperandSize::kQuad,
isolate()->factory()->NewNumber(3)),
65536);
Handle<FixedArray> constant_array = builder.ToFixedArray();
CHECK_EQ(constant_array->length(), 65537);
int count = 1;
for (int i = 0; i < constant_array->length(); ++i) {
Handle<Object> expected;
if (i == 0 || i == 256 || i == 65536) {
expected = isolate()->factory()->NewNumber(count++);
} else {
expected = isolate()->factory()->the_hole_value();
}
CHECK(constant_array->get(i)->SameValue(*expected));
}
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment