blob: 1bc80c0e4a7eeb635cd881c1a87eb9fdfdb77bfa [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;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100431 case interpreter::OperandType::kIntrinsicId:
432 EXPECT_THAT(m.BytecodeOperandIntrinsicId(i),
433 m.IsUnsignedOperand(offset, operand_size));
434 break;
Ben Murdochda12d292016-06-02 14:46:10 +0100435 case interpreter::OperandType::kNone:
436 UNREACHABLE();
437 break;
438 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000439 }
440 }
441 }
442}
443
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000444TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
445 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
Ben Murdochda12d292016-06-02 14:46:10 +0100446 if (!interpreter::Bytecodes::ReadsAccumulator(bytecode) ||
447 !interpreter::Bytecodes::WritesAccumulator(bytecode)) {
448 continue;
449 }
450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 InterpreterAssemblerForTest m(this, bytecode);
452 // Should be incoming accumulator if not set.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100453 EXPECT_THAT(
454 m.GetAccumulator(),
455 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100456 // Should be set by SetAccumulator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
458 m.SetAccumulator(accumulator_value_1);
459 EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
460 Node* accumulator_value_2 = m.Int32Constant(42);
461 m.SetAccumulator(accumulator_value_2);
462 EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
463
464 // Should be passed to next bytecode handler on dispatch.
Ben Murdochc5610432016-08-08 18:44:38 +0100465 Node* tail_call_node = m.Dispatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466
467 EXPECT_THAT(tail_call_node,
Ben Murdochc5610432016-08-08 18:44:38 +0100468 IsTailCall(_, _, accumulator_value_2, _, _, _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 }
470}
471
Ben Murdochc5610432016-08-08 18:44:38 +0100472TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100473 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
474 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochc5610432016-08-08 18:44:38 +0100475 EXPECT_THAT(
476 m.GetContext(),
477 m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
478 IsIntPtrConstant(Register::current_context().ToOperand()
479 << kPointerSizeLog2)));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100480 }
481}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000482
483TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
484 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
485 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100486 Node* reg_index_node = m.IntPtrConstant(44);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000487 Node* reg_location_node = m.RegisterLocation(reg_index_node);
Ben Murdochc5610432016-08-08 18:44:38 +0100488 EXPECT_THAT(reg_location_node,
489 IsIntPtrAdd(IsLoadParentFramePointer(),
490 IsWordShl(reg_index_node,
491 IsIntPtrConstant(kPointerSizeLog2))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000492 }
493}
494
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000495TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
496 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
497 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100498 Node* reg_index_node = m.IntPtrConstant(44);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 Node* load_reg_node = m.LoadRegister(reg_index_node);
Ben Murdochc5610432016-08-08 18:44:38 +0100500 EXPECT_THAT(load_reg_node,
501 m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
502 IsWordShl(reg_index_node,
503 IsIntPtrConstant(kPointerSizeLog2))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 }
505}
506
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000507TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
508 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
509 InterpreterAssemblerForTest m(this, bytecode);
510 Node* store_value = m.Int32Constant(0xdeadbeef);
Ben Murdochda12d292016-06-02 14:46:10 +0100511 Node* reg_index_node = m.IntPtrConstant(44);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000512 Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
513 EXPECT_THAT(
514 store_reg_node,
Ben Murdochc5610432016-08-08 18:44:38 +0100515 m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
516 kNoWriteBarrier),
517 IsLoadParentFramePointer(),
518 IsWordShl(reg_index_node, IsIntPtrConstant(kPointerSizeLog2)),
519 store_value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000520 }
521}
522
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000523TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
524 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
525 InterpreterAssemblerForTest m(this, bytecode);
526 Node* value = m.Int32Constant(44);
Ben Murdochc5610432016-08-08 18:44:38 +0100527 EXPECT_THAT(m.SmiTag(value),
528 IsIntPtrConstant(static_cast<intptr_t>(44)
529 << (kSmiShiftSize + kSmiTagSize)));
Ben Murdochda12d292016-06-02 14:46:10 +0100530 EXPECT_THAT(
531 m.SmiUntag(value),
532 IsWordSar(value, IsIntPtrConstant(kSmiShiftSize + kSmiTagSize)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000533 }
534}
535
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
537 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
538 InterpreterAssemblerForTest m(this, bytecode);
539 Node* a = m.Int32Constant(0);
540 Node* b = m.Int32Constant(1);
541 Node* add = m.IntPtrAdd(a, b);
542 EXPECT_THAT(add, IsIntPtrAdd(a, b));
543 }
544}
545
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000546TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
547 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
548 InterpreterAssemblerForTest m(this, bytecode);
549 Node* a = m.Int32Constant(0);
550 Node* b = m.Int32Constant(1);
551 Node* add = m.IntPtrSub(a, b);
552 EXPECT_THAT(add, IsIntPtrSub(a, b));
553 }
554}
555
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000556TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
557 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
558 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100559 Node* a = m.IntPtrConstant(0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000560 Node* add = m.WordShl(a, 10);
Ben Murdochda12d292016-06-02 14:46:10 +0100561 EXPECT_THAT(add, IsWordShl(a, IsIntPtrConstant(10)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000562 }
563}
564
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000565TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
566 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
567 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100568 Node* index = m.IntPtrConstant(2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000569 Node* load_constant = m.LoadConstantPoolEntry(index);
570 Matcher<Node*> constant_pool_matcher = m.IsLoad(
571 MachineType::AnyTagged(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100572 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573 IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
574 EXPECT_THAT(
575 load_constant,
576 m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
577 IsIntPtrAdd(
578 IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
Ben Murdochda12d292016-06-02 14:46:10 +0100579 IsWordShl(index, IsIntPtrConstant(kPointerSizeLog2)))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 }
581}
582
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
584 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
585 InterpreterAssemblerForTest m(this, bytecode);
586 Node* object = m.IntPtrConstant(0xdeadbeef);
587 int offset = 16;
588 Node* load_field = m.LoadObjectField(object, offset);
589 EXPECT_THAT(load_field,
590 m.IsLoad(MachineType::AnyTagged(), object,
591 IsIntPtrConstant(offset - kHeapObjectTag)));
592 }
593}
594
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000595TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
596 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
597 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100598 Node* context = m.IntPtrConstant(1);
599 Node* slot_index = m.IntPtrConstant(22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000600 Node* load_context_slot = m.LoadContextSlot(context, slot_index);
601
602 Matcher<Node*> offset =
Ben Murdochda12d292016-06-02 14:46:10 +0100603 IsIntPtrAdd(IsWordShl(slot_index, IsIntPtrConstant(kPointerSizeLog2)),
604 IsIntPtrConstant(Context::kHeaderSize - kHeapObjectTag));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000605 EXPECT_THAT(load_context_slot,
606 m.IsLoad(MachineType::AnyTagged(), context, offset));
607 }
608}
609
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
611 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
612 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdochda12d292016-06-02 14:46:10 +0100613 Node* context = m.IntPtrConstant(1);
614 Node* slot_index = m.IntPtrConstant(22);
615 Node* value = m.SmiConstant(Smi::FromInt(100));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000616 Node* store_context_slot = m.StoreContextSlot(context, slot_index, value);
617
618 Matcher<Node*> offset =
Ben Murdochda12d292016-06-02 14:46:10 +0100619 IsIntPtrAdd(IsWordShl(slot_index, IsIntPtrConstant(kPointerSizeLog2)),
620 IsIntPtrConstant(Context::kHeaderSize - kHeapObjectTag));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000621 EXPECT_THAT(store_context_slot,
622 m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
623 kFullWriteBarrier),
624 context, offset, value));
625 }
626}
627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
629 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
630 InterpreterAssemblerForTest m(this, bytecode);
631 Node* arg1 = m.Int32Constant(2);
632 Node* arg2 = m.Int32Constant(3);
Ben Murdochc5610432016-08-08 18:44:38 +0100633 Node* context = m.Int32Constant(4);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100634 Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
Ben Murdochc5610432016-08-08 18:44:38 +0100635 EXPECT_THAT(call_runtime,
636 IsCall(_, _, arg1, arg2, _, IsInt32Constant(2), context, _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000637 }
638}
639
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
641 const int kResultSizes[] = {1, 2};
642 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
643 TRACED_FOREACH(int, result_size, kResultSizes) {
644 InterpreterAssemblerForTest m(this, bytecode);
645 Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
646
647 Node* function_id = m.Int32Constant(0);
648 Node* first_arg = m.Int32Constant(1);
649 Node* arg_count = m.Int32Constant(2);
Ben Murdochc5610432016-08-08 18:44:38 +0100650 Node* context = m.Int32Constant(4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000651
652 Matcher<Node*> function_table = IsExternalConstant(
653 ExternalReference::runtime_function_table_address(isolate()));
654 Matcher<Node*> function = IsIntPtrAdd(
655 function_table,
656 IsInt32Mul(function_id, IsInt32Constant(sizeof(Runtime::Function))));
657 Matcher<Node*> function_entry =
658 m.IsLoad(MachineType::Pointer(), function,
Ben Murdochda12d292016-06-02 14:46:10 +0100659 IsIntPtrConstant(offsetof(Runtime::Function, entry)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000660
Ben Murdoch097c5b22016-05-18 11:27:45 +0100661 Node* call_runtime = m.CallRuntimeN(function_id, context, first_arg,
662 arg_count, result_size);
Ben Murdochc5610432016-08-08 18:44:38 +0100663 EXPECT_THAT(call_runtime,
664 IsCall(_, IsHeapConstant(builtin.code()), arg_count,
665 first_arg, function_entry, context, _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000666 }
667 }
668}
669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100671 TailCallMode tail_call_modes[] = {TailCallMode::kDisallow,
672 TailCallMode::kAllow};
673 TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
674 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
675 InterpreterAssemblerForTest m(this, bytecode);
676 Callable builtin =
677 CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
678 Node* function = m.Int32Constant(0);
679 Node* first_arg = m.Int32Constant(1);
680 Node* arg_count = m.Int32Constant(2);
Ben Murdochc5610432016-08-08 18:44:38 +0100681 Node* context = m.Int32Constant(3);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100682 Node* call_js =
683 m.CallJS(function, context, first_arg, arg_count, tail_call_mode);
Ben Murdochc5610432016-08-08 18:44:38 +0100684 EXPECT_THAT(call_js, IsCall(_, IsHeapConstant(builtin.code()), arg_count,
685 first_arg, function, context, _, _));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100686 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000687 }
688}
689
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000690TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
691 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
692 InterpreterAssemblerForTest m(this, bytecode);
693 Node* feedback_vector = m.LoadTypeFeedbackVector();
694
Ben Murdochc5610432016-08-08 18:44:38 +0100695 Matcher<Node*> load_function_matcher =
696 m.IsLoad(MachineType::AnyTagged(), IsLoadParentFramePointer(),
697 IsIntPtrConstant(Register::function_closure().ToOperand()
698 << kPointerSizeLog2));
Ben Murdoch61f157c2016-09-16 13:49:30 +0100699 Matcher<Node*> load_literals_matcher = m.IsLoad(
700 MachineType::AnyTagged(), load_function_matcher,
701 IsIntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000702
Ben Murdoch61f157c2016-09-16 13:49:30 +0100703 EXPECT_THAT(feedback_vector,
704 m.IsLoad(MachineType::AnyTagged(), load_literals_matcher,
705 IsIntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
706 kHeapObjectTag)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000707 }
708}
709
Ben Murdoch097c5b22016-05-18 11:27:45 +0100710} // namespace interpreter
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000711} // namespace internal
712} // namespace v8