blob: b3ec5ff6680113e19e076493145daabdf1af3066 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
3// found in the LICENSE file.
4
5#include "src/v8.h"
6
7#include "src/factory.h"
8#include "src/handles-inl.h"
9#include "src/interpreter/constant-array-builder.h"
10#include "src/isolate.h"
11#include "test/unittests/test-utils.h"
12
13namespace v8 {
14namespace internal {
15namespace interpreter {
16
17class ConstantArrayBuilderTest : public TestWithIsolateAndZone {
18 public:
19 ConstantArrayBuilderTest() {}
20 ~ConstantArrayBuilderTest() override {}
21
22 static const size_t kLowCapacity = ConstantArrayBuilder::kLowCapacity;
23 static const size_t kMaxCapacity = ConstantArrayBuilder::kMaxCapacity;
24};
25
26
27STATIC_CONST_MEMBER_DEFINITION const size_t
28 ConstantArrayBuilderTest::kMaxCapacity;
29STATIC_CONST_MEMBER_DEFINITION const size_t
30 ConstantArrayBuilderTest::kLowCapacity;
31
32
33TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) {
34 ConstantArrayBuilder builder(isolate(), zone());
35 for (size_t i = 0; i < kMaxCapacity; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010036 builder.Insert(handle(Smi::FromInt(static_cast<int>(i)), isolate()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 }
Ben Murdoch097c5b22016-05-18 11:27:45 +010038 CHECK_EQ(builder.size(), kMaxCapacity);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 for (size_t i = 0; i < kMaxCapacity; i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010040 CHECK_EQ(Handle<Smi>::cast(builder.At(i))->value(), i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041 }
42}
43
44
45TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx8Reservations) {
46 for (size_t reserved = 1; reserved < kLowCapacity; reserved *= 3) {
47 ConstantArrayBuilder builder(isolate(), zone());
48 for (size_t i = 0; i < reserved; i++) {
49 OperandSize operand_size = builder.CreateReservedEntry();
50 CHECK(operand_size == OperandSize::kByte);
51 }
52 for (size_t i = 0; i < 2 * kLowCapacity; i++) {
53 Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
54 builder.Insert(object);
55 if (i + reserved < kLowCapacity) {
56 CHECK_LE(builder.size(), kLowCapacity);
57 CHECK_EQ(builder.size(), i + 1);
58 CHECK(builder.At(i)->SameValue(*object));
59 } else {
60 CHECK_GE(builder.size(), kLowCapacity);
61 CHECK_EQ(builder.size(), i + reserved + 1);
62 CHECK(builder.At(i + reserved)->SameValue(*object));
63 }
64 }
65 CHECK_EQ(builder.size(), 2 * kLowCapacity + reserved);
66
67 // Check reserved values represented by the hole.
68 for (size_t i = 0; i < reserved; i++) {
69 Handle<Object> empty = builder.At(kLowCapacity - reserved + i);
70 CHECK(empty->SameValue(isolate()->heap()->the_hole_value()));
71 }
72
73 // Commmit reserved entries with duplicates and check size does not change.
74 DCHECK_EQ(reserved + 2 * kLowCapacity, builder.size());
75 size_t duplicates_in_idx8_space =
76 std::min(reserved, kLowCapacity - reserved);
77 for (size_t i = 0; i < duplicates_in_idx8_space; i++) {
78 builder.CommitReservedEntry(OperandSize::kByte,
79 isolate()->factory()->NewNumberFromSize(i));
80 DCHECK_EQ(reserved + 2 * kLowCapacity, builder.size());
81 }
82
83 // Check all committed values match expected (holes where
84 // duplicates_in_idx8_space allocated).
85 for (size_t i = 0; i < kLowCapacity - reserved; i++) {
86 Smi* smi = Smi::FromInt(static_cast<int>(i));
87 CHECK(Handle<Smi>::cast(builder.At(i))->SameValue(smi));
88 }
89 for (size_t i = kLowCapacity; i < 2 * kLowCapacity + reserved; i++) {
90 Smi* smi = Smi::FromInt(static_cast<int>(i - reserved));
91 CHECK(Handle<Smi>::cast(builder.At(i))->SameValue(smi));
92 }
93 for (size_t i = 0; i < reserved; i++) {
94 size_t index = kLowCapacity - reserved + i;
95 CHECK(builder.At(index)->IsTheHole());
96 }
97
98 // Now make reservations, and commit them with unique entries.
99 for (size_t i = 0; i < duplicates_in_idx8_space; i++) {
100 OperandSize operand_size = builder.CreateReservedEntry();
101 CHECK(operand_size == OperandSize::kByte);
102 }
103 for (size_t i = 0; i < duplicates_in_idx8_space; i++) {
104 Handle<Object> object =
105 isolate()->factory()->NewNumberFromSize(2 * kLowCapacity + i);
106 size_t index = builder.CommitReservedEntry(OperandSize::kByte, object);
107 CHECK_EQ(static_cast<int>(index), kLowCapacity - reserved + i);
108 CHECK(builder.At(static_cast<int>(index))->SameValue(*object));
109 }
110 CHECK_EQ(builder.size(), 2 * kLowCapacity + reserved);
111 }
112}
113
114
115TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx16Reservations) {
116 for (size_t reserved = 1; reserved < kLowCapacity; reserved *= 3) {
117 ConstantArrayBuilder builder(isolate(), zone());
118 for (size_t i = 0; i < kLowCapacity; i++) {
119 Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
120 builder.Insert(object);
121 CHECK(builder.At(i)->SameValue(*object));
122 CHECK_EQ(builder.size(), i + 1);
123 }
124 for (size_t i = 0; i < reserved; i++) {
125 OperandSize operand_size = builder.CreateReservedEntry();
126 CHECK(operand_size == OperandSize::kShort);
127 CHECK_EQ(builder.size(), kLowCapacity);
128 }
129 for (size_t i = 0; i < reserved; i++) {
130 builder.DiscardReservedEntry(OperandSize::kShort);
131 CHECK_EQ(builder.size(), kLowCapacity);
132 }
133 for (size_t i = 0; i < reserved; i++) {
134 OperandSize operand_size = builder.CreateReservedEntry();
135 CHECK(operand_size == OperandSize::kShort);
136 Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
137 builder.CommitReservedEntry(operand_size, object);
138 CHECK_EQ(builder.size(), kLowCapacity);
139 }
140 for (size_t i = kLowCapacity; i < kLowCapacity + reserved; i++) {
141 OperandSize operand_size = builder.CreateReservedEntry();
142 CHECK(operand_size == OperandSize::kShort);
143 Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
144 builder.CommitReservedEntry(operand_size, object);
145 CHECK_EQ(builder.size(), i + 1);
146 }
147 }
148}
149
150
151TEST_F(ConstantArrayBuilderTest, ToFixedArray) {
152 ConstantArrayBuilder builder(isolate(), zone());
153 static const size_t kNumberOfElements = 37;
154 for (size_t i = 0; i < kNumberOfElements; i++) {
155 Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
156 builder.Insert(object);
157 CHECK(builder.At(i)->SameValue(*object));
158 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100159 Handle<FixedArray> constant_array = builder.ToFixedArray();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000160 CHECK_EQ(constant_array->length(), kNumberOfElements);
161 for (size_t i = 0; i < kNumberOfElements; i++) {
162 CHECK(constant_array->get(static_cast<int>(i))->SameValue(*builder.At(i)));
163 }
164}
165
166
167TEST_F(ConstantArrayBuilderTest, GapFilledWhenLowReservationCommitted) {
168 ConstantArrayBuilder builder(isolate(), zone());
169 for (size_t i = 0; i < kLowCapacity; i++) {
170 OperandSize operand_size = builder.CreateReservedEntry();
171 CHECK(OperandSize::kByte == operand_size);
172 CHECK_EQ(builder.size(), 0);
173 }
174 for (size_t i = 0; i < kLowCapacity; i++) {
175 Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
176 builder.Insert(object);
177 CHECK_EQ(builder.size(), i + kLowCapacity + 1);
178 }
179 for (size_t i = 0; i < kLowCapacity; i++) {
180 builder.CommitReservedEntry(OperandSize::kByte,
181 builder.At(i + kLowCapacity));
182 CHECK_EQ(builder.size(), 2 * kLowCapacity);
183 }
184 for (size_t i = 0; i < kLowCapacity; i++) {
185 Handle<Object> original = builder.At(kLowCapacity + i);
186 Handle<Object> duplicate = builder.At(i);
187 CHECK(original->SameValue(*duplicate));
188 Handle<Object> reference = isolate()->factory()->NewNumberFromSize(i);
189 CHECK(original->SameValue(*reference));
190 }
191}
192
193
194TEST_F(ConstantArrayBuilderTest, GapNotFilledWhenLowReservationDiscarded) {
195 ConstantArrayBuilder builder(isolate(), zone());
196 for (size_t i = 0; i < kLowCapacity; i++) {
197 OperandSize operand_size = builder.CreateReservedEntry();
198 CHECK(OperandSize::kByte == operand_size);
199 CHECK_EQ(builder.size(), 0);
200 }
201 for (size_t i = 0; i < kLowCapacity; i++) {
202 Handle<Object> object = isolate()->factory()->NewNumberFromSize(i);
203 builder.Insert(object);
204 CHECK_EQ(builder.size(), i + kLowCapacity + 1);
205 }
206 for (size_t i = 0; i < kLowCapacity; i++) {
207 builder.DiscardReservedEntry(OperandSize::kByte);
208 builder.Insert(builder.At(i + kLowCapacity));
209 CHECK_EQ(builder.size(), 2 * kLowCapacity);
210 }
211 for (size_t i = 0; i < kLowCapacity; i++) {
212 Handle<Object> reference = isolate()->factory()->NewNumberFromSize(i);
213 Handle<Object> original = builder.At(kLowCapacity + i);
214 CHECK(original->SameValue(*reference));
215 Handle<Object> duplicate = builder.At(i);
216 CHECK(duplicate->SameValue(*isolate()->factory()->the_hole_value()));
217 }
218}
219
220} // namespace interpreter
221} // namespace internal
222} // namespace v8