blob: 3375a6b81743dc5493642ab66ef9cb29d0f76e42 [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 Murdoch4a90d5f2016-03-22 12:00:34 +000065Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
66 const Matcher<LoadRepresentation>& rep_matcher,
67 const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher) {
68 return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
69}
70
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
72 const Matcher<StoreRepresentation>& rep_matcher,
73 const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
74 const Matcher<Node*>& value_matcher) {
75 return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher,
76 value_matcher, _, _);
77}
78
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000079Matcher<Node*>
80InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
81 int offset) {
82 return IsLoad(
83 MachineType::Uint8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +010084 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
85 IsIntPtrAdd(
86 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
87 IsInt32Constant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088}
89
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000090Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
91 IsBytecodeOperandSignExtended(int offset) {
92 Matcher<Node*> load_matcher = IsLoad(
93 MachineType::Int8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +010094 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
95 IsIntPtrAdd(
96 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
97 IsInt32Constant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 if (kPointerSize == 8) {
99 load_matcher = IsChangeInt32ToInt64(load_matcher);
100 }
101 return load_matcher;
102}
103
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104Matcher<Node*>
105InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperandShort(
106 int offset) {
107 if (TargetSupportsUnalignedAccess()) {
108 return IsLoad(
109 MachineType::Uint16(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100110 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
111 IsIntPtrAdd(
112 IsParameter(
113 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
114 IsInt32Constant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000115 } else {
116 Matcher<Node*> first_byte = IsLoad(
117 MachineType::Uint8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100118 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
119 IsIntPtrAdd(
120 IsParameter(
121 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
122 IsInt32Constant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123 Matcher<Node*> second_byte = IsLoad(
124 MachineType::Uint8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
126 IsIntPtrAdd(
127 IsParameter(
128 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
129 IsInt32Constant(offset + 1)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000130#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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000142Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
143 IsBytecodeOperandShortSignExtended(int offset) {
144 Matcher<Node*> load_matcher;
145 if (TargetSupportsUnalignedAccess()) {
146 load_matcher = IsLoad(
147 MachineType::Int16(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100148 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
149 IsIntPtrAdd(
150 IsParameter(
151 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
152 IsInt32Constant(offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 } else {
154#if V8_TARGET_LITTLE_ENDIAN
155 int hi_byte_offset = offset + 1;
156 int lo_byte_offset = offset;
157
158#elif V8_TARGET_BIG_ENDIAN
159 int hi_byte_offset = offset;
160 int lo_byte_offset = offset + 1;
161#else
162#error "Unknown Architecture"
163#endif
164 Matcher<Node*> hi_byte = IsLoad(
165 MachineType::Int8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100166 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
167 IsIntPtrAdd(
168 IsParameter(
169 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
170 IsInt32Constant(hi_byte_offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 hi_byte = IsWord32Shl(hi_byte, IsInt32Constant(kBitsPerByte));
172 Matcher<Node*> lo_byte = IsLoad(
173 MachineType::Uint8(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100174 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
175 IsIntPtrAdd(
176 IsParameter(
177 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
178 IsInt32Constant(lo_byte_offset)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179 load_matcher = IsWord32Or(hi_byte, lo_byte);
180 }
181
182 if (kPointerSize == 8) {
183 load_matcher = IsChangeInt32ToInt64(load_matcher);
184 }
185 return load_matcher;
186}
187
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000188TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
189 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
190 InterpreterAssemblerForTest m(this, bytecode);
191 m.Dispatch();
192 Graph* graph = m.graph();
193
194 Node* end = graph->end();
195 EXPECT_EQ(1, end->InputCount());
196 Node* tail_call_node = end->InputAt(0);
197
Ben Murdoch097c5b22016-05-18 11:27:45 +0100198 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
199 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
200 IsInt32Constant(interpreter::Bytecodes::Size(bytecode)));
201 Matcher<Node*> target_bytecode_matcher = m.IsLoad(
202 MachineType::Uint8(),
203 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
204 next_bytecode_offset_matcher);
205 Matcher<Node*> code_target_matcher = m.IsLoad(
206 MachineType::Pointer(),
207 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
208 IsWord32Shl(target_bytecode_matcher,
209 IsInt32Constant(kPointerSizeLog2)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 EXPECT_THAT(
212 tail_call_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100213 IsTailCall(
214 _, code_target_matcher,
215 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
216 IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
217 next_bytecode_offset_matcher,
218 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
219 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
220 IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
221 _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 }
223}
224
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100226 // If debug code is enabled we emit extra code in Jump.
227 if (FLAG_debug_code) return;
228
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000229 int jump_offsets[] = {-9710, -77, 0, +3, +97109};
230 TRACED_FOREACH(int, jump_offset, jump_offsets) {
231 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
232 InterpreterAssemblerForTest m(this, bytecode);
233 m.Jump(m.Int32Constant(jump_offset));
234 Graph* graph = m.graph();
235 Node* end = graph->end();
236 EXPECT_EQ(1, end->InputCount());
237 Node* tail_call_node = end->InputAt(0);
238
Ben Murdoch097c5b22016-05-18 11:27:45 +0100239 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
240 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
241 IsInt32Constant(jump_offset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242 Matcher<Node*> target_bytecode_matcher =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100243 m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
244 Matcher<Node*> code_target_matcher = m.IsLoad(
245 MachineType::Pointer(),
246 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
247 IsWord32Shl(target_bytecode_matcher,
248 IsInt32Constant(kPointerSizeLog2)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000249
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000250 EXPECT_THAT(
251 tail_call_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100252 IsTailCall(
253 _, code_target_matcher,
254 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
255 IsParameter(
256 InterpreterDispatchDescriptor::kRegisterFileParameter),
257 next_bytecode_offset_matcher, _,
258 IsParameter(
259 InterpreterDispatchDescriptor::kDispatchTableParameter),
260 IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
261 _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 }
263 }
264}
265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
267 static const int kJumpIfTrueOffset = 73;
268
Ben Murdoch097c5b22016-05-18 11:27:45 +0100269 // If debug code is enabled we emit extra code in Jump.
270 if (FLAG_debug_code) return;
271
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 MachineOperatorBuilder machine(zone());
273
274 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
275 InterpreterAssemblerForTest m(this, bytecode);
276 Node* lhs = m.IntPtrConstant(0);
277 Node* rhs = m.IntPtrConstant(1);
278 m.JumpIfWordEqual(lhs, rhs, m.Int32Constant(kJumpIfTrueOffset));
279 Graph* graph = m.graph();
280 Node* end = graph->end();
281 EXPECT_EQ(2, end->InputCount());
282
283 int jump_offsets[] = {kJumpIfTrueOffset,
284 interpreter::Bytecodes::Size(bytecode)};
285 for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100286 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd(
287 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
288 IsInt32Constant(jump_offsets[i]));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 Matcher<Node*> target_bytecode_matcher =
Ben Murdoch097c5b22016-05-18 11:27:45 +0100290 m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
291 Matcher<Node*> code_target_matcher = m.IsLoad(
292 MachineType::Pointer(),
293 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
294 IsWord32Shl(target_bytecode_matcher,
295 IsInt32Constant(kPointerSizeLog2)));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000296 EXPECT_THAT(
297 end->InputAt(i),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100298 IsTailCall(
299 _, code_target_matcher,
300 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
301 IsParameter(
302 InterpreterDispatchDescriptor::kRegisterFileParameter),
303 next_bytecode_offset_matcher, _,
304 IsParameter(
305 InterpreterDispatchDescriptor::kDispatchTableParameter),
306 IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
307 _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000308 }
309
310 // TODO(oth): test control flow paths.
311 }
312}
313
Ben Murdoch097c5b22016-05-18 11:27:45 +0100314TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) {
315 // If debug code is enabled we emit extra code in InterpreterReturn.
316 if (FLAG_debug_code) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
319 InterpreterAssemblerForTest m(this, bytecode);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100320 m.InterpreterReturn();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000321 Graph* graph = m.graph();
322
323 Node* end = graph->end();
324 EXPECT_EQ(1, end->InputCount());
325 Node* tail_call_node = end->InputAt(0);
326
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 Handle<HeapObject> exit_trampoline =
328 isolate()->builtins()->InterpreterExitTrampoline();
329 EXPECT_THAT(
330 tail_call_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100331 IsTailCall(
332 _, IsHeapConstant(exit_trampoline),
333 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
334 IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
335 IsParameter(
336 InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
337 _,
338 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
339 IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
340 _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000341 }
342}
343
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000344TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
345 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
346 InterpreterAssemblerForTest m(this, bytecode);
347 int number_of_operands = interpreter::Bytecodes::NumberOfOperands(bytecode);
348 for (int i = 0; i < number_of_operands; i++) {
349 int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i);
350 switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351 case interpreter::OperandType::kRegCount8:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 EXPECT_THAT(m.BytecodeOperandCount(i), m.IsBytecodeOperand(offset));
353 break;
354 case interpreter::OperandType::kIdx8:
355 EXPECT_THAT(m.BytecodeOperandIdx(i), m.IsBytecodeOperand(offset));
356 break;
357 case interpreter::OperandType::kImm8:
358 EXPECT_THAT(m.BytecodeOperandImm(i),
359 m.IsBytecodeOperandSignExtended(offset));
360 break;
361 case interpreter::OperandType::kMaybeReg8:
362 case interpreter::OperandType::kReg8:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100363 case interpreter::OperandType::kRegOut8:
364 case interpreter::OperandType::kRegOutPair8:
365 case interpreter::OperandType::kRegOutTriple8:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 case interpreter::OperandType::kRegPair8:
367 EXPECT_THAT(m.BytecodeOperandReg(i),
368 m.IsBytecodeOperandSignExtended(offset));
369 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100370 case interpreter::OperandType::kRegCount16:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 EXPECT_THAT(m.BytecodeOperandCount(i),
372 m.IsBytecodeOperandShort(offset));
373 break;
374 case interpreter::OperandType::kIdx16:
375 EXPECT_THAT(m.BytecodeOperandIdx(i),
376 m.IsBytecodeOperandShort(offset));
377 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100378 case interpreter::OperandType::kMaybeReg16:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000379 case interpreter::OperandType::kReg16:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100380 case interpreter::OperandType::kRegOut16:
381 case interpreter::OperandType::kRegOutPair16:
382 case interpreter::OperandType::kRegOutTriple16:
383 case interpreter::OperandType::kRegPair16:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000384 EXPECT_THAT(m.BytecodeOperandReg(i),
385 m.IsBytecodeOperandShortSignExtended(offset));
386 break;
387 case interpreter::OperandType::kNone:
388 UNREACHABLE();
389 break;
390 }
391 }
392 }
393}
394
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000395TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
396 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
397 InterpreterAssemblerForTest m(this, bytecode);
398 // Should be incoming accumulator if not set.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100399 EXPECT_THAT(
400 m.GetAccumulator(),
401 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000402
Ben Murdoch097c5b22016-05-18 11:27:45 +0100403 // Should be set by SetAccumulator.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000404 Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef);
405 m.SetAccumulator(accumulator_value_1);
406 EXPECT_THAT(m.GetAccumulator(), accumulator_value_1);
407 Node* accumulator_value_2 = m.Int32Constant(42);
408 m.SetAccumulator(accumulator_value_2);
409 EXPECT_THAT(m.GetAccumulator(), accumulator_value_2);
410
411 // Should be passed to next bytecode handler on dispatch.
412 m.Dispatch();
413 Graph* graph = m.graph();
414
415 Node* end = graph->end();
416 EXPECT_EQ(1, end->InputCount());
417 Node* tail_call_node = end->InputAt(0);
418
419 EXPECT_THAT(tail_call_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100420 IsTailCall(_, _, accumulator_value_2, _, _, _, _, _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000421 }
422}
423
Ben Murdoch097c5b22016-05-18 11:27:45 +0100424TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
425 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
426 InterpreterAssemblerForTest m(this, bytecode);
427 Node* context_node = m.Int32Constant(100);
428 m.SetContext(context_node);
429 EXPECT_THAT(m.GetContext(), context_node);
430 }
431}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000432
433TARGET_TEST_F(InterpreterAssemblerTest, RegisterLocation) {
434 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
435 InterpreterAssemblerForTest m(this, bytecode);
436 Node* reg_index_node = m.Int32Constant(44);
437 Node* reg_location_node = m.RegisterLocation(reg_index_node);
438 EXPECT_THAT(
439 reg_location_node,
440 IsIntPtrAdd(
Ben Murdoch097c5b22016-05-18 11:27:45 +0100441 IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442 IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
443 }
444}
445
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000446TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
447 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
448 InterpreterAssemblerForTest m(this, bytecode);
449 Node* reg_index_node = m.Int32Constant(44);
450 Node* load_reg_node = m.LoadRegister(reg_index_node);
451 EXPECT_THAT(
452 load_reg_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100453 m.IsLoad(
454 MachineType::AnyTagged(),
455 IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
456 IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457 }
458}
459
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
461 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
462 InterpreterAssemblerForTest m(this, bytecode);
463 Node* store_value = m.Int32Constant(0xdeadbeef);
464 Node* reg_index_node = m.Int32Constant(44);
465 Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
466 EXPECT_THAT(
467 store_reg_node,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100468 m.IsStore(
469 StoreRepresentation(MachineRepresentation::kTagged,
470 kNoWriteBarrier),
471 IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
472 IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
473 store_value));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474 }
475}
476
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000477TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
478 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
479 InterpreterAssemblerForTest m(this, bytecode);
480 Node* value = m.Int32Constant(44);
481 EXPECT_THAT(m.SmiTag(value),
482 IsWordShl(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
483 EXPECT_THAT(m.SmiUntag(value),
484 IsWordSar(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
485 }
486}
487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488TARGET_TEST_F(InterpreterAssemblerTest, IntPtrAdd) {
489 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
490 InterpreterAssemblerForTest m(this, bytecode);
491 Node* a = m.Int32Constant(0);
492 Node* b = m.Int32Constant(1);
493 Node* add = m.IntPtrAdd(a, b);
494 EXPECT_THAT(add, IsIntPtrAdd(a, b));
495 }
496}
497
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000498TARGET_TEST_F(InterpreterAssemblerTest, IntPtrSub) {
499 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
500 InterpreterAssemblerForTest m(this, bytecode);
501 Node* a = m.Int32Constant(0);
502 Node* b = m.Int32Constant(1);
503 Node* add = m.IntPtrSub(a, b);
504 EXPECT_THAT(add, IsIntPtrSub(a, b));
505 }
506}
507
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508TARGET_TEST_F(InterpreterAssemblerTest, WordShl) {
509 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
510 InterpreterAssemblerForTest m(this, bytecode);
511 Node* a = m.Int32Constant(0);
512 Node* add = m.WordShl(a, 10);
513 EXPECT_THAT(add, IsWordShl(a, IsInt32Constant(10)));
514 }
515}
516
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000517TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
518 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
519 InterpreterAssemblerForTest m(this, bytecode);
520 Node* index = m.Int32Constant(2);
521 Node* load_constant = m.LoadConstantPoolEntry(index);
522 Matcher<Node*> constant_pool_matcher = m.IsLoad(
523 MachineType::AnyTagged(),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100524 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 IsIntPtrConstant(BytecodeArray::kConstantPoolOffset - kHeapObjectTag));
526 EXPECT_THAT(
527 load_constant,
528 m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
529 IsIntPtrAdd(
530 IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
531 IsWordShl(index, IsInt32Constant(kPointerSizeLog2)))));
532 }
533}
534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000535TARGET_TEST_F(InterpreterAssemblerTest, LoadFixedArrayElement) {
536 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
537 InterpreterAssemblerForTest m(this, bytecode);
538 int index = 3;
539 Node* fixed_array = m.IntPtrConstant(0xdeadbeef);
540 Node* load_element = m.LoadFixedArrayElement(fixed_array, index);
541 EXPECT_THAT(
542 load_element,
543 m.IsLoad(MachineType::AnyTagged(), fixed_array,
544 IsIntPtrAdd(
545 IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
546 IsWordShl(IsInt32Constant(index),
547 IsInt32Constant(kPointerSizeLog2)))));
548 }
549}
550
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000551TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
552 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
553 InterpreterAssemblerForTest m(this, bytecode);
554 Node* object = m.IntPtrConstant(0xdeadbeef);
555 int offset = 16;
556 Node* load_field = m.LoadObjectField(object, offset);
557 EXPECT_THAT(load_field,
558 m.IsLoad(MachineType::AnyTagged(), object,
559 IsIntPtrConstant(offset - kHeapObjectTag)));
560 }
561}
562
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000563TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
564 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
565 InterpreterAssemblerForTest m(this, bytecode);
566 Node* context = m.Int32Constant(1);
567 Node* slot_index = m.Int32Constant(22);
568 Node* load_context_slot = m.LoadContextSlot(context, slot_index);
569
570 Matcher<Node*> offset =
571 IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
572 IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
573 EXPECT_THAT(load_context_slot,
574 m.IsLoad(MachineType::AnyTagged(), context, offset));
575 }
576}
577
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000578TARGET_TEST_F(InterpreterAssemblerTest, StoreContextSlot) {
579 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
580 InterpreterAssemblerForTest m(this, bytecode);
581 Node* context = m.Int32Constant(1);
582 Node* slot_index = m.Int32Constant(22);
583 Node* value = m.Int32Constant(100);
584 Node* store_context_slot = m.StoreContextSlot(context, slot_index, value);
585
586 Matcher<Node*> offset =
587 IsIntPtrAdd(IsWordShl(slot_index, IsInt32Constant(kPointerSizeLog2)),
588 IsInt32Constant(Context::kHeaderSize - kHeapObjectTag));
589 EXPECT_THAT(store_context_slot,
590 m.IsStore(StoreRepresentation(MachineRepresentation::kTagged,
591 kFullWriteBarrier),
592 context, offset, value));
593 }
594}
595
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000596TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
597 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
598 InterpreterAssemblerForTest m(this, bytecode);
599 Node* arg1 = m.Int32Constant(2);
600 Node* arg2 = m.Int32Constant(3);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100601 Node* context =
602 m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
603 Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604 EXPECT_THAT(
605 call_runtime,
606 IsCall(_, _, arg1, arg2, _, IsInt32Constant(2),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100607 IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
608 _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000609 }
610}
611
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
613 const int kResultSizes[] = {1, 2};
614 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
615 TRACED_FOREACH(int, result_size, kResultSizes) {
616 InterpreterAssemblerForTest m(this, bytecode);
617 Callable builtin = CodeFactory::InterpreterCEntry(isolate(), result_size);
618
619 Node* function_id = m.Int32Constant(0);
620 Node* first_arg = m.Int32Constant(1);
621 Node* arg_count = m.Int32Constant(2);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100622 Node* context =
623 m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000624
625 Matcher<Node*> function_table = IsExternalConstant(
626 ExternalReference::runtime_function_table_address(isolate()));
627 Matcher<Node*> function = IsIntPtrAdd(
628 function_table,
629 IsInt32Mul(function_id, IsInt32Constant(sizeof(Runtime::Function))));
630 Matcher<Node*> function_entry =
631 m.IsLoad(MachineType::Pointer(), function,
632 IsInt32Constant(offsetof(Runtime::Function, entry)));
633
Ben Murdoch097c5b22016-05-18 11:27:45 +0100634 Node* call_runtime = m.CallRuntimeN(function_id, context, first_arg,
635 arg_count, result_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000636 EXPECT_THAT(
637 call_runtime,
638 IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
639 function_entry,
Ben Murdoch097c5b22016-05-18 11:27:45 +0100640 IsParameter(InterpreterDispatchDescriptor::kContextParameter),
641 _, _));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642 }
643 }
644}
645
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000646TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100647 TailCallMode tail_call_modes[] = {TailCallMode::kDisallow,
648 TailCallMode::kAllow};
649 TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
650 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
651 InterpreterAssemblerForTest m(this, bytecode);
652 Callable builtin =
653 CodeFactory::InterpreterPushArgsAndCall(isolate(), tail_call_mode);
654 Node* function = m.Int32Constant(0);
655 Node* first_arg = m.Int32Constant(1);
656 Node* arg_count = m.Int32Constant(2);
657 Node* context =
658 m.Parameter(InterpreterDispatchDescriptor::kContextParameter);
659 Node* call_js =
660 m.CallJS(function, context, first_arg, arg_count, tail_call_mode);
661 EXPECT_THAT(
662 call_js,
663 IsCall(_, IsHeapConstant(builtin.code()), arg_count, first_arg,
664 function,
665 IsParameter(InterpreterDispatchDescriptor::kContextParameter),
666 _, _));
667 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 }
669}
670
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000671TARGET_TEST_F(InterpreterAssemblerTest, LoadTypeFeedbackVector) {
672 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
673 InterpreterAssemblerForTest m(this, bytecode);
674 Node* feedback_vector = m.LoadTypeFeedbackVector();
675
Ben Murdoch097c5b22016-05-18 11:27:45 +0100676 Matcher<Node*> load_function_matcher = m.IsLoad(
677 MachineType::AnyTagged(),
678 IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
679 IsIntPtrConstant(
680 InterpreterFrameConstants::kFunctionFromRegisterPointer));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000681 Matcher<Node*> load_shared_function_info_matcher =
682 m.IsLoad(MachineType::AnyTagged(), load_function_matcher,
683 IsIntPtrConstant(JSFunction::kSharedFunctionInfoOffset -
684 kHeapObjectTag));
685
686 EXPECT_THAT(
687 feedback_vector,
688 m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher,
689 IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset -
690 kHeapObjectTag)));
691 }
692}
693
Ben Murdoch097c5b22016-05-18 11:27:45 +0100694} // namespace interpreter
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000695} // namespace internal
696} // namespace v8