blob: cd21f095081c97bfc5e0bf97bfdc64016d43358a [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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
Ben Murdoch097c5b22016-05-18 11:27:45 +01005#include "test/unittests/interpreter/interpreter-assembler-unittest.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00006
7#include "src/code-factory.h"
8#include "src/compiler/graph.h"
9#include "src/compiler/node.h"
10#include "src/interface-descriptors.h"
11#include "src/isolate.h"
12#include "test/unittests/compiler/compiler-test-utils.h"
13#include "test/unittests/compiler/node-test-utils.h"
14
15using ::testing::_;
16
17namespace v8 {
18namespace internal {
Ben Murdoch097c5b22016-05-18 11:27:45 +010019
20using namespace compiler;
21
22namespace interpreter {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000023
24const interpreter::Bytecode kBytecodes[] = {
25#define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
26 BYTECODE_LIST(DEFINE_BYTECODE)
27#undef DEFINE_BYTECODE
28};
29
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030Matcher<Node*> IsIntPtrConstant(const intptr_t value) {
31 return kPointerSize == 8 ? IsInt64Constant(static_cast<int64_t>(value))
32 : IsInt32Constant(static_cast<int32_t>(value));
33}
34
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
36 const Matcher<Node*>& rhs_matcher) {
37 return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
38 : IsInt32Add(lhs_matcher, rhs_matcher);
39}
40
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041Matcher<Node*> IsIntPtrSub(const Matcher<Node*>& lhs_matcher,
42 const Matcher<Node*>& rhs_matcher) {
43 return kPointerSize == 8 ? IsInt64Sub(lhs_matcher, rhs_matcher)
44 : IsInt32Sub(lhs_matcher, rhs_matcher);
45}
46
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
48 const Matcher<Node*>& rhs_matcher) {
49 return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
50 : IsWord32Shl(lhs_matcher, rhs_matcher);
51}
52
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000053Matcher<Node*> IsWordSar(const Matcher<Node*>& lhs_matcher,
54 const Matcher<Node*>& rhs_matcher) {
55 return kPointerSize == 8 ? IsWord64Sar(lhs_matcher, rhs_matcher)
56 : IsWord32Sar(lhs_matcher, rhs_matcher);
57}
58
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000059Matcher<Node*> IsWordOr(const Matcher<Node*>& lhs_matcher,
60 const Matcher<Node*>& rhs_matcher) {
61 return kPointerSize == 8 ? IsWord64Or(lhs_matcher, rhs_matcher)
62 : IsWord32Or(lhs_matcher, rhs_matcher);
63}
64
Ben Murdochda12d292016-06-02 14:46:10 +010065InterpreterAssemblerTest::InterpreterAssemblerForTest::
66 ~InterpreterAssemblerForTest() {
67 // Tests don't necessarily read and write accumulator but
68 // InterpreterAssembler checks accumulator uses.
69 if (Bytecodes::ReadsAccumulator(bytecode())) {
70 GetAccumulator();
71 }
72 if (Bytecodes::WritesAccumulator(bytecode())) {
73 SetAccumulator(nullptr);
74 }
75}
76
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
78 const Matcher<LoadRepresentation>& rep_matcher,
79 const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher) {
80 return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
81}
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
84 const Matcher<StoreRepresentation>& rep_matcher,
85 const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
86 const Matcher<Node*>& value_matcher) {
87 return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher,
88 value_matcher, _, _);
89}
90
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091Matcher<Node*>
Ben Murdochda12d292016-06-02 14:46:10 +010092InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedByteOperand(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000093 int offset) {
94 return IsLoad(
95 MachineType::Uint8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +010096 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
97 IsIntPtrAdd(
98 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
Ben Murdochda12d292016-06-02 14:46:10 +010099 IsIntPtrConstant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100}
101
Ben Murdochda12d292016-06-02 14:46:10 +0100102Matcher<Node*>
103InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedByteOperand(
104 int offset) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000105 Matcher<Node*> load_matcher = IsLoad(
106 MachineType::Int8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100107 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
108 IsIntPtrAdd(
109 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
Ben Murdochda12d292016-06-02 14:46:10 +0100110 IsIntPtrConstant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 if (kPointerSize == 8) {
112 load_matcher = IsChangeInt32ToInt64(load_matcher);
113 }
114 return load_matcher;
115}
116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117Matcher<Node*>
Ben Murdochda12d292016-06-02 14:46:10 +0100118InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedShortOperand(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000119 int offset) {
120 if (TargetSupportsUnalignedAccess()) {
121 return IsLoad(
122 MachineType::Uint16(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100123 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
124 IsIntPtrAdd(
125 IsParameter(
126 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
Ben Murdochda12d292016-06-02 14:46:10 +0100127 IsIntPtrConstant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000128 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129#if V8_TARGET_LITTLE_ENDIAN
Ben Murdochda12d292016-06-02 14:46:10 +0100130 const int kStep = -1;
131 const int kMsbOffset = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132#elif V8_TARGET_BIG_ENDIAN
Ben Murdochda12d292016-06-02 14:46:10 +0100133 const int kStep = 1;
134 const int kMsbOffset = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135#else
136#error "Unknown Architecture"
137#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100138 Matcher<Node*> bytes[2];
139 for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
140 bytes[i] = IsLoad(
141 MachineType::Uint8(),
142 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
143 IsIntPtrAdd(
144 IsParameter(
145 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
146 IsIntPtrConstant(offset + kMsbOffset + kStep * i)));
147 }
148 return IsWord32Or(IsWord32Shl(bytes[0], IsInt32Constant(kBitsPerByte)),
149 bytes[1]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 }
151}
152
Ben Murdochda12d292016-06-02 14:46:10 +0100153Matcher<Node*>
154InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedShortOperand(
155 int offset) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000156 Matcher<Node*> load_matcher;
157 if (TargetSupportsUnalignedAccess()) {
158 load_matcher = IsLoad(
159 MachineType::Int16(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100160 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
161 IsIntPtrAdd(
162 IsParameter(
163 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
Ben Murdochda12d292016-06-02 14:46:10 +0100164 IsIntPtrConstant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165 } else {
166#if V8_TARGET_LITTLE_ENDIAN
Ben Murdochda12d292016-06-02 14:46:10 +0100167 const int kStep = -1;
168 const int kMsbOffset = 1;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169#elif V8_TARGET_BIG_ENDIAN
Ben Murdochda12d292016-06-02 14:46:10 +0100170 const int kStep = 1;
171 const int kMsbOffset = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000172#else
173#error "Unknown Architecture"
174#endif
Ben Murdochda12d292016-06-02 14:46:10 +0100175 Matcher<Node*> bytes[2];
176 for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
177 bytes[i] = IsLoad(
178 (i == 0) ? MachineType::Int8() : MachineType::Uint8(),
179 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
180 IsIntPtrAdd(
181 IsParameter(
182 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
183 IsIntPtrConstant(offset + kMsbOffset + kStep * i)));
184 }
185 load_matcher = IsWord32Or(
186 IsWord32Shl(bytes[0], IsInt32Constant(kBitsPerByte)), bytes[1]);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 }
188
189 if (kPointerSize == 8) {
190 load_matcher = IsChangeInt32ToInt64(load_matcher);
191 }
192 return load_matcher;
193}
194
Ben Murdochda12d292016-06-02 14:46:10 +0100195Matcher<Node*>
196InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedQuadOperand(
197 int offset) {
198 if (TargetSupportsUnalignedAccess()) {
199 return IsLoad(
200 MachineType::Uint32(),
201 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
202 IsIntPtrAdd(
203 IsParameter(
204 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
205 IsIntPtrConstant(offset)));
206 } else {
207#if V8_TARGET_LITTLE_ENDIAN
208 const int kStep = -1;
209 const int kMsbOffset = 3;
210#elif V8_TARGET_BIG_ENDIAN
211 const int kStep = 1;
212 const int kMsbOffset = 0;
213#else
214#error "Unknown Architecture"
215#endif
216 Matcher<Node*> bytes[4];
217 for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
218 bytes[i] = IsLoad(
219 MachineType::Uint8(),
220 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
221 IsIntPtrAdd(
222 IsParameter(
223 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
224 IsIntPtrConstant(offset + kMsbOffset + kStep * i)));
225 }
226 return IsWord32Or(
227 IsWord32Shl(bytes[0], IsInt32Constant(3 * kBitsPerByte)),
228 IsWord32Or(
229 IsWord32Shl(bytes[1], IsInt32Constant(2 * kBitsPerByte)),
230 IsWord32Or(IsWord32Shl(bytes[2], IsInt32Constant(1 * kBitsPerByte)),
231 bytes[3])));
232 }
233}
234
235Matcher<Node*>
236InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedQuadOperand(
237 int offset) {
238 Matcher<Node*> load_matcher;
239 if (TargetSupportsUnalignedAccess()) {
240 load_matcher = IsLoad(
241 MachineType::Int32(),
242 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
243 IsIntPtrAdd(
244 IsParameter(
245 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
246 IsIntPtrConstant(offset)));
247 } else {
248#if V8_TARGET_LITTLE_ENDIAN
249 const int kStep = -1;
250 int kMsbOffset = 3;
251#elif V8_TARGET_BIG_ENDIAN
252 const int kStep = 1;
253 int kMsbOffset = 0;
254#else
255#error "Unknown Architecture"
256#endif
257 Matcher<Node*> bytes[4];
258 for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
259 bytes[i] = IsLoad(
260 (i == 0) ? MachineType::Int8() : MachineType::Uint8(),
261 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
262 IsIntPtrAdd(
263 IsParameter(
264 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
265 IsIntPtrConstant(offset + kMsbOffset + kStep * i)));
266 }
267 load_matcher = IsWord32Or(
268 IsWord32Shl(bytes[0], IsInt32Constant(3 * kBitsPerByte)),
269 IsWord32Or(
270 IsWord32Shl(bytes[1], IsInt32Constant(2 * kBitsPerByte)),
271 IsWord32Or(IsWord32Shl(bytes[2], IsInt32Constant(1 * kBitsPerByte)),
272 bytes[3])));
273 }
274
275 if (kPointerSize == 8) {
276 load_matcher = IsChangeInt32ToInt64(load_matcher);
277 }
278 return load_matcher;
279}
280
281Matcher<Node*>
282InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedOperand(
283 int offset, OperandSize operand_size) {
284 switch (operand_size) {
285 case OperandSize::kByte:
286 return IsSignedByteOperand(offset);
287 case OperandSize::kShort:
288 return IsSignedShortOperand(offset);
289 case OperandSize::kQuad:
290 return IsSignedQuadOperand(offset);
291 case OperandSize::kNone:
292 UNREACHABLE();
293 }
294 return nullptr;
295}
296
297Matcher<Node*>
298InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedOperand(
299 int offset, OperandSize operand_size) {
300 switch (operand_size) {
301 case OperandSize::kByte:
302 return IsUnsignedByteOperand(offset);
303 case OperandSize::kShort:
304 return IsUnsignedShortOperand(offset);
305 case OperandSize::kQuad:
306 return IsUnsignedQuadOperand(offset);
307 case OperandSize::kNone:
308 UNREACHABLE();
309 }
310 return nullptr;
311}
312
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
314 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
315 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochc5610432016-08-08 18:44:38 +0100316 Node* tail_call_node = m.Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317
Ben Murdochda12d292016-06-02 14:46:10 +0100318 OperandScale operand_scale = OperandScale::kSingle;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100319 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
320 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
Ben Murdochda12d292016-06-02 14:46:10 +0100321 IsIntPtrConstant(
322 interpreter::Bytecodes::Size(bytecode, operand_scale)));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100323 Matcher<Node*> target_bytecode_matcher = m.IsLoad(
324 MachineType::Uint8(),
325 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
326 next_bytecode_offset_matcher);
Ben Murdochda12d292016-06-02 14:46:10 +0100327 if (kPointerSize == 8) {
328 target_bytecode_matcher = IsChangeUint32ToUint64(target_bytecode_matcher);
329 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100330 Matcher<Node*> code_target_matcher = m.IsLoad(
331 MachineType::Pointer(),
332 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
Ben Murdochda12d292016-06-02 14:46:10 +0100333 IsWordShl(target_bytecode_matcher, IsIntPtrConstant(kPointerSizeLog2)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000335 EXPECT_THAT(
336 tail_call_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100337 IsTailCall(
338 _, code_target_matcher,
339 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100340 next_bytecode_offset_matcher,
341 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
342 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
Ben Murdochc5610432016-08-08 18:44:38 +0100343 _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344 }
345}
346
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000347TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100348 // If debug code is enabled we emit extra code in Jump.
349 if (FLAG_debug_code) return;
350
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000351 int jump_offsets[] = {-9710, -77, 0, +3, +97109};
352 TRACED_FOREACH(int, jump_offset, jump_offsets) {
353 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
354 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochc5610432016-08-08 18:44:38 +0100355 Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000356
Ben Murdoch097c5b22016-05-18 11:27:45 +0100357 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
358 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
Ben Murdochda12d292016-06-02 14:46:10 +0100359 IsIntPtrConstant(jump_offset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360 Matcher<Node*> target_bytecode_matcher =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100361 m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
Ben Murdochda12d292016-06-02 14:46:10 +0100362 if (kPointerSize == 8) {
363 target_bytecode_matcher =
364 IsChangeUint32ToUint64(target_bytecode_matcher);
365 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100366 Matcher<Node*> code_target_matcher = m.IsLoad(
367 MachineType::Pointer(),
368 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
Ben Murdochda12d292016-06-02 14:46:10 +0100369 IsWordShl(target_bytecode_matcher,
370 IsIntPtrConstant(kPointerSizeLog2)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372 EXPECT_THAT(
373 tail_call_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100374 IsTailCall(
375 _, code_target_matcher,
376 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100377 next_bytecode_offset_matcher, _,
378 IsParameter(
379 InterpreterDispatchDescriptor::kDispatchTableParameter),
Ben Murdochc5610432016-08-08 18:44:38 +0100380 _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 }
382 }
383}
384
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
Ben Murdochda12d292016-06-02 14:46:10 +0100386 static const OperandScale kOperandScales[] = {
387 OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
Ben Murdochda12d292016-06-02 14:46:10 +0100389 TRACED_FOREACH(interpreter::OperandScale, operand_scale, kOperandScales) {
390 InterpreterAssemblerForTest m(this, bytecode, operand_scale);
391 int number_of_operands =
392 interpreter::Bytecodes::NumberOfOperands(bytecode);
393 for (int i = 0; i < number_of_operands; i++) {
394 int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i,
395 operand_scale);
396 OperandType operand_type =
397 interpreter::Bytecodes::GetOperandType(bytecode, i);
398 OperandSize operand_size =
399 Bytecodes::SizeOfOperand(operand_type, operand_scale);
400 switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
401 case interpreter::OperandType::kRegCount:
402 EXPECT_THAT(m.BytecodeOperandCount(i),
403 m.IsUnsignedOperand(offset, operand_size));
404 break;
405 case interpreter::OperandType::kFlag8:
406 EXPECT_THAT(m.BytecodeOperandFlag(i),
407 m.IsUnsignedOperand(offset, operand_size));
408 break;
409 case interpreter::OperandType::kIdx:
410 EXPECT_THAT(m.BytecodeOperandIdx(i),
411 m.IsUnsignedOperand(offset, operand_size));
412 break;
413 case interpreter::OperandType::kImm: {
414 EXPECT_THAT(m.BytecodeOperandImm(i),
415 m.IsSignedOperand(offset, operand_size));
416 break;
417 }
418 case interpreter::OperandType::kMaybeReg:
419 case interpreter::OperandType::kReg:
420 case interpreter::OperandType::kRegOut:
421 case interpreter::OperandType::kRegOutPair:
422 case interpreter::OperandType::kRegOutTriple:
423 case interpreter::OperandType::kRegPair:
424 EXPECT_THAT(m.BytecodeOperandReg(i),
425 m.IsSignedOperand(offset, operand_size));
426 break;
427 case interpreter::OperandType::kRuntimeId:
428 EXPECT_THAT(m.BytecodeOperandRuntimeId(i),
429 m.IsUnsignedOperand(offset, operand_size));
430 break;
431 case interpreter::OperandType::kNone:
432 UNREACHABLE();
433 break;
434 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000435 }
436 }
437 }
438}
439
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
441 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
Ben Murdochda12d292016-06-02 14:46:10 +0100442 if (!interpreter::Bytecodes::ReadsAccumulator(bytecode) ||
443 !interpreter::Bytecodes::WritesAccumulator(bytecode)) {
444 continue;
445 }
446
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000447 InterpreterAssemblerForTest m(this, bytecode);
448 // Should be incoming accumulator if not set.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100449 EXPECT_THAT(
450 m.GetAccumulator(),
451 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100452 // Should be set by SetAccumulator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000453 Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
454 m.SetAccumulator(accumulator_value_1);
455 EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
456 Node* accumulator_value_2 = m.Int32Constant(42);
457 m.SetAccumulator(accumulator_value_2);
458 EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
459
460 // Should be passed to next bytecode handler on dispatch.
Ben Murdochc5610432016-08-08 18:44:38 +0100461 Node* tail_call_node = m.Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000462
463 EXPECT_THAT(tail_call_node,
Ben Murdochc5610432016-08-08 18:44:38 +0100464 IsTailCall(_, _, accumulator_value_2, _, _, _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 }
466}
467
Ben Murdochc5610432016-08-08 18:44:38 +0100468TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100469 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
470 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochc5610432016-08-08 18:44:38 +0100471 EXPECT_THAT(
472 m.GetContext(),
473 m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
474 IsIntPtrConstant(Register::current_context().ToOperand()
475 << kPointerSizeLog2)));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100476 }
477}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478
479TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
480 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
481 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100482 Node* reg_index_node = m.IntPtrConstant(44);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 Node* reg_location_node = m.RegisterLocation(reg_index_node);
Ben Murdochc5610432016-08-08 18:44:38 +0100484 EXPECT_THAT(reg_location_node,
485 IsIntPtrAdd(IsLoadParentFramePointer(),
486 IsWordShl(reg_index_node,
487 IsIntPtrConstant(kPointerSizeLog2))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 }
489}
490
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000491TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
492 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
493 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100494 Node* reg_index_node = m.IntPtrConstant(44);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495 Node* load_reg_node = m.LoadRegister(reg_index_node);
Ben Murdochc5610432016-08-08 18:44:38 +0100496 EXPECT_THAT(load_reg_node,
497 m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
498 IsWordShl(reg_index_node,
499 IsIntPtrConstant(kPointerSizeLog2))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000500 }
501}
502
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000503TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
504 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
505 InterpreterAssemblerForTest m(this, bytecode);
506 Node* store_value = m.Int32Constant(0xdeadbeef);
Ben Murdochda12d292016-06-02 14:46:10 +0100507 Node* reg_index_node = m.IntPtrConstant(44);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
509 EXPECT_THAT(
510 store_reg_node,
Ben Murdochc5610432016-08-08 18:44:38 +0100511 m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
512 kNoWriteBarrier),
513 IsLoadParentFramePointer(),
514 IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2)),
515 store_value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000516 }
517}
518
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
520 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
521 InterpreterAssemblerForTest m(this, bytecode);
522 Node* value = m.Int32Constant(44);
Ben Murdochc5610432016-08-08 18:44:38 +0100523 EXPECT_THAT(m.SmiTag(value),
524 IsIntPtrConstant(static_cast<intptr_t>(44)
525 << (kSmiShiftSize + kSmiTagSize)));
Ben Murdochda12d292016-06-02 14:46:10 +0100526 EXPECT_THAT(
527 m.SmiUntag(value),
528 IsWordSar(value, IsIntPtrConstant(kSmiShiftSize + kSmiTagSize)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 }
530}
531
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
533 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
534 InterpreterAssemblerForTest m(this, bytecode);
535 Node* a = m.Int32Constant(0);
536 Node* b = m.Int32Constant(1);
537 Node* add = m.IntPtrAdd(a, b);
538 EXPECT_THAT(add, IsIntPtrAdd(a, b));
539 }
540}
541
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000542TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
543 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
544 InterpreterAssemblerForTest m(this, bytecode);
545 Node* a = m.Int32Constant(0);
546 Node* b = m.Int32Constant(1);
547 Node* add = m.IntPtrSub(a, b);
548 EXPECT_THAT(add, IsIntPtrSub(a, b));
549 }
550}
551
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
553 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
554 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100555 Node* a = m.IntPtrConstant(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556 Node* add = m.WordShl(a, 10);
Ben Murdochda12d292016-06-02 14:46:10 +0100557 EXPECT_THAT(add, IsWordShl(a, IsIntPtrConstant(10)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000558 }
559}
560
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
562 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
563 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100564 Node* index = m.IntPtrConstant(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565 Node* load_constant = m.LoadConstantPoolEntry(index);
566 Matcher<Node*> constant_pool_matcher = m.IsLoad(
567 MachineType::AnyTagged(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100568 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
570 EXPECT_THAT(
571 load_constant,
572 m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
573 IsIntPtrAdd(
574 IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
Ben Murdochda12d292016-06-02 14:46:10 +0100575 IsWordShl(index, IsIntPtrConstant(kPointerSizeLog2)))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576 }
577}
578
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000579TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
580 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
581 InterpreterAssemblerForTest m(this, bytecode);
582 Node* object = m.IntPtrConstant(0xdeadbeef);
583 int offset = 16;
584 Node* load_field = m.LoadObjectField(object, offset);
585 EXPECT_THAT(load_field,
586 m.IsLoad(MachineType::AnyTagged(), object,
587 IsIntPtrConstant(offset - kHeapObjectTag)));
588 }
589}
590
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000591TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
592 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
593 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100594 Node* context = m.IntPtrConstant(1);
595 Node* slot_index = m.IntPtrConstant(22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596 Node* load_context_slot = m.LoadContextSlot(context, slot_index);
597
598 Matcher<Node*> offset =
Ben Murdochda12d292016-06-02 14:46:10 +0100599 IsIntPtrAdd(IsWordShl(slot_index, IsIntPtrConstant(kPointerSizeLog2)),
600 IsIntPtrConstant(Context::kHeaderSize - kHeapObjectTag));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601 EXPECT_THAT(load_context_slot,
602 m.IsLoad(MachineType::AnyTagged(), context, offset));
603 }
604}
605
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000606TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
607 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
608 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100609 Node* context = m.IntPtrConstant(1);
610 Node* slot_index = m.IntPtrConstant(22);
611 Node* value = m.SmiConstant(Smi::FromInt(100));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 Node* store_context_slot = m.StoreContextSlot(context, slot_index, value);
613
614 Matcher<Node*> offset =
Ben Murdochda12d292016-06-02 14:46:10 +0100615 IsIntPtrAdd(IsWordShl(slot_index, IsIntPtrConstant(kPointerSizeLog2)),
616 IsIntPtrConstant(Context::kHeaderSize - kHeapObjectTag));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000617 EXPECT_THAT(store_context_slot,
618 m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
619 kFullWriteBarrier),
620 context, offset, value));
621 }
622}
623
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
625 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
626 InterpreterAssemblerForTest m(this, bytecode);
627 Node* arg1 = m.Int32Constant(2);
628 Node* arg2 = m.Int32Constant(3);
Ben Murdochc5610432016-08-08 18:44:38 +0100629 Node* context = m.Int32Constant(4);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100630 Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
Ben Murdochc5610432016-08-08 18:44:38 +0100631 EXPECT_THAT(call_runtime,
632 IsCall(_, _, arg1, arg2, _, IsInt32Constant(2), context, _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 }
634}
635
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
637 const int kResultSizes[] = {1, 2};
638 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
639 TRACED_FOREACH(int, result_size, kResultSizes) {
640 InterpreterAssemblerForTest m(this, bytecode);
641 Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
642
643 Node* function_id = m.Int32Constant(0);
644 Node* first_arg = m.Int32Constant(1);
645 Node* arg_count = m.Int32Constant(2);
Ben Murdochc5610432016-08-08 18:44:38 +0100646 Node* context = m.Int32Constant(4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000647
648 Matcher<Node*> function_table = IsExternalConstant(
649 ExternalReference::runtime_function_table_address(isolate()));
650 Matcher<Node*> function = IsIntPtrAdd(
651 function_table,
652 IsInt32Mul(function_id, IsInt32Constant(sizeof(Runtime::Function))));
653 Matcher<Node*> function_entry =
654 m.IsLoad(MachineType::Pointer(), function,
Ben Murdochda12d292016-06-02 14:46:10 +0100655 IsIntPtrConstant(offsetof(Runtime::Function, entry)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000656
Ben Murdoch097c5b22016-05-18 11:27:45 +0100657 Node* call_runtime = m.CallRuntimeN(function_id, context, first_arg,
658 arg_count, result_size);
Ben Murdochc5610432016-08-08 18:44:38 +0100659 EXPECT_THAT(call_runtime,
660 IsCall(_, IsHeapConstant(builtin.code()), arg_count,
661 first_arg, function_entry, context, _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000662 }
663 }
664}
665
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100667 TailCallMode tail_call_modes[] = {TailCallMode::kDisallow,
668 TailCallMode::kAllow};
669 TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
670 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
671 InterpreterAssemblerForTest m(this, bytecode);
672 Callable builtin =
673 CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
674 Node* function = m.Int32Constant(0);
675 Node* first_arg = m.Int32Constant(1);
676 Node* arg_count = m.Int32Constant(2);
Ben Murdochc5610432016-08-08 18:44:38 +0100677 Node* context = m.Int32Constant(3);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100678 Node* call_js =
679 m.CallJS(function, context, first_arg, arg_count, tail_call_mode);
Ben Murdochc5610432016-08-08 18:44:38 +0100680 EXPECT_THAT(call_js, IsCall(_, IsHeapConstant(builtin.code()), arg_count,
681 first_arg, function, context, _, _));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100682 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 }
684}
685
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000686TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
687 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
688 InterpreterAssemblerForTest m(this, bytecode);
689 Node* feedback_vector = m.LoadTypeFeedbackVector();
690
Ben Murdochc5610432016-08-08 18:44:38 +0100691 Matcher<Node*> load_function_matcher =
692 m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
693 IsIntPtrConstant(Register::function_closure().ToOperand()
694 << kPointerSizeLog2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695 Matcher<Node*> load_shared_function_info_matcher =
696 m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
697 IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
698 kHeapObjectTag));
699
700 EXPECT_THAT(
701 feedback_vector,
702 m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher,
703 IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
704 kHeapObjectTag)));
705 }
706}
707
Ben Murdoch097c5b22016-05-18 11:27:45 +0100708} // namespace interpreter
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709} // namespace internal
710} // namespace v8