Line data Source code
1 : // Copyright 2015 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "test/unittests/interpreter/interpreter-assembler-unittest.h"
6 :
7 : #include "src/code-factory.h"
8 : #include "src/compiler/node.h"
9 : #include "src/interface-descriptors.h"
10 : #include "src/isolate.h"
11 : #include "src/objects-inl.h"
12 : #include "test/unittests/compiler/compiler-test-utils.h"
13 : #include "test/unittests/compiler/node-test-utils.h"
14 :
15 : using ::testing::_;
16 : using v8::internal::compiler::Node;
17 :
18 : namespace c = v8::internal::compiler;
19 :
20 : namespace v8 {
21 : namespace internal {
22 : namespace interpreter {
23 : namespace interpreter_assembler_unittest {
24 :
25 1446 : InterpreterAssemblerTestState::InterpreterAssemblerTestState(
26 : InterpreterAssemblerTest* test, Bytecode bytecode)
27 : : compiler::CodeAssemblerState(
28 : test->isolate(), test->zone(), InterpreterDispatchDescriptor{},
29 : Code::BYTECODE_HANDLER, Bytecodes::ToString(bytecode),
30 4338 : PoisoningMitigationLevel::kPoisonCriticalOnly) {}
31 :
32 : const interpreter::Bytecode kBytecodes[] = {
33 : #define DEFINE_BYTECODE(Name, ...) interpreter::Bytecode::k##Name,
34 : BYTECODE_LIST(DEFINE_BYTECODE)
35 : #undef DEFINE_BYTECODE
36 : };
37 :
38 :
39 1446 : InterpreterAssemblerTest::InterpreterAssemblerForTest::
40 1446 : ~InterpreterAssemblerForTest() {
41 : // Tests don't necessarily read and write accumulator but
42 : // InterpreterAssembler checks accumulator uses.
43 4338 : if (Bytecodes::ReadsAccumulator(bytecode())) {
44 856 : GetAccumulator();
45 : }
46 1446 : if (Bytecodes::WritesAccumulator(bytecode())) {
47 1028 : SetAccumulator(nullptr);
48 : }
49 1446 : }
50 :
51 2868 : Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad(
52 : const Matcher<c::LoadRepresentation>& rep_matcher,
53 : const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
54 : LoadSensitivity needs_poisoning) {
55 2868 : CHECK_NE(LoadSensitivity::kUnsafe, needs_poisoning);
56 2868 : CHECK_NE(PoisoningMitigationLevel::kPoisonAll, poisoning_level());
57 2868 : if (poisoning_level() == PoisoningMitigationLevel::kPoisonCriticalOnly &&
58 : needs_poisoning == LoadSensitivity::kCritical) {
59 : return ::i::compiler::IsPoisonedLoad(rep_matcher, base_matcher,
60 3798 : index_matcher, _, _);
61 : }
62 4806 : return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, _, _);
63 : }
64 :
65 0 : Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
66 : const Matcher<c::StoreRepresentation>& rep_matcher,
67 : const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher,
68 : const Matcher<Node*>& value_matcher) {
69 : return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher,
70 0 : value_matcher, _, _);
71 : }
72 :
73 0 : Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsWordNot(
74 : const Matcher<Node*>& value_matcher) {
75 : return kSystemPointerSize == 8
76 : ? IsWord64Xor(value_matcher, c::IsInt64Constant(-1))
77 0 : : IsWord32Xor(value_matcher, c::IsInt32Constant(-1));
78 : }
79 :
80 : Matcher<Node*>
81 188 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedByteOperand(
82 : int offset, LoadSensitivity needs_poisoning) {
83 : return IsLoad(
84 : MachineType::Uint8(),
85 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
86 : c::IsIntPtrAdd(
87 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
88 : c::IsIntPtrConstant(offset)),
89 1692 : needs_poisoning);
90 : }
91 :
92 : Matcher<Node*>
93 130 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedByteOperand(
94 : int offset, LoadSensitivity needs_poisoning) {
95 : return IsLoad(
96 : MachineType::Int8(),
97 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
98 : c::IsIntPtrAdd(
99 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
100 : c::IsIntPtrConstant(offset)),
101 1170 : needs_poisoning);
102 : }
103 :
104 : Matcher<Node*>
105 170 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedShortOperand(
106 : int offset, LoadSensitivity needs_poisoning) {
107 170 : if (TargetSupportsUnalignedAccess()) {
108 : return IsLoad(
109 : MachineType::Uint16(),
110 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
111 : c::IsIntPtrAdd(
112 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
113 : c::IsIntPtrConstant(offset)),
114 1530 : needs_poisoning);
115 : } else {
116 : #if V8_TARGET_LITTLE_ENDIAN
117 : const int kStep = -1;
118 : const int kMsbOffset = 1;
119 : #elif V8_TARGET_BIG_ENDIAN
120 : const int kStep = 1;
121 : const int kMsbOffset = 0;
122 : #else
123 : #error "Unknown Architecture"
124 : #endif
125 0 : Matcher<Node*> bytes[2];
126 0 : for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
127 0 : bytes[i] = IsLoad(
128 : MachineType::Uint8(),
129 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
130 : c::IsIntPtrAdd(
131 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
132 0 : c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
133 : needs_poisoning);
134 : }
135 : return c::IsWord32Or(
136 0 : c::IsWord32Shl(bytes[0], c::IsInt32Constant(kBitsPerByte)), bytes[1]);
137 : }
138 : }
139 :
140 : Matcher<Node*>
141 130 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedShortOperand(
142 : int offset, LoadSensitivity needs_poisoning) {
143 130 : if (TargetSupportsUnalignedAccess()) {
144 : return IsLoad(
145 : MachineType::Int16(),
146 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
147 : c::IsIntPtrAdd(
148 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
149 : c::IsIntPtrConstant(offset)),
150 1170 : needs_poisoning);
151 : } else {
152 : #if V8_TARGET_LITTLE_ENDIAN
153 : const int kStep = -1;
154 : const int kMsbOffset = 1;
155 : #elif V8_TARGET_BIG_ENDIAN
156 : const int kStep = 1;
157 : const int kMsbOffset = 0;
158 : #else
159 : #error "Unknown Architecture"
160 : #endif
161 0 : Matcher<Node*> bytes[2];
162 0 : for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
163 0 : bytes[i] = IsLoad(
164 : (i == 0) ? MachineType::Int8() : MachineType::Uint8(),
165 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
166 : c::IsIntPtrAdd(
167 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
168 0 : c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
169 : needs_poisoning);
170 : }
171 : return c::IsWord32Or(
172 0 : c::IsWord32Shl(bytes[0], c::IsInt32Constant(kBitsPerByte)), bytes[1]);
173 : }
174 : }
175 :
176 : Matcher<Node*>
177 158 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedQuadOperand(
178 : int offset, LoadSensitivity needs_poisoning) {
179 158 : if (TargetSupportsUnalignedAccess()) {
180 : return IsLoad(
181 : MachineType::Uint32(),
182 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
183 : c::IsIntPtrAdd(
184 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
185 : c::IsIntPtrConstant(offset)),
186 1422 : needs_poisoning);
187 : } else {
188 : #if V8_TARGET_LITTLE_ENDIAN
189 : const int kStep = -1;
190 : const int kMsbOffset = 3;
191 : #elif V8_TARGET_BIG_ENDIAN
192 : const int kStep = 1;
193 : const int kMsbOffset = 0;
194 : #else
195 : #error "Unknown Architecture"
196 : #endif
197 0 : Matcher<Node*> bytes[4];
198 0 : for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
199 0 : bytes[i] = IsLoad(
200 : MachineType::Uint8(),
201 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
202 : c::IsIntPtrAdd(
203 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
204 0 : c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
205 : needs_poisoning);
206 : }
207 : return c::IsWord32Or(
208 : c::IsWord32Shl(bytes[0], c::IsInt32Constant(3 * kBitsPerByte)),
209 : c::IsWord32Or(
210 : c::IsWord32Shl(bytes[1], c::IsInt32Constant(2 * kBitsPerByte)),
211 : c::IsWord32Or(
212 : c::IsWord32Shl(bytes[2], c::IsInt32Constant(1 * kBitsPerByte)),
213 0 : bytes[3])));
214 : }
215 : }
216 :
217 : Matcher<Node*>
218 130 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedQuadOperand(
219 : int offset, LoadSensitivity needs_poisoning) {
220 130 : if (TargetSupportsUnalignedAccess()) {
221 : return IsLoad(
222 : MachineType::Int32(),
223 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
224 : c::IsIntPtrAdd(
225 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
226 : c::IsIntPtrConstant(offset)),
227 1170 : needs_poisoning);
228 : } else {
229 : #if V8_TARGET_LITTLE_ENDIAN
230 : const int kStep = -1;
231 : int kMsbOffset = 3;
232 : #elif V8_TARGET_BIG_ENDIAN
233 : const int kStep = 1;
234 : int kMsbOffset = 0;
235 : #else
236 : #error "Unknown Architecture"
237 : #endif
238 0 : Matcher<Node*> bytes[4];
239 0 : for (int i = 0; i < static_cast<int>(arraysize(bytes)); i++) {
240 0 : bytes[i] = IsLoad(
241 : (i == 0) ? MachineType::Int8() : MachineType::Uint8(),
242 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
243 : c::IsIntPtrAdd(
244 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
245 0 : c::IsIntPtrConstant(offset + kMsbOffset + kStep * i)),
246 : needs_poisoning);
247 : }
248 : return c::IsWord32Or(
249 : c::IsWord32Shl(bytes[0], c::IsInt32Constant(3 * kBitsPerByte)),
250 : c::IsWord32Or(
251 : c::IsWord32Shl(bytes[1], c::IsInt32Constant(2 * kBitsPerByte)),
252 : c::IsWord32Or(
253 : c::IsWord32Shl(bytes[2], c::IsInt32Constant(1 * kBitsPerByte)),
254 0 : bytes[3])));
255 : }
256 : }
257 :
258 : Matcher<Node*>
259 390 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsSignedOperand(
260 : int offset, OperandSize operand_size, LoadSensitivity needs_poisoning) {
261 390 : switch (operand_size) {
262 : case OperandSize::kByte:
263 130 : return IsSignedByteOperand(offset, needs_poisoning);
264 : case OperandSize::kShort:
265 130 : return IsSignedShortOperand(offset, needs_poisoning);
266 : case OperandSize::kQuad:
267 130 : return IsSignedQuadOperand(offset, needs_poisoning);
268 : case OperandSize::kNone:
269 0 : UNREACHABLE();
270 : }
271 0 : return nullptr;
272 : }
273 :
274 : Matcher<Node*>
275 516 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsUnsignedOperand(
276 : int offset, OperandSize operand_size, LoadSensitivity needs_poisoning) {
277 516 : switch (operand_size) {
278 : case OperandSize::kByte:
279 188 : return IsUnsignedByteOperand(offset, needs_poisoning);
280 : case OperandSize::kShort:
281 170 : return IsUnsignedShortOperand(offset, needs_poisoning);
282 : case OperandSize::kQuad:
283 158 : return IsUnsignedQuadOperand(offset, needs_poisoning);
284 : case OperandSize::kNone:
285 0 : UNREACHABLE();
286 : }
287 0 : return nullptr;
288 : }
289 :
290 : Matcher<compiler::Node*>
291 336 : InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoadRegisterOperand(
292 : int offset, OperandSize operand_size) {
293 : Matcher<compiler::Node*> reg_operand = IsChangeInt32ToIntPtr(
294 672 : IsSignedOperand(offset, operand_size, LoadSensitivity::kSafe));
295 : return IsBitcastWordToTagged(IsLoad(
296 : MachineType::Pointer(), c::IsLoadParentFramePointer(),
297 : c::IsWordShl(reg_operand, c::IsIntPtrConstant(kSystemPointerSizeLog2)),
298 2688 : LoadSensitivity::kCritical));
299 : }
300 :
301 15189 : TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
302 : // If debug code is enabled we emit extra code in Jump.
303 2 : if (FLAG_debug_code) return;
304 :
305 1 : int jump_offsets[] = {-9710, -77, 0, +3, +97109};
306 5 : TRACED_FOREACH(int, jump_offset, jump_offsets) {
307 5 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
308 3 : if (!interpreter::Bytecodes::IsJump(bytecode)) return;
309 :
310 0 : InterpreterAssemblerTestState state(this, bytecode);
311 0 : InterpreterAssemblerForTest m(&state, bytecode);
312 0 : Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset));
313 :
314 : Matcher<Node*> next_bytecode_offset_matcher = c::IsIntPtrAdd(
315 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeOffset),
316 0 : c::IsIntPtrConstant(jump_offset));
317 : Matcher<Node*> target_bytecode_matcher =
318 0 : m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher);
319 0 : target_bytecode_matcher =
320 : c::IsChangeUint32ToWord(target_bytecode_matcher);
321 : Matcher<Node*> code_target_matcher = m.IsLoad(
322 : MachineType::Pointer(),
323 : c::IsParameter(InterpreterDispatchDescriptor::kDispatchTable),
324 : c::IsWordShl(target_bytecode_matcher,
325 0 : c::IsIntPtrConstant(kSystemPointerSizeLog2)));
326 :
327 0 : EXPECT_THAT(
328 : tail_call_node,
329 : c::IsTailCall(
330 : _, code_target_matcher,
331 : c::IsParameter(InterpreterDispatchDescriptor::kAccumulator),
332 : next_bytecode_offset_matcher, _,
333 : c::IsParameter(InterpreterDispatchDescriptor::kDispatchTable), _,
334 0 : _));
335 0 : }
336 0 : }
337 : }
338 :
339 15189 : TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
340 : static const OperandScale kOperandScales[] = {
341 : OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};
342 1081 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
343 3780 : TRACED_FOREACH(interpreter::OperandScale, operand_scale, kOperandScales) {
344 540 : InterpreterAssemblerTestState state(this, bytecode);
345 1080 : InterpreterAssemblerForTest m(&state, bytecode, operand_scale);
346 : int number_of_operands =
347 540 : interpreter::Bytecodes::NumberOfOperands(bytecode);
348 1446 : for (int i = 0; i < number_of_operands; i++) {
349 : int offset = interpreter::Bytecodes::GetOperandOffset(bytecode, i,
350 906 : operand_scale);
351 : OperandType operand_type =
352 906 : interpreter::Bytecodes::GetOperandType(bytecode, i);
353 : OperandSize operand_size =
354 906 : Bytecodes::SizeOfOperand(operand_type, operand_scale);
355 906 : switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
356 : case interpreter::OperandType::kRegCount:
357 156 : EXPECT_THAT(m.BytecodeOperandCount(i),
358 : m.IsUnsignedOperand(offset, operand_size,
359 0 : LoadSensitivity::kCritical));
360 39 : break;
361 : case interpreter::OperandType::kFlag8:
362 108 : EXPECT_THAT(m.BytecodeOperandFlag(i),
363 : m.IsUnsignedOperand(offset, operand_size,
364 0 : LoadSensitivity::kCritical));
365 27 : break;
366 : case interpreter::OperandType::kIdx:
367 1785 : EXPECT_THAT(m.BytecodeOperandIdx(i),
368 : c::IsChangeUint32ToWord(m.IsUnsignedOperand(
369 0 : offset, operand_size, LoadSensitivity::kCritical)));
370 357 : break;
371 : case interpreter::OperandType::kNativeContextIndex:
372 15 : EXPECT_THAT(m.BytecodeOperandNativeContextIndex(i),
373 : c::IsChangeUint32ToWord(m.IsUnsignedOperand(
374 0 : offset, operand_size, LoadSensitivity::kCritical)));
375 3 : break;
376 : case interpreter::OperandType::kUImm:
377 300 : EXPECT_THAT(m.BytecodeOperandUImm(i),
378 : m.IsUnsignedOperand(offset, operand_size,
379 0 : LoadSensitivity::kCritical));
380 75 : break;
381 : case interpreter::OperandType::kImm: {
382 216 : EXPECT_THAT(m.BytecodeOperandImm(i),
383 : m.IsSignedOperand(offset, operand_size,
384 0 : LoadSensitivity::kCritical));
385 54 : break;
386 : }
387 : case interpreter::OperandType::kRuntimeId:
388 48 : EXPECT_THAT(m.BytecodeOperandRuntimeId(i),
389 : m.IsUnsignedOperand(offset, operand_size,
390 0 : LoadSensitivity::kCritical));
391 12 : break;
392 : case interpreter::OperandType::kIntrinsicId:
393 12 : EXPECT_THAT(m.BytecodeOperandIntrinsicId(i),
394 : m.IsUnsignedOperand(offset, operand_size,
395 0 : LoadSensitivity::kCritical));
396 3 : break;
397 : case interpreter::OperandType::kRegList:
398 : case interpreter::OperandType::kReg:
399 : case interpreter::OperandType::kRegPair:
400 : case interpreter::OperandType::kRegOut:
401 : case interpreter::OperandType::kRegOutList:
402 : case interpreter::OperandType::kRegOutPair:
403 : case interpreter::OperandType::kRegOutTriple:
404 1344 : EXPECT_THAT(m.LoadRegisterAtOperandIndex(i),
405 0 : m.IsLoadRegisterOperand(offset, operand_size));
406 336 : break;
407 : case interpreter::OperandType::kNone:
408 0 : UNREACHABLE();
409 : break;
410 : }
411 : }
412 540 : }
413 180 : }
414 1 : }
415 :
416 15189 : TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
417 1081 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
418 180 : InterpreterAssemblerTestState state(this, bytecode);
419 360 : InterpreterAssemblerForTest m(&state, bytecode);
420 1620 : EXPECT_THAT(
421 : m.GetContext(),
422 : IsBitcastWordToTagged(m.IsLoad(
423 : MachineType::Pointer(), c::IsLoadParentFramePointer(),
424 : c::IsIntPtrConstant(Register::current_context().ToOperand() *
425 0 : kSystemPointerSize))));
426 180 : }
427 1 : }
428 :
429 15189 : TARGET_TEST_F(InterpreterAssemblerTest, LoadConstantPoolEntry) {
430 1081 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
431 180 : InterpreterAssemblerTestState state(this, bytecode);
432 360 : InterpreterAssemblerForTest m(&state, bytecode);
433 : {
434 360 : Node* index = m.IntPtrConstant(2);
435 180 : Node* load_constant = m.LoadConstantPoolEntry(index);
436 : Matcher<Node*> constant_pool_matcher = m.IsLoad(
437 : MachineType::AnyTagged(),
438 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
439 : c::IsIntPtrConstant(BytecodeArray::kConstantPoolOffset -
440 900 : kHeapObjectTag));
441 1080 : EXPECT_THAT(
442 : load_constant,
443 : m.IsLoad(MachineType::AnyTagged(), constant_pool_matcher,
444 : c::IsIntPtrConstant(FixedArray::OffsetOfElementAt(2) -
445 : kHeapObjectTag),
446 0 : LoadSensitivity::kCritical));
447 : }
448 : {
449 180 : Node* index = m.Parameter(2);
450 180 : Node* load_constant = m.LoadConstantPoolEntry(index);
451 : Matcher<Node*> constant_pool_matcher = m.IsLoad(
452 : MachineType::AnyTagged(),
453 : c::IsParameter(InterpreterDispatchDescriptor::kBytecodeArray),
454 : c::IsIntPtrConstant(BytecodeArray::kConstantPoolOffset -
455 900 : kHeapObjectTag));
456 2160 : EXPECT_THAT(
457 : load_constant,
458 : m.IsLoad(
459 : MachineType::AnyTagged(), constant_pool_matcher,
460 : c::IsIntPtrAdd(
461 : c::IsIntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
462 : c::IsWordShl(index,
463 : c::IsIntPtrConstant(kSystemPointerSizeLog2))),
464 0 : LoadSensitivity::kCritical));
465 : }
466 180 : }
467 1 : }
468 :
469 15189 : TARGET_TEST_F(InterpreterAssemblerTest, LoadObjectField) {
470 1081 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
471 180 : InterpreterAssemblerTestState state(this, bytecode);
472 360 : InterpreterAssemblerForTest m(&state, bytecode);
473 360 : Node* object = m.IntPtrConstant(0xDEADBEEF);
474 : int offset = 16;
475 180 : Node* load_field = m.LoadObjectField(object, offset);
476 1260 : EXPECT_THAT(load_field,
477 : m.IsLoad(MachineType::AnyTagged(), object,
478 0 : c::IsIntPtrConstant(offset - kHeapObjectTag)));
479 180 : }
480 1 : }
481 :
482 15189 : TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime2) {
483 1081 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
484 180 : InterpreterAssemblerTestState state(this, bytecode);
485 360 : InterpreterAssemblerForTest m(&state, bytecode);
486 360 : Node* arg1 = m.Int32Constant(2);
487 360 : Node* arg2 = m.Int32Constant(3);
488 360 : Node* context = m.Int32Constant(4);
489 180 : Node* call_runtime = m.CallRuntime(Runtime::kAdd, context, arg1, arg2);
490 2880 : EXPECT_THAT(call_runtime, c::IsCall(_, _, arg1, arg2, _,
491 0 : c::IsInt32Constant(2), context, _, _));
492 180 : }
493 1 : }
494 :
495 15189 : TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
496 1 : const int kResultSizes[] = {1, 2};
497 1081 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
498 2520 : TRACED_FOREACH(int, result_size, kResultSizes) {
499 720 : if (Bytecodes::IsCallRuntime(bytecode)) {
500 6 : InterpreterAssemblerTestState state(this, bytecode);
501 12 : InterpreterAssemblerForTest m(&state, bytecode);
502 : Callable builtin =
503 6 : CodeFactory::InterpreterCEntry(isolate(), result_size);
504 :
505 12 : Node* function_id = m.Int32Constant(0);
506 : InterpreterAssembler::RegListNodePair registers(m.IntPtrConstant(1),
507 18 : m.Int32Constant(2));
508 12 : Node* context = m.IntPtrConstant(4);
509 :
510 : Matcher<Node*> function_table = c::IsExternalConstant(
511 : ExternalReference::runtime_function_table_address_for_unittests(
512 12 : isolate()));
513 : Matcher<Node*> function = c::IsIntPtrAdd(
514 : function_table,
515 : c::IsChangeUint32ToWord(c::IsInt32Mul(
516 36 : function_id, c::IsInt32Constant(sizeof(Runtime::Function)))));
517 : Matcher<Node*> function_entry =
518 : m.IsLoad(MachineType::Pointer(), function,
519 18 : c::IsIntPtrConstant(offsetof(Runtime::Function, entry)));
520 :
521 : Node* call_runtime =
522 6 : m.CallRuntimeN(function_id, context, registers, result_size);
523 78 : EXPECT_THAT(
524 : call_runtime,
525 : c::IsCall(_, c::IsHeapConstant(builtin.code()),
526 : registers.reg_count(), registers.base_reg_location(),
527 0 : function_entry, context, _, _));
528 : }
529 360 : }
530 180 : }
531 1 : }
532 :
533 15189 : TARGET_TEST_F(InterpreterAssemblerTest, LoadFeedbackVector) {
534 1081 : TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
535 180 : InterpreterAssemblerTestState state(this, bytecode);
536 360 : InterpreterAssemblerForTest m(&state, bytecode);
537 360 : Node* feedback_vector = m.LoadFeedbackVector();
538 :
539 : Matcher<Node*> load_function_matcher = IsBitcastWordToTagged(
540 : m.IsLoad(MachineType::Pointer(), c::IsLoadParentFramePointer(),
541 540 : c::IsIntPtrConstant(Register::function_closure().ToOperand() *
542 900 : kSystemPointerSize)));
543 : Matcher<Node*> load_vector_cell_matcher = m.IsLoad(
544 : MachineType::AnyTagged(), load_function_matcher,
545 540 : c::IsIntPtrConstant(JSFunction::kFeedbackCellOffset - kHeapObjectTag));
546 1080 : EXPECT_THAT(
547 : feedback_vector,
548 : m.IsLoad(MachineType::AnyTagged(), load_vector_cell_matcher,
549 0 : c::IsIntPtrConstant(Cell::kValueOffset - kHeapObjectTag)));
550 180 : }
551 1 : }
552 :
553 : } // namespace interpreter_assembler_unittest
554 : } // namespace interpreter
555 : } // namespace internal
556 9111 : } // namespace v8
|