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