blob: f57ca05b3f16630d96fe6f620c4910f13fdb67ad [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
5#include "test/unittests/compiler/interpreter-assembler-unittest.h"
6
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 {
19namespace compiler {
20
21const interpreter::Bytecode kBytecodes[] = {
22#define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
23 BYTECODE_LIST(DEFINE_BYTECODE)
24#undef DEFINE_BYTECODE
25};
26
27
28Matcher<Node*> IsIntPtrConstant(const intptr_t value) {
29 return kPointerSize == 8 ? IsInt64Constant(static_cast<int64_t>(value))
30 : IsInt32Constant(static_cast<int32_t>(value));
31}
32
33
34Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
35 const Matcher<Node*>& rhs_matcher) {
36 return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
37 : IsInt32Add(lhs_matcher, rhs_matcher);
38}
39
40
41Matcher<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
47
48Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
49 const Matcher<Node*>& rhs_matcher) {
50 return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
51 : IsWord32Shl(lhs_matcher, rhs_matcher);
52}
53
54
55Matcher<Node*> IsWordSar(const Matcher<Node*>& lhs_matcher,
56 const Matcher<Node*>& rhs_matcher) {
57 return kPointerSize == 8 ? IsWord64Sar(lhs_matcher, rhs_matcher)
58 : IsWord32Sar(lhs_matcher, rhs_matcher);
59}
60
61
62Matcher<Node*> IsWordOr(const Matcher<Node*>& lhs_matcher,
63 const Matcher<Node*>& rhs_matcher) {
64 return kPointerSize == 8 ? IsWord64Or(lhs_matcher, rhs_matcher)
65 : IsWord32Or(lhs_matcher, rhs_matcher);
66}
67
68
69Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
70 const Matcher<LoadRepresentation>& rep_matcher,
71 const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher) {
72 return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
73}
74
75
76Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
77 const Matcher<StoreRepresentation>& rep_matcher,
78 const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
79 const Matcher<Node*>& value_matcher) {
80 return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher,
81 value_matcher, _, _);
82}
83
84
85Matcher<Node*>
86InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
87 int offset) {
88 return IsLoad(
89 MachineType::Uint8(),
90 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
91 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
92 IsInt32Constant(offset)));
93}
94
95
96Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
97 IsBytecodeOperandSignExtended(int offset) {
98 Matcher<Node*> load_matcher = IsLoad(
99 MachineType::Int8(),
100 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
101 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
102 IsInt32Constant(offset)));
103 if (kPointerSize == 8) {
104 load_matcher = IsChangeInt32ToInt64(load_matcher);
105 }
106 return load_matcher;
107}
108
109
110Matcher<Node*>
111InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperandShort(
112 int offset) {
113 if (TargetSupportsUnalignedAccess()) {
114 return IsLoad(
115 MachineType::Uint16(),
116 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
117 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
118 IsInt32Constant(offset)));
119 } else {
120 Matcher<Node*> first_byte = IsLoad(
121 MachineType::Uint8(),
122 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
123 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
124 IsInt32Constant(offset)));
125 Matcher<Node*> second_byte = IsLoad(
126 MachineType::Uint8(),
127 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
128 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
129 IsInt32Constant(offset + 1)));
130#if V8_TARGET_LITTLE_ENDIAN
131 return IsWordOr(IsWordShl(second_byte, IsInt32Constant(kBitsPerByte)),
132 first_byte);
133#elif V8_TARGET_BIG_ENDIAN
134 return IsWordOr(IsWordShl(first_byte, IsInt32Constant(kBitsPerByte)),
135 second_byte);
136#else
137#error "Unknown Architecture"
138#endif
139 }
140}
141
142
143Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
144 IsBytecodeOperandShortSignExtended(int offset) {
145 Matcher<Node*> load_matcher;
146 if (TargetSupportsUnalignedAccess()) {
147 load_matcher = IsLoad(
148 MachineType::Int16(),
149 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
150 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
151 IsInt32Constant(offset)));
152 } else {
153#if V8_TARGET_LITTLE_ENDIAN
154 int hi_byte_offset = offset + 1;
155 int lo_byte_offset = offset;
156
157#elif V8_TARGET_BIG_ENDIAN
158 int hi_byte_offset = offset;
159 int lo_byte_offset = offset + 1;
160#else
161#error "Unknown Architecture"
162#endif
163 Matcher<Node*> hi_byte = IsLoad(
164 MachineType::Int8(),
165 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
166 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
167 IsInt32Constant(hi_byte_offset)));
168 hi_byte = IsWord32Shl(hi_byte, IsInt32Constant(kBitsPerByte));
169 Matcher<Node*> lo_byte = IsLoad(
170 MachineType::Uint8(),
171 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
172 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
173 IsInt32Constant(lo_byte_offset)));
174 load_matcher = IsWord32Or(hi_byte, lo_byte);
175 }
176
177 if (kPointerSize == 8) {
178 load_matcher = IsChangeInt32ToInt64(load_matcher);
179 }
180 return load_matcher;
181}
182
183
184TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
185 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
186 InterpreterAssemblerForTest m(this, bytecode);
187 m.Dispatch();
188 Graph* graph = m.graph();
189
190 Node* end = graph->end();
191 EXPECT_EQ(1, end->InputCount());
192 Node* tail_call_node = end->InputAt(0);
193
194 Matcher<Node*> next_bytecode_offset_matcher =
195 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
196 IsInt32Constant(interpreter::Bytecodes::Size(bytecode)));
197 Matcher<Node*> target_bytecode_matcher =
198 m.IsLoad(MachineType::Uint8(),
199 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
200 next_bytecode_offset_matcher);
201 Matcher<Node*> code_target_matcher =
202 m.IsLoad(MachineType::Pointer(),
203 IsParameter(Linkage::kInterpreterDispatchTableParameter),
204 IsWord32Shl(target_bytecode_matcher,
205 IsInt32Constant(kPointerSizeLog2)));
206
207 EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
208 EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
209 EXPECT_THAT(
210 tail_call_node,
211 IsTailCall(m.call_descriptor(), code_target_matcher,
212 IsParameter(Linkage::kInterpreterAccumulatorParameter),
213 IsParameter(Linkage::kInterpreterRegisterFileParameter),
214 next_bytecode_offset_matcher,
215 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
216 IsParameter(Linkage::kInterpreterDispatchTableParameter),
217 IsParameter(Linkage::kInterpreterContextParameter), _, _));
218 }
219}
220
221
222TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
223 int jump_offsets[] = {-9710, -77, 0, +3, +97109};
224 TRACED_FOREACH(int, jump_offset, jump_offsets) {
225 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
226 InterpreterAssemblerForTest m(this, bytecode);
227 m.Jump(m.Int32Constant(jump_offset));
228 Graph* graph = m.graph();
229 Node* end = graph->end();
230 EXPECT_EQ(1, end->InputCount());
231 Node* tail_call_node = end->InputAt(0);
232
233 Matcher<Node*> next_bytecode_offset_matcher =
234 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
235 IsInt32Constant(jump_offset));
236 Matcher<Node*> target_bytecode_matcher =
237 m.IsLoad(MachineType::Uint8(),
238 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
239 next_bytecode_offset_matcher);
240 Matcher<Node*> code_target_matcher =
241 m.IsLoad(MachineType::Pointer(),
242 IsParameter(Linkage::kInterpreterDispatchTableParameter),
243 IsWord32Shl(target_bytecode_matcher,
244 IsInt32Constant(kPointerSizeLog2)));
245
246 EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
247 EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
248 EXPECT_THAT(
249 tail_call_node,
250 IsTailCall(m.call_descriptor(), code_target_matcher,
251 IsParameter(Linkage::kInterpreterAccumulatorParameter),
252 IsParameter(Linkage::kInterpreterRegisterFileParameter),
253 next_bytecode_offset_matcher,
254 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
255 IsParameter(Linkage::kInterpreterDispatchTableParameter),
256 IsParameter(Linkage::kInterpreterContextParameter), _, _));
257 }
258 }
259}
260
261
262TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
263 static const int kJumpIfTrueOffset = 73;
264
265 MachineOperatorBuilder machine(zone());
266
267 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
268 InterpreterAssemblerForTest m(this, bytecode);
269 Node* lhs = m.IntPtrConstant(0);
270 Node* rhs = m.IntPtrConstant(1);
271 m.JumpIfWordEqual(lhs, rhs, m.Int32Constant(kJumpIfTrueOffset));
272 Graph* graph = m.graph();
273 Node* end = graph->end();
274 EXPECT_EQ(2, end->InputCount());
275
276 int jump_offsets[] = {kJumpIfTrueOffset,
277 interpreter::Bytecodes::Size(bytecode)};
278 for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) {
279 Matcher<Node*> next_bytecode_offset_matcher =
280 IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
281 IsInt32Constant(jump_offsets[i]));
282 Matcher<Node*> target_bytecode_matcher =
283 m.IsLoad(MachineType::Uint8(),
284 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
285 next_bytecode_offset_matcher);
286 Matcher<Node*> code_target_matcher =
287 m.IsLoad(MachineType::Pointer(),
288 IsParameter(Linkage::kInterpreterDispatchTableParameter),
289 IsWord32Shl(target_bytecode_matcher,
290 IsInt32Constant(kPointerSizeLog2)));
291 EXPECT_THAT(
292 end->InputAt(i),
293 IsTailCall(m.call_descriptor(), code_target_matcher,
294 IsParameter(Linkage::kInterpreterAccumulatorParameter),
295 IsParameter(Linkage::kInterpreterRegisterFileParameter),
296 next_bytecode_offset_matcher,
297 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
298 IsParameter(Linkage::kInterpreterDispatchTableParameter),
299 IsParameter(Linkage::kInterpreterContextParameter), _, _));
300 }
301
302 // TODO(oth): test control flow paths.
303 }
304}
305
306
307TARGET_TEST_F(InterpreterAssemblerTest, Return) {
308 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
309 InterpreterAssemblerForTest m(this, bytecode);
310 m.Return();
311 Graph* graph = m.graph();
312
313 Node* end = graph->end();
314 EXPECT_EQ(1, end->InputCount());
315 Node* tail_call_node = end->InputAt(0);
316
317 EXPECT_EQ(CallDescriptor::kCallCodeObject, m.call_descriptor()->kind());
318 EXPECT_TRUE(m.call_descriptor()->flags() & CallDescriptor::kCanUseRoots);
319 Handle<HeapObject> exit_trampoline =
320 isolate()->builtins()->InterpreterExitTrampoline();
321 EXPECT_THAT(
322 tail_call_node,
323 IsTailCall(m.call_descriptor(), IsHeapConstant(exit_trampoline),
324 IsParameter(Linkage::kInterpreterAccumulatorParameter),
325 IsParameter(Linkage::kInterpreterRegisterFileParameter),
326 IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
327 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
328 IsParameter(Linkage::kInterpreterDispatchTableParameter),
329 IsParameter(Linkage::kInterpreterContextParameter), _, _));
330 }
331}
332
333
334TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
335 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
336 InterpreterAssemblerForTest m(this, bytecode);
337 int number_of_operands = interpreter::Bytecodes::NumberOfOperands(bytecode);
338 for (int i = 0; i < number_of_operands; i++) {
339 int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i);
340 switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
341 case interpreter::OperandType::kCount8:
342 EXPECT_THAT(m.BytecodeOperandCount(i), m.IsBytecodeOperand(offset));
343 break;
344 case interpreter::OperandType::kIdx8:
345 EXPECT_THAT(m.BytecodeOperandIdx(i), m.IsBytecodeOperand(offset));
346 break;
347 case interpreter::OperandType::kImm8:
348 EXPECT_THAT(m.BytecodeOperandImm(i),
349 m.IsBytecodeOperandSignExtended(offset));
350 break;
351 case interpreter::OperandType::kMaybeReg8:
352 case interpreter::OperandType::kReg8:
353 case interpreter::OperandType::kRegPair8:
354 EXPECT_THAT(m.BytecodeOperandReg(i),
355 m.IsBytecodeOperandSignExtended(offset));
356 break;
357 case interpreter::OperandType::kCount16:
358 EXPECT_THAT(m.BytecodeOperandCount(i),
359 m.IsBytecodeOperandShort(offset));
360 break;
361 case interpreter::OperandType::kIdx16:
362 EXPECT_THAT(m.BytecodeOperandIdx(i),
363 m.IsBytecodeOperandShort(offset));
364 break;
365 case interpreter::OperandType::kReg16:
366 EXPECT_THAT(m.BytecodeOperandReg(i),
367 m.IsBytecodeOperandShortSignExtended(offset));
368 break;
369 case interpreter::OperandType::kNone:
370 UNREACHABLE();
371 break;
372 }
373 }
374 }
375}
376
377
378TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
379 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
380 InterpreterAssemblerForTest m(this, bytecode);
381 // Should be incoming accumulator if not set.
382 EXPECT_THAT(m.GetAccumulator(),
383 IsParameter(Linkage::kInterpreterAccumulatorParameter));
384
385 // Should be set by SedtAccumulator.
386 Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
387 m.SetAccumulator(accumulator_value_1);
388 EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
389 Node* accumulator_value_2 = m.Int32Constant(42);
390 m.SetAccumulator(accumulator_value_2);
391 EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
392
393 // Should be passed to next bytecode handler on dispatch.
394 m.Dispatch();
395 Graph* graph = m.graph();
396
397 Node* end = graph->end();
398 EXPECT_EQ(1, end->InputCount());
399 Node* tail_call_node = end->InputAt(0);
400
401 EXPECT_THAT(tail_call_node,
402 IsTailCall(m.call_descriptor(), _, accumulator_value_2, _, _, _,
403 _, _, _));
404 }
405}
406
407
408TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
409 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
410 InterpreterAssemblerForTest m(this, bytecode);
411 Node* reg_index_node = m.Int32Constant(44);
412 Node* reg_location_node = m.RegisterLocation(reg_index_node);
413 EXPECT_THAT(
414 reg_location_node,
415 IsIntPtrAdd(
416 IsParameter(Linkage::kInterpreterRegisterFileParameter),
417 IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
418 }
419}
420
421
422TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
423 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
424 InterpreterAssemblerForTest m(this, bytecode);
425 Node* reg_index_node = m.Int32Constant(44);
426 Node* load_reg_node = m.LoadRegister(reg_index_node);
427 EXPECT_THAT(
428 load_reg_node,
429 m.IsLoad(MachineType::AnyTagged(),
430 IsParameter(Linkage::kInterpreterRegisterFileParameter),
431 IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
432 }
433}
434
435
436TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
437 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
438 InterpreterAssemblerForTest m(this, bytecode);
439 Node* store_value = m.Int32Constant(0xdeadbeef);
440 Node* reg_index_node = m.Int32Constant(44);
441 Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
442 EXPECT_THAT(
443 store_reg_node,
444 m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
445 kNoWriteBarrier),
446 IsParameter(Linkage::kInterpreterRegisterFileParameter),
447 IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
448 store_value));
449 }
450}
451
452
453TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
454 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
455 InterpreterAssemblerForTest m(this, bytecode);
456 Node* value = m.Int32Constant(44);
457 EXPECT_THAT(m.SmiTag(value),
458 IsWordShl(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
459 EXPECT_THAT(m.SmiUntag(value),
460 IsWordSar(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
461 }
462}
463
464
465TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
466 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
467 InterpreterAssemblerForTest m(this, bytecode);
468 Node* a = m.Int32Constant(0);
469 Node* b = m.Int32Constant(1);
470 Node* add = m.IntPtrAdd(a, b);
471 EXPECT_THAT(add, IsIntPtrAdd(a, b));
472 }
473}
474
475
476TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
477 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
478 InterpreterAssemblerForTest m(this, bytecode);
479 Node* a = m.Int32Constant(0);
480 Node* b = m.Int32Constant(1);
481 Node* add = m.IntPtrSub(a, b);
482 EXPECT_THAT(add, IsIntPtrSub(a, b));
483 }
484}
485
486
487TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
488 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
489 InterpreterAssemblerForTest m(this, bytecode);
490 Node* a = m.Int32Constant(0);
491 Node* add = m.WordShl(a, 10);
492 EXPECT_THAT(add, IsWordShl(a, IsInt32Constant(10)));
493 }
494}
495
496
497TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
498 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
499 InterpreterAssemblerForTest m(this, bytecode);
500 Node* index = m.Int32Constant(2);
501 Node* load_constant = m.LoadConstantPoolEntry(index);
502 Matcher<Node*> constant_pool_matcher = m.IsLoad(
503 MachineType::AnyTagged(),
504 IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
505 IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
506 EXPECT_THAT(
507 load_constant,
508 m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
509 IsIntPtrAdd(
510 IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
511 IsWordShl(index, IsInt32Constant(kPointerSizeLog2)))));
512 }
513}
514
515
516TARGET_TEST_F(InterpreterAssemblerTest, LoadFixedArrayElement) {
517 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
518 InterpreterAssemblerForTest m(this, bytecode);
519 int index = 3;
520 Node* fixed_array = m.IntPtrConstant(0xdeadbeef);
521 Node* load_element = m.LoadFixedArrayElement(fixed_array, index);
522 EXPECT_THAT(
523 load_element,
524 m.IsLoad(MachineType::AnyTagged(), fixed_array,
525 IsIntPtrAdd(
526 IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
527 IsWordShl(IsInt32Constant(index),
528 IsInt32Constant(kPointerSizeLog2)))));
529 }
530}
531
532
533TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
534 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
535 InterpreterAssemblerForTest m(this, bytecode);
536 Node* object = m.IntPtrConstant(0xdeadbeef);
537 int offset = 16;
538 Node* load_field = m.LoadObjectField(object, offset);
539 EXPECT_THAT(load_field,
540 m.IsLoad(MachineType::AnyTagged(), object,
541 IsIntPtrConstant(offset - kHeapObjectTag)));
542 }
543}
544
545
546TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
547 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
548 InterpreterAssemblerForTest m(this, bytecode);
549 Node* context = m.Int32Constant(1);
550 Node* slot_index = m.Int32Constant(22);
551 Node* load_context_slot = m.LoadContextSlot(context, slot_index);
552
553 Matcher<Node*> offset =
554 IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
555 IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
556 EXPECT_THAT(load_context_slot,
557 m.IsLoad(MachineType::AnyTagged(), context, offset));
558 }
559}
560
561
562TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
563 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
564 InterpreterAssemblerForTest m(this, bytecode);
565 Node* context = m.Int32Constant(1);
566 Node* slot_index = m.Int32Constant(22);
567 Node* value = m.Int32Constant(100);
568 Node* store_context_slot = m.StoreContextSlot(context, slot_index, value);
569
570 Matcher<Node*> offset =
571 IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
572 IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
573 EXPECT_THAT(store_context_slot,
574 m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
575 kFullWriteBarrier),
576 context, offset, value));
577 }
578}
579
580
581TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
582 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
583 InterpreterAssemblerForTest m(this, bytecode);
584 Node* arg1 = m.Int32Constant(2);
585 Node* arg2 = m.Int32Constant(3);
586 Node* call_runtime = m.CallRuntime(Runtime::kAdd, arg1, arg2);
587 EXPECT_THAT(
588 call_runtime,
589 IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
590 IsParameter(Linkage::kInterpreterContextParameter), _, _));
591 }
592}
593
594
595TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
596 const int kResultSizes[] = {1, 2};
597 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
598 TRACED_FOREACH(int, result_size, kResultSizes) {
599 InterpreterAssemblerForTest m(this, bytecode);
600 Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
601
602 Node* function_id = m.Int32Constant(0);
603 Node* first_arg = m.Int32Constant(1);
604 Node* arg_count = m.Int32Constant(2);
605
606 Matcher<Node*> function_table = IsExternalConstant(
607 ExternalReference::runtime_function_table_address(isolate()));
608 Matcher<Node*> function = IsIntPtrAdd(
609 function_table,
610 IsInt32Mul(function_id, IsInt32Constant(sizeof(Runtime::Function))));
611 Matcher<Node*> function_entry =
612 m.IsLoad(MachineType::Pointer(), function,
613 IsInt32Constant(offsetof(Runtime::Function, entry)));
614
615 Node* call_runtime =
616 m.CallRuntime(function_id, first_arg, arg_count, result_size);
617 EXPECT_THAT(
618 call_runtime,
619 IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
620 function_entry,
621 IsParameter(Linkage::kInterpreterContextParameter), _, _));
622 }
623 }
624}
625
626
627TARGET_TEST_F(InterpreterAssemblerTest, CallIC) {
628 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
629 InterpreterAssemblerForTest m(this, bytecode);
630 LoadWithVectorDescriptor descriptor(isolate());
631 Node* target = m.Int32Constant(1);
632 Node* arg1 = m.Int32Constant(2);
633 Node* arg2 = m.Int32Constant(3);
634 Node* arg3 = m.Int32Constant(4);
635 Node* arg4 = m.Int32Constant(5);
636 Node* call_ic = m.CallIC(descriptor, target, arg1, arg2, arg3, arg4);
637 EXPECT_THAT(
638 call_ic,
639 IsCall(_, target, arg1, arg2, arg3, arg4,
640 IsParameter(Linkage::kInterpreterContextParameter), _, _));
641 }
642}
643
644
645TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
646 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
647 InterpreterAssemblerForTest m(this, bytecode);
648 Callable builtin = CodeFactory::InterpreterPushArgsAndCall(isolate());
649 Node* function = m.Int32Constant(0);
650 Node* first_arg = m.Int32Constant(1);
651 Node* arg_count = m.Int32Constant(2);
652 Node* call_js = m.CallJS(function, first_arg, arg_count);
653 EXPECT_THAT(
654 call_js,
655 IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
656 function, IsParameter(Linkage::kInterpreterContextParameter), _,
657 _));
658 }
659}
660
661
662TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
663 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
664 InterpreterAssemblerForTest m(this, bytecode);
665 Node* feedback_vector = m.LoadTypeFeedbackVector();
666
667 Matcher<Node*> load_function_matcher =
668 m.IsLoad(MachineType::AnyTagged(),
669 IsParameter(Linkage::kInterpreterRegisterFileParameter),
670 IsIntPtrConstant(
671 InterpreterFrameConstants::kFunctionFromRegisterPointer));
672 Matcher<Node*> load_shared_function_info_matcher =
673 m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
674 IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
675 kHeapObjectTag));
676
677 EXPECT_THAT(
678 feedback_vector,
679 m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher,
680 IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
681 kHeapObjectTag)));
682 }
683}
684
685} // namespace compiler
686} // namespace internal
687} // namespace v8