OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "test/unittests/interpreter/interpreter-assembler-unittest.h" | 5 #include "test/unittests/interpreter/interpreter-assembler-unittest.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/compiler/graph.h" | 8 #include "src/compiler/graph.h" |
9 #include "src/compiler/node.h" | 9 #include "src/compiler/node.h" |
10 #include "src/interface-descriptors.h" | 10 #include "src/interface-descriptors.h" |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 return IsUnsignedQuadOperand(offset); | 306 return IsUnsignedQuadOperand(offset); |
307 case OperandSize::kNone: | 307 case OperandSize::kNone: |
308 UNREACHABLE(); | 308 UNREACHABLE(); |
309 } | 309 } |
310 return nullptr; | 310 return nullptr; |
311 } | 311 } |
312 | 312 |
313 TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) { | 313 TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) { |
314 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { | 314 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
315 InterpreterAssemblerForTest m(this, bytecode); | 315 InterpreterAssemblerForTest m(this, bytecode); |
316 m.Dispatch(); | 316 Node* tail_call_node = m.Dispatch(); |
317 Graph* graph = m.graph(); | |
318 | |
319 Node* end = graph->end(); | |
320 EXPECT_EQ(1, end->InputCount()); | |
321 Node* tail_call_node = end->InputAt(0); | |
322 | 317 |
323 OperandScale operand_scale = OperandScale::kSingle; | 318 OperandScale operand_scale = OperandScale::kSingle; |
324 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd( | 319 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd( |
325 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter), | 320 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter), |
326 IsIntPtrConstant( | 321 IsIntPtrConstant( |
327 interpreter::Bytecodes::Size(bytecode, operand_scale))); | 322 interpreter::Bytecodes::Size(bytecode, operand_scale))); |
328 Matcher<Node*> target_bytecode_matcher = m.IsLoad( | 323 Matcher<Node*> target_bytecode_matcher = m.IsLoad( |
329 MachineType::Uint8(), | 324 MachineType::Uint8(), |
330 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter), | 325 IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter), |
331 next_bytecode_offset_matcher); | 326 next_bytecode_offset_matcher); |
(...skipping 18 matching lines...) Expand all Loading... |
350 } | 345 } |
351 | 346 |
352 TARGET_TEST_F(InterpreterAssemblerTest, Jump) { | 347 TARGET_TEST_F(InterpreterAssemblerTest, Jump) { |
353 // If debug code is enabled we emit extra code in Jump. | 348 // If debug code is enabled we emit extra code in Jump. |
354 if (FLAG_debug_code) return; | 349 if (FLAG_debug_code) return; |
355 | 350 |
356 int jump_offsets[] = {-9710, -77, 0, +3, +97109}; | 351 int jump_offsets[] = {-9710, -77, 0, +3, +97109}; |
357 TRACED_FOREACH(int, jump_offset, jump_offsets) { | 352 TRACED_FOREACH(int, jump_offset, jump_offsets) { |
358 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { | 353 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
359 InterpreterAssemblerForTest m(this, bytecode); | 354 InterpreterAssemblerForTest m(this, bytecode); |
360 m.Jump(m.IntPtrConstant(jump_offset)); | 355 Node* tail_call_node = m.Jump(m.IntPtrConstant(jump_offset)); |
361 Graph* graph = m.graph(); | |
362 Node* end = graph->end(); | |
363 EXPECT_EQ(1, end->InputCount()); | |
364 Node* tail_call_node = end->InputAt(0); | |
365 | 356 |
366 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd( | 357 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd( |
367 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter), | 358 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter), |
368 IsIntPtrConstant(jump_offset)); | 359 IsIntPtrConstant(jump_offset)); |
369 Matcher<Node*> target_bytecode_matcher = | 360 Matcher<Node*> target_bytecode_matcher = |
370 m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher); | 361 m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher); |
371 if (kPointerSize == 8) { | 362 if (kPointerSize == 8) { |
372 target_bytecode_matcher = | 363 target_bytecode_matcher = |
373 IsChangeUint32ToUint64(target_bytecode_matcher); | 364 IsChangeUint32ToUint64(target_bytecode_matcher); |
374 } | 365 } |
375 Matcher<Node*> code_target_matcher = m.IsLoad( | 366 Matcher<Node*> code_target_matcher = m.IsLoad( |
376 MachineType::Pointer(), | 367 MachineType::Pointer(), |
377 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter), | 368 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter), |
378 IsWordShl(target_bytecode_matcher, | 369 IsWordShl(target_bytecode_matcher, |
379 IsIntPtrConstant(kPointerSizeLog2))); | 370 IsIntPtrConstant(kPointerSizeLog2))); |
380 | 371 |
381 EXPECT_THAT( | 372 EXPECT_THAT( |
382 tail_call_node, | 373 tail_call_node, |
383 IsTailCall( | 374 IsTailCall( |
384 _, code_target_matcher, | 375 _, code_target_matcher, |
385 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter), | 376 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter), |
386 next_bytecode_offset_matcher, _, | 377 next_bytecode_offset_matcher, _, |
387 IsParameter( | 378 IsParameter( |
388 InterpreterDispatchDescriptor::kDispatchTableParameter), | 379 InterpreterDispatchDescriptor::kDispatchTableParameter), |
389 _, _)); | 380 _, _)); |
390 } | 381 } |
391 } | 382 } |
392 } | 383 } |
393 | 384 |
394 TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) { | |
395 static const int kJumpIfTrueOffset = 73; | |
396 | |
397 // If debug code is enabled we emit extra code in Jump. | |
398 if (FLAG_debug_code) return; | |
399 | |
400 MachineOperatorBuilder machine(zone()); | |
401 | |
402 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { | |
403 InterpreterAssemblerForTest m(this, bytecode); | |
404 Node* lhs = m.IntPtrConstant(0); | |
405 Node* rhs = m.IntPtrConstant(1); | |
406 m.JumpIfWordEqual(lhs, rhs, m.IntPtrConstant(kJumpIfTrueOffset)); | |
407 Graph* graph = m.graph(); | |
408 Node* end = graph->end(); | |
409 EXPECT_EQ(2, end->InputCount()); | |
410 | |
411 OperandScale operand_scale = OperandScale::kSingle; | |
412 int jump_offsets[] = {kJumpIfTrueOffset, interpreter::Bytecodes::Size( | |
413 bytecode, operand_scale)}; | |
414 for (int i = 0; i < static_cast<int>(arraysize(jump_offsets)); i++) { | |
415 Matcher<Node*> next_bytecode_offset_matcher = IsIntPtrAdd( | |
416 IsParameter(InterpreterDispatchDescriptor::kBytecodeOffsetParameter), | |
417 IsIntPtrConstant(jump_offsets[i])); | |
418 Matcher<Node*> target_bytecode_matcher = | |
419 m.IsLoad(MachineType::Uint8(), _, next_bytecode_offset_matcher); | |
420 if (kPointerSize == 8) { | |
421 target_bytecode_matcher = | |
422 IsChangeUint32ToUint64(target_bytecode_matcher); | |
423 } | |
424 Matcher<Node*> code_target_matcher = m.IsLoad( | |
425 MachineType::Pointer(), | |
426 IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter), | |
427 IsWordShl(target_bytecode_matcher, | |
428 IsIntPtrConstant(kPointerSizeLog2))); | |
429 EXPECT_THAT( | |
430 end->InputAt(i), | |
431 IsTailCall( | |
432 _, code_target_matcher, | |
433 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter), | |
434 next_bytecode_offset_matcher, _, | |
435 IsParameter( | |
436 InterpreterDispatchDescriptor::kDispatchTableParameter), | |
437 _, _)); | |
438 } | |
439 | |
440 // TODO(oth): test control flow paths. | |
441 } | |
442 } | |
443 | |
444 TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) { | 385 TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) { |
445 // If debug code is enabled we emit extra code in InterpreterReturn. | 386 // If debug code is enabled we emit extra code in InterpreterReturn. |
446 if (FLAG_debug_code) return; | 387 if (FLAG_debug_code) return; |
447 | 388 |
448 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { | 389 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
449 InterpreterAssemblerForTest m(this, bytecode); | 390 InterpreterAssemblerForTest m(this, bytecode); |
450 m.InterpreterReturn(); | 391 Node* tail_call_node = m.InterpreterReturn(); |
451 Graph* graph = m.graph(); | |
452 | |
453 Node* end = graph->end(); | |
454 EXPECT_EQ(1, end->InputCount()); | |
455 Node* tail_call_node = end->InputAt(0); | |
456 | 392 |
457 Handle<HeapObject> exit_trampoline = | 393 Handle<HeapObject> exit_trampoline = |
458 isolate()->builtins()->InterpreterExitTrampoline(); | 394 isolate()->builtins()->InterpreterExitTrampoline(); |
459 Matcher<Node*> exit_trampoline_entry_matcher = | 395 Matcher<Node*> exit_trampoline_entry_matcher = |
460 IsIntPtrAdd(IsHeapConstant(exit_trampoline), | 396 IsIntPtrAdd(IsHeapConstant(exit_trampoline), |
461 IsIntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); | 397 IsIntPtrConstant(Code::kHeaderSize - kHeapObjectTag)); |
462 EXPECT_THAT( | 398 EXPECT_THAT( |
463 tail_call_node, | 399 tail_call_node, |
464 IsTailCall( | 400 IsTailCall( |
465 _, exit_trampoline_entry_matcher, | 401 _, exit_trampoline_entry_matcher, |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter)); | 477 IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter)); |
542 // Should be set by SetAccumulator. | 478 // Should be set by SetAccumulator. |
543 Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef); | 479 Node* accumulator_value_1 = m.Int32Constant(0xdeadbeef); |
544 m.SetAccumulator(accumulator_value_1); | 480 m.SetAccumulator(accumulator_value_1); |
545 EXPECT_THAT(m.GetAccumulator(), accumulator_value_1); | 481 EXPECT_THAT(m.GetAccumulator(), accumulator_value_1); |
546 Node* accumulator_value_2 = m.Int32Constant(42); | 482 Node* accumulator_value_2 = m.Int32Constant(42); |
547 m.SetAccumulator(accumulator_value_2); | 483 m.SetAccumulator(accumulator_value_2); |
548 EXPECT_THAT(m.GetAccumulator(), accumulator_value_2); | 484 EXPECT_THAT(m.GetAccumulator(), accumulator_value_2); |
549 | 485 |
550 // Should be passed to next bytecode handler on dispatch. | 486 // Should be passed to next bytecode handler on dispatch. |
551 m.Dispatch(); | 487 Node* tail_call_node = m.Dispatch(); |
552 Graph* graph = m.graph(); | |
553 | |
554 Node* end = graph->end(); | |
555 EXPECT_EQ(1, end->InputCount()); | |
556 Node* tail_call_node = end->InputAt(0); | |
557 | 488 |
558 EXPECT_THAT(tail_call_node, | 489 EXPECT_THAT(tail_call_node, |
559 IsTailCall(_, _, accumulator_value_2, _, _, _, _)); | 490 IsTailCall(_, _, accumulator_value_2, _, _, _, _)); |
560 } | 491 } |
561 } | 492 } |
562 | 493 |
563 TARGET_TEST_F(InterpreterAssemblerTest, GetContext) { | 494 TARGET_TEST_F(InterpreterAssemblerTest, GetContext) { |
564 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { | 495 TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
565 InterpreterAssemblerForTest m(this, bytecode); | 496 InterpreterAssemblerForTest m(this, bytecode); |
566 EXPECT_THAT( | 497 EXPECT_THAT( |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 feedback_vector, | 727 feedback_vector, |
797 m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher, | 728 m.IsLoad(MachineType::AnyTagged(), load_shared_function_info_matcher, |
798 IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset - | 729 IsIntPtrConstant(SharedFunctionInfo::kFeedbackVectorOffset - |
799 kHeapObjectTag))); | 730 kHeapObjectTag))); |
800 } | 731 } |
801 } | 732 } |
802 | 733 |
803 } // namespace interpreter | 734 } // namespace interpreter |
804 } // namespace internal | 735 } // namespace internal |
805 } // namespace v8 | 736 } // namespace v8 |
OLD | NEW |