Line data Source code
1 : // Copyright 2015 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 <vector>
6 :
7 : #include "src/v8.h"
8 :
9 : #include "src/interpreter/bytecode-register.h"
10 : #include "src/interpreter/bytecodes.h"
11 : #include "test/unittests/test-utils.h"
12 :
13 : namespace v8 {
14 : namespace internal {
15 : namespace interpreter {
16 :
17 15443 : TEST(OperandConversion, Registers) {
18 : int register_count = 128;
19 : int step = register_count / 7;
20 : for (int i = 0; i < register_count; i += step) {
21 : if (i <= kMaxInt8) {
22 : uint32_t operand0 = Register(i).ToOperand();
23 : Register reg0 = Register::FromOperand(operand0);
24 : CHECK_EQ(i, reg0.index());
25 : }
26 :
27 : uint32_t operand1 = Register(i).ToOperand();
28 : Register reg1 = Register::FromOperand(operand1);
29 : CHECK_EQ(i, reg1.index());
30 :
31 : uint32_t operand2 = Register(i).ToOperand();
32 : Register reg2 = Register::FromOperand(operand2);
33 : CHECK_EQ(i, reg2.index());
34 : }
35 1 : }
36 :
37 15443 : TEST(OperandConversion, Parameters) {
38 1 : int parameter_counts[] = {7, 13, 99};
39 :
40 : size_t count = sizeof(parameter_counts) / sizeof(parameter_counts[0]);
41 7 : for (size_t p = 0; p < count; p++) {
42 3 : int parameter_count = parameter_counts[p];
43 241 : for (int i = 0; i < parameter_count; i++) {
44 119 : Register r = Register::FromParameterIndex(i, parameter_count);
45 : uint32_t operand_value = r.ToOperand();
46 119 : Register s = Register::FromOperand(operand_value);
47 119 : CHECK_EQ(i, s.ToParameterIndex(parameter_count));
48 : }
49 : }
50 1 : }
51 :
52 15443 : TEST(OperandConversion, RegistersParametersNoOverlap) {
53 : int register_count = 128;
54 : int parameter_count = 100;
55 1 : int32_t register_space_size = base::bits::RoundUpToPowerOfTwo32(
56 : static_cast<uint32_t>(register_count + parameter_count));
57 : uint32_t range = static_cast<uint32_t>(register_space_size);
58 1 : std::vector<uint8_t> operand_count(range);
59 :
60 257 : for (int i = 0; i < register_count; i += 1) {
61 : Register r = Register(i);
62 : int32_t operand = r.ToOperand();
63 128 : uint8_t index = static_cast<uint8_t>(operand);
64 128 : CHECK_LT(index, operand_count.size());
65 128 : operand_count[index] += 1;
66 256 : CHECK_EQ(operand_count[index], 1);
67 : }
68 :
69 201 : for (int i = 0; i < parameter_count; i += 1) {
70 100 : Register r = Register::FromParameterIndex(i, parameter_count);
71 : uint32_t operand = r.ToOperand();
72 100 : uint8_t index = static_cast<uint8_t>(operand);
73 100 : CHECK_LT(index, operand_count.size());
74 100 : operand_count[index] += 1;
75 200 : CHECK_EQ(operand_count[index], 1);
76 : }
77 1 : }
78 :
79 15443 : TEST(OperandScaling, ScalableAndNonScalable) {
80 : const OperandScale kOperandScales[] = {
81 : #define VALUE(Name, _) OperandScale::k##Name,
82 : OPERAND_SCALE_LIST(VALUE)
83 : #undef VALUE
84 1 : };
85 :
86 7 : for (OperandScale operand_scale : kOperandScales) {
87 3 : int scale = static_cast<int>(operand_scale);
88 6 : CHECK_EQ(Bytecodes::Size(Bytecode::kCallRuntime, operand_scale),
89 : 1 + 2 + 2 * scale);
90 6 : CHECK_EQ(Bytecodes::Size(Bytecode::kCreateObjectLiteral, operand_scale),
91 : 1 + 2 * scale + 1);
92 6 : CHECK_EQ(Bytecodes::Size(Bytecode::kTestIn, operand_scale), 1 + 2 * scale);
93 : }
94 1 : }
95 :
96 15443 : TEST(Bytecodes, RegisterOperands) {
97 1 : CHECK(Bytecodes::IsRegisterOperandType(OperandType::kReg));
98 1 : CHECK(Bytecodes::IsRegisterOperandType(OperandType::kRegPair));
99 1 : CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::kReg));
100 1 : CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::kRegPair));
101 1 : CHECK(Bytecodes::IsRegisterInputOperandType(OperandType::kRegList));
102 1 : CHECK(!Bytecodes::IsRegisterOutputOperandType(OperandType::kReg));
103 1 : CHECK(!Bytecodes::IsRegisterInputOperandType(OperandType::kRegOut));
104 1 : CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::kRegOut));
105 1 : CHECK(Bytecodes::IsRegisterOutputOperandType(OperandType::kRegOutPair));
106 1 : }
107 :
108 15443 : TEST(Bytecodes, DebugBreakExistForEachBytecode) {
109 : static const OperandScale kOperandScale = OperandScale::kSingle;
110 : #define CHECK_DEBUG_BREAK_SIZE(Name, ...) \
111 : if (!Bytecodes::IsDebugBreak(Bytecode::k##Name) && \
112 : !Bytecodes::IsPrefixScalingBytecode(Bytecode::k##Name)) { \
113 : Bytecode debug_bytecode = Bytecodes::GetDebugBreak(Bytecode::k##Name); \
114 : CHECK_EQ(Bytecodes::Size(Bytecode::k##Name, kOperandScale), \
115 : Bytecodes::Size(debug_bytecode, kOperandScale)); \
116 : }
117 170 : BYTECODE_LIST(CHECK_DEBUG_BREAK_SIZE)
118 : #undef CHECK_DEBUG_BREAK_SIZE
119 1 : }
120 :
121 15443 : TEST(Bytecodes, DebugBreakForPrefixBytecodes) {
122 1 : CHECK_EQ(Bytecode::kDebugBreakWide,
123 : Bytecodes::GetDebugBreak(Bytecode::kWide));
124 1 : CHECK_EQ(Bytecode::kDebugBreakExtraWide,
125 : Bytecodes::GetDebugBreak(Bytecode::kExtraWide));
126 1 : }
127 :
128 15443 : TEST(Bytecodes, PrefixMappings) {
129 1 : Bytecode prefixes[] = {Bytecode::kWide, Bytecode::kExtraWide};
130 9 : TRACED_FOREACH(Bytecode, prefix, prefixes) {
131 4 : CHECK_EQ(prefix, Bytecodes::OperandScaleToPrefixBytecode(
132 : Bytecodes::PrefixBytecodeToOperandScale(prefix)));
133 : }
134 1 : }
135 :
136 15443 : TEST(Bytecodes, ScaleForSignedOperand) {
137 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(0), OperandScale::kSingle);
138 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMaxInt8), OperandScale::kSingle);
139 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMinInt8), OperandScale::kSingle);
140 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMaxInt8 + 1),
141 : OperandScale::kDouble);
142 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMinInt8 - 1),
143 : OperandScale::kDouble);
144 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMaxInt16), OperandScale::kDouble);
145 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMinInt16), OperandScale::kDouble);
146 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMaxInt16 + 1),
147 : OperandScale::kQuadruple);
148 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMinInt16 - 1),
149 : OperandScale::kQuadruple);
150 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMaxInt), OperandScale::kQuadruple);
151 : CHECK_EQ(Bytecodes::ScaleForSignedOperand(kMinInt), OperandScale::kQuadruple);
152 1 : }
153 :
154 15443 : TEST(Bytecodes, ScaleForUnsignedOperands) {
155 : // int overloads
156 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(0), OperandScale::kSingle);
157 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(kMaxUInt8),
158 : OperandScale::kSingle);
159 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(kMaxUInt8 + 1),
160 : OperandScale::kDouble);
161 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(kMaxUInt16),
162 : OperandScale::kDouble);
163 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(kMaxUInt16 + 1),
164 : OperandScale::kQuadruple);
165 : // size_t overloads
166 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(0)),
167 : OperandScale::kSingle);
168 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(kMaxUInt8)),
169 : OperandScale::kSingle);
170 : CHECK(Bytecodes::ScaleForUnsignedOperand(
171 : static_cast<size_t>(kMaxUInt8 + 1)) == OperandScale::kDouble);
172 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(kMaxUInt16)),
173 : OperandScale::kDouble);
174 : CHECK(Bytecodes::ScaleForUnsignedOperand(
175 : static_cast<size_t>(kMaxUInt16 + 1)) == OperandScale::kQuadruple);
176 : CHECK_EQ(Bytecodes::ScaleForUnsignedOperand(static_cast<size_t>(kMaxUInt32)),
177 : OperandScale::kQuadruple);
178 1 : }
179 :
180 15443 : TEST(Bytecodes, SizesForUnsignedOperands) {
181 : // int overloads
182 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(0), OperandSize::kByte);
183 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(kMaxUInt8), OperandSize::kByte);
184 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(kMaxUInt8 + 1),
185 : OperandSize::kShort);
186 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(kMaxUInt16), OperandSize::kShort);
187 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(kMaxUInt16 + 1),
188 : OperandSize::kQuad);
189 : // size_t overloads
190 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(0)),
191 : OperandSize::kByte);
192 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt8)),
193 : OperandSize::kByte);
194 : CHECK_EQ(
195 : Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt8 + 1)),
196 : OperandSize::kShort);
197 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt16)),
198 : OperandSize::kShort);
199 : CHECK(Bytecodes::SizeForUnsignedOperand(
200 : static_cast<size_t>(kMaxUInt16 + 1)) == OperandSize::kQuad);
201 : CHECK_EQ(Bytecodes::SizeForUnsignedOperand(static_cast<size_t>(kMaxUInt32)),
202 : OperandSize::kQuad);
203 1 : }
204 :
205 : // Helper macros to generate a check for if a bytecode is in a macro list of
206 : // bytecodes. We can use these to exhaustively test a check over all bytecodes,
207 : // both those that should pass and those that should fail the check.
208 : #define OR_IS_BYTECODE(Name, ...) || bytecode == Bytecode::k##Name
209 : #define IN_BYTECODE_LIST(BYTECODE, LIST) \
210 : ([](Bytecode bytecode) { return false LIST(OR_IS_BYTECODE); }(BYTECODE))
211 :
212 15443 : TEST(Bytecodes, IsJump) {
213 : #define TEST_BYTECODE(Name, ...) \
214 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_BYTECODE_LIST)) { \
215 : EXPECT_TRUE(Bytecodes::IsJump(Bytecode::k##Name)); \
216 : } else { \
217 : EXPECT_FALSE(Bytecodes::IsJump(Bytecode::k##Name)); \
218 : }
219 :
220 : BYTECODE_LIST(TEST_BYTECODE)
221 : #undef TEST_BYTECODE
222 1 : }
223 :
224 15443 : TEST(Bytecodes, IsForwardJump) {
225 : #define TEST_BYTECODE(Name, ...) \
226 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_FORWARD_BYTECODE_LIST)) { \
227 : EXPECT_TRUE(Bytecodes::IsForwardJump(Bytecode::k##Name)); \
228 : } else { \
229 : EXPECT_FALSE(Bytecodes::IsForwardJump(Bytecode::k##Name)); \
230 : }
231 :
232 : BYTECODE_LIST(TEST_BYTECODE)
233 : #undef TEST_BYTECODE
234 1 : }
235 :
236 15443 : TEST(Bytecodes, IsConditionalJump) {
237 : #define TEST_BYTECODE(Name, ...) \
238 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_CONDITIONAL_BYTECODE_LIST)) { \
239 : EXPECT_TRUE(Bytecodes::IsConditionalJump(Bytecode::k##Name)); \
240 : } else { \
241 : EXPECT_FALSE(Bytecodes::IsConditionalJump(Bytecode::k##Name)); \
242 : }
243 :
244 : BYTECODE_LIST(TEST_BYTECODE)
245 : #undef TEST_BYTECODE
246 1 : }
247 :
248 15443 : TEST(Bytecodes, IsUnconditionalJump) {
249 : #define TEST_BYTECODE(Name, ...) \
250 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_UNCONDITIONAL_BYTECODE_LIST)) { \
251 : EXPECT_TRUE(Bytecodes::IsUnconditionalJump(Bytecode::k##Name)); \
252 : } else { \
253 : EXPECT_FALSE(Bytecodes::IsUnconditionalJump(Bytecode::k##Name)); \
254 : }
255 :
256 : BYTECODE_LIST(TEST_BYTECODE)
257 : #undef TEST_BYTECODE
258 1 : }
259 :
260 15443 : TEST(Bytecodes, IsJumpImmediate) {
261 : #define TEST_BYTECODE(Name, ...) \
262 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_IMMEDIATE_BYTECODE_LIST)) { \
263 : EXPECT_TRUE(Bytecodes::IsJumpImmediate(Bytecode::k##Name)); \
264 : } else { \
265 : EXPECT_FALSE(Bytecodes::IsJumpImmediate(Bytecode::k##Name)); \
266 : }
267 :
268 : BYTECODE_LIST(TEST_BYTECODE)
269 : #undef TEST_BYTECODE
270 1 : }
271 :
272 15443 : TEST(Bytecodes, IsJumpConstant) {
273 : #define TEST_BYTECODE(Name, ...) \
274 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_CONSTANT_BYTECODE_LIST)) { \
275 : EXPECT_TRUE(Bytecodes::IsJumpConstant(Bytecode::k##Name)); \
276 : } else { \
277 : EXPECT_FALSE(Bytecodes::IsJumpConstant(Bytecode::k##Name)); \
278 : }
279 :
280 : BYTECODE_LIST(TEST_BYTECODE)
281 : #undef TEST_BYTECODE
282 1 : }
283 :
284 15443 : TEST(Bytecodes, IsConditionalJumpImmediate) {
285 : #define TEST_BYTECODE(Name, ...) \
286 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_CONDITIONAL_BYTECODE_LIST) && \
287 : IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_IMMEDIATE_BYTECODE_LIST)) { \
288 : EXPECT_TRUE(Bytecodes::IsConditionalJumpImmediate(Bytecode::k##Name)); \
289 : } else { \
290 : EXPECT_FALSE(Bytecodes::IsConditionalJumpImmediate(Bytecode::k##Name)); \
291 : }
292 :
293 : BYTECODE_LIST(TEST_BYTECODE)
294 : #undef TEST_BYTECODE
295 1 : }
296 :
297 15443 : TEST(Bytecodes, IsConditionalJumpConstant) {
298 : #define TEST_BYTECODE(Name, ...) \
299 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_CONDITIONAL_BYTECODE_LIST) && \
300 : IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_CONSTANT_BYTECODE_LIST)) { \
301 : EXPECT_TRUE(Bytecodes::IsConditionalJumpConstant(Bytecode::k##Name)); \
302 : } else { \
303 : EXPECT_FALSE(Bytecodes::IsConditionalJumpConstant(Bytecode::k##Name)); \
304 : }
305 :
306 : BYTECODE_LIST(TEST_BYTECODE)
307 : #undef TEST_BYTECODE
308 1 : }
309 :
310 15443 : TEST(Bytecodes, IsJumpIfToBoolean) {
311 : #define TEST_BYTECODE(Name, ...) \
312 : if (IN_BYTECODE_LIST(Bytecode::k##Name, JUMP_TO_BOOLEAN_BYTECODE_LIST)) { \
313 : EXPECT_TRUE(Bytecodes::IsJumpIfToBoolean(Bytecode::k##Name)); \
314 : } else { \
315 : EXPECT_FALSE(Bytecodes::IsJumpIfToBoolean(Bytecode::k##Name)); \
316 : }
317 :
318 : BYTECODE_LIST(TEST_BYTECODE)
319 : #undef TEST_BYTECODE
320 1 : }
321 :
322 : #undef OR_IS_BYTECODE
323 : #undef IN_BYTECODE_LIST
324 :
325 15443 : TEST(OperandScale, PrefixesRequired) {
326 : CHECK(!Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale::kSingle));
327 : CHECK(Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale::kDouble));
328 : CHECK(
329 : Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale::kQuadruple));
330 : CHECK_EQ(Bytecodes::OperandScaleToPrefixBytecode(OperandScale::kDouble),
331 : Bytecode::kWide);
332 : CHECK_EQ(Bytecodes::OperandScaleToPrefixBytecode(OperandScale::kQuadruple),
333 : Bytecode::kExtraWide);
334 1 : }
335 :
336 15443 : TEST(AccumulatorUse, LogicalOperators) {
337 : CHECK_EQ(AccumulatorUse::kNone | AccumulatorUse::kRead,
338 : AccumulatorUse::kRead);
339 : CHECK_EQ(AccumulatorUse::kRead | AccumulatorUse::kWrite,
340 : AccumulatorUse::kReadWrite);
341 : CHECK_EQ(AccumulatorUse::kRead & AccumulatorUse::kReadWrite,
342 : AccumulatorUse::kRead);
343 : CHECK_EQ(AccumulatorUse::kRead & AccumulatorUse::kWrite,
344 : AccumulatorUse::kNone);
345 1 : }
346 :
347 15443 : TEST(AccumulatorUse, SampleBytecodes) {
348 1 : CHECK(Bytecodes::ReadsAccumulator(Bytecode::kStar));
349 1 : CHECK(!Bytecodes::WritesAccumulator(Bytecode::kStar));
350 1 : CHECK_EQ(Bytecodes::GetAccumulatorUse(Bytecode::kStar),
351 : AccumulatorUse::kRead);
352 1 : CHECK(!Bytecodes::ReadsAccumulator(Bytecode::kLdar));
353 1 : CHECK(Bytecodes::WritesAccumulator(Bytecode::kLdar));
354 1 : CHECK_EQ(Bytecodes::GetAccumulatorUse(Bytecode::kLdar),
355 : AccumulatorUse::kWrite);
356 1 : CHECK(Bytecodes::ReadsAccumulator(Bytecode::kAdd));
357 1 : CHECK(Bytecodes::WritesAccumulator(Bytecode::kAdd));
358 1 : CHECK_EQ(Bytecodes::GetAccumulatorUse(Bytecode::kAdd),
359 : AccumulatorUse::kReadWrite);
360 1 : }
361 :
362 : } // namespace interpreter
363 : } // namespace internal
364 9264 : } // namespace v8
|