OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/compiler/instruction-selector-unittest.h" | 5 #include "test/unittests/compiler/instruction-selector-unittest.h" |
6 | 6 |
7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
8 #include "src/compiler/schedule.h" | 8 #include "src/compiler/schedule.h" |
9 #include "src/flags.h" | 9 #include "src/flags.h" |
10 #include "test/unittests/compiler/compiler-test-utils.h" | 10 #include "test/unittests/compiler/compiler-test-utils.h" |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 | 355 |
356 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); | 356 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); |
357 ZoneVector<MachineType> empty_types(zone()); | 357 ZoneVector<MachineType> empty_types(zone()); |
358 | 358 |
359 Node* parameters = | 359 Node* parameters = |
360 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(1)); | 360 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(1)); |
361 Node* locals = m.NewNode(m.common()->TypedStateValues(&empty_types)); | 361 Node* locals = m.NewNode(m.common()->TypedStateValues(&empty_types)); |
362 Node* stack = m.NewNode(m.common()->TypedStateValues(&empty_types)); | 362 Node* stack = m.NewNode(m.common()->TypedStateValues(&empty_types)); |
363 Node* context_dummy = m.Int32Constant(0); | 363 Node* context_dummy = m.Int32Constant(0); |
364 | 364 |
365 Node* state_node = m.NewNode( | 365 Node* state_node = |
366 m.common()->FrameState(JS_FRAME, bailout_id, | 366 m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id, |
367 OutputFrameStateCombine::Push()), | 367 OutputFrameStateCombine::Push()), |
368 parameters, locals, stack, context_dummy, m.UndefinedConstant()); | 368 parameters, locals, stack, context_dummy, function_node, |
| 369 m.UndefinedConstant()); |
369 Node* call = m.CallJS0(function_node, receiver, context, state_node); | 370 Node* call = m.CallJS0(function_node, receiver, context, state_node); |
370 m.Return(call); | 371 m.Return(call); |
371 | 372 |
372 Stream s = m.Build(kAllExceptNopInstructions); | 373 Stream s = m.Build(kAllExceptNopInstructions); |
373 | 374 |
374 // Skip until kArchCallJSFunction. | 375 // Skip until kArchCallJSFunction. |
375 size_t index = 0; | 376 size_t index = 0; |
376 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction; | 377 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction; |
377 index++) { | 378 index++) { |
378 } | 379 } |
(...skipping 24 matching lines...) Expand all Loading... |
403 | 404 |
404 // Build frame state for the state before the call. | 405 // Build frame state for the state before the call. |
405 Node* parameters = | 406 Node* parameters = |
406 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); | 407 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); |
407 Node* locals = m.NewNode(m.common()->TypedStateValues(&float64_type), | 408 Node* locals = m.NewNode(m.common()->TypedStateValues(&float64_type), |
408 m.Float64Constant(0.5)); | 409 m.Float64Constant(0.5)); |
409 Node* stack = m.NewNode(m.common()->TypedStateValues(&tagged_type), | 410 Node* stack = m.NewNode(m.common()->TypedStateValues(&tagged_type), |
410 m.UndefinedConstant()); | 411 m.UndefinedConstant()); |
411 | 412 |
412 Node* context_sentinel = m.Int32Constant(0); | 413 Node* context_sentinel = m.Int32Constant(0); |
413 Node* frame_state_before = m.NewNode( | 414 Node* frame_state_before = |
414 m.common()->FrameState(JS_FRAME, bailout_id_before, | 415 m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before, |
415 OutputFrameStateCombine::Push()), | 416 OutputFrameStateCombine::Push()), |
416 parameters, locals, stack, context_sentinel, m.UndefinedConstant()); | 417 parameters, locals, stack, context_sentinel, function_node, |
| 418 m.UndefinedConstant()); |
417 | 419 |
418 // Build the call. | 420 // Build the call. |
419 Node* call = m.CallFunctionStub0(function_node, receiver, context, | 421 Node* call = m.CallFunctionStub0(function_node, receiver, context, |
420 frame_state_before, CALL_AS_METHOD); | 422 frame_state_before, CALL_AS_METHOD); |
421 | 423 |
422 m.Return(call); | 424 m.Return(call); |
423 | 425 |
424 Stream s = m.Build(kAllExceptNopInstructions); | 426 Stream s = m.Build(kAllExceptNopInstructions); |
425 | 427 |
426 // Skip until kArchCallJSFunction. | 428 // Skip until kArchCallJSFunction. |
427 size_t index = 0; | 429 size_t index = 0; |
428 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; | 430 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; |
429 index++) { | 431 index++) { |
430 } | 432 } |
431 // Now we should have two instructions: call, return. | 433 // Now we should have two instructions: call, return. |
432 ASSERT_EQ(index + 2, s.size()); | 434 ASSERT_EQ(index + 2, s.size()); |
433 | 435 |
434 // Check the call instruction | 436 // Check the call instruction |
435 const Instruction* call_instr = s[index++]; | 437 const Instruction* call_instr = s[index++]; |
436 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode()); | 438 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode()); |
437 size_t num_operands = | 439 size_t num_operands = |
438 1 + // Code object. | 440 1 + // Code object. |
439 1 + | 441 1 + |
440 4 + // Frame state deopt id + one input for each value in frame state. | 442 5 + // Frame state deopt id + one input for each value in frame state. |
441 1 + // Function. | 443 1 + // Function. |
442 1; // Context. | 444 1; // Context. |
443 ASSERT_EQ(num_operands, call_instr->InputCount()); | 445 ASSERT_EQ(num_operands, call_instr->InputCount()); |
444 | 446 |
445 // Code object. | 447 // Code object. |
446 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate()); | 448 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate()); |
447 | 449 |
448 // Deoptimization id. | 450 // Deoptimization id. |
449 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1)); | 451 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1)); |
450 FrameStateDescriptor* desc_before = | 452 FrameStateDescriptor* desc_before = |
451 s.GetFrameStateDescriptor(deopt_id_before); | 453 s.GetFrameStateDescriptor(deopt_id_before); |
452 EXPECT_EQ(bailout_id_before, desc_before->bailout_id()); | 454 EXPECT_EQ(bailout_id_before, desc_before->bailout_id()); |
453 EXPECT_EQ(OutputFrameStateCombine::kPushOutput, | 455 EXPECT_EQ(OutputFrameStateCombine::kPushOutput, |
454 desc_before->state_combine().kind()); | 456 desc_before->state_combine().kind()); |
455 EXPECT_EQ(1u, desc_before->parameters_count()); | 457 EXPECT_EQ(1u, desc_before->parameters_count()); |
456 EXPECT_EQ(1u, desc_before->locals_count()); | 458 EXPECT_EQ(1u, desc_before->locals_count()); |
457 EXPECT_EQ(1u, desc_before->stack_count()); | 459 EXPECT_EQ(1u, desc_before->stack_count()); |
458 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2))); | 460 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(3))); |
459 EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(3))); // This should be a context. | 461 EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(4))); // This should be a context. |
460 // We inserted 0 here. | 462 // We inserted 0 here. |
461 EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(4))); | 463 EXPECT_EQ(0.5, s.ToFloat64(call_instr->InputAt(5))); |
462 EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(5))->IsUndefined()); | 464 EXPECT_TRUE(s.ToHeapObject(call_instr->InputAt(6))->IsUndefined()); |
463 EXPECT_EQ(kMachInt32, desc_before->GetType(0)); | 465 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); // function is always |
464 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1)); // context is always | |
465 // tagged/any. | 466 // tagged/any. |
466 EXPECT_EQ(kMachFloat64, desc_before->GetType(2)); | 467 EXPECT_EQ(kMachInt32, desc_before->GetType(1)); |
467 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(3)); | 468 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2)); // context is always |
| 469 // tagged/any. |
| 470 EXPECT_EQ(kMachFloat64, desc_before->GetType(3)); |
| 471 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(4)); |
468 | 472 |
469 // Function. | 473 // Function. |
470 EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(6))); | 474 EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(7))); |
471 // Context. | 475 // Context. |
472 EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(7))); | 476 EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(8))); |
473 | 477 |
474 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); | 478 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); |
475 | 479 |
476 EXPECT_EQ(index, s.size()); | 480 EXPECT_EQ(index, s.size()); |
477 } | 481 } |
478 | 482 |
479 | 483 |
480 TARGET_TEST_F(InstructionSelectorTest, | 484 TARGET_TEST_F(InstructionSelectorTest, |
481 CallFunctionStubDeoptRecursiveFrameState) { | 485 CallFunctionStubDeoptRecursiveFrameState) { |
482 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, | 486 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, |
(...skipping 11 matching lines...) Expand all Loading... |
494 ZoneVector<MachineType> int32x2_type(2, kMachInt32, zone()); | 498 ZoneVector<MachineType> int32x2_type(2, kMachInt32, zone()); |
495 ZoneVector<MachineType> float64_type(1, kMachFloat64, zone()); | 499 ZoneVector<MachineType> float64_type(1, kMachFloat64, zone()); |
496 | 500 |
497 // Build frame state for the state before the call. | 501 // Build frame state for the state before the call. |
498 Node* parameters = | 502 Node* parameters = |
499 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(63)); | 503 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(63)); |
500 Node* locals = | 504 Node* locals = |
501 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64)); | 505 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64)); |
502 Node* stack = | 506 Node* stack = |
503 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65)); | 507 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65)); |
504 Node* frame_state_parent = | 508 Node* frame_state_parent = m.NewNode( |
505 m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_parent, | 509 m.common()->FrameState(JS_FRAME, bailout_id_parent, |
506 OutputFrameStateCombine::Ignore()), | 510 OutputFrameStateCombine::Ignore()), |
507 parameters, locals, stack, context, m.UndefinedConstant()); | 511 parameters, locals, stack, context, function_node, m.UndefinedConstant()); |
508 | 512 |
509 Node* context2 = m.Int32Constant(46); | 513 Node* context2 = m.Int32Constant(46); |
510 Node* parameters2 = | 514 Node* parameters2 = |
511 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); | 515 m.NewNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); |
512 Node* locals2 = m.NewNode(m.common()->TypedStateValues(&float64_type), | 516 Node* locals2 = m.NewNode(m.common()->TypedStateValues(&float64_type), |
513 m.Float64Constant(0.25)); | 517 m.Float64Constant(0.25)); |
514 Node* stack2 = m.NewNode(m.common()->TypedStateValues(&int32x2_type), | 518 Node* stack2 = m.NewNode(m.common()->TypedStateValues(&int32x2_type), |
515 m.Int32Constant(44), m.Int32Constant(45)); | 519 m.Int32Constant(44), m.Int32Constant(45)); |
516 Node* frame_state_before = | 520 Node* frame_state_before = |
517 m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before, | 521 m.NewNode(m.common()->FrameState(JS_FRAME, bailout_id_before, |
518 OutputFrameStateCombine::Push()), | 522 OutputFrameStateCombine::Push()), |
519 parameters2, locals2, stack2, context2, frame_state_parent); | 523 parameters2, locals2, stack2, context2, function_node, |
| 524 frame_state_parent); |
520 | 525 |
521 // Build the call. | 526 // Build the call. |
522 Node* call = m.CallFunctionStub0(function_node, receiver, context2, | 527 Node* call = m.CallFunctionStub0(function_node, receiver, context2, |
523 frame_state_before, CALL_AS_METHOD); | 528 frame_state_before, CALL_AS_METHOD); |
524 | 529 |
525 m.Return(call); | 530 m.Return(call); |
526 | 531 |
527 Stream s = m.Build(kAllExceptNopInstructions); | 532 Stream s = m.Build(kAllExceptNopInstructions); |
528 | 533 |
529 // Skip until kArchCallJSFunction. | 534 // Skip until kArchCallJSFunction. |
530 size_t index = 0; | 535 size_t index = 0; |
531 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; | 536 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; |
532 index++) { | 537 index++) { |
533 } | 538 } |
534 // Now we should have three instructions: call, return. | 539 // Now we should have three instructions: call, return. |
535 EXPECT_EQ(index + 2, s.size()); | 540 EXPECT_EQ(index + 2, s.size()); |
536 | 541 |
537 // Check the call instruction | 542 // Check the call instruction |
538 const Instruction* call_instr = s[index++]; | 543 const Instruction* call_instr = s[index++]; |
539 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode()); | 544 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode()); |
540 size_t num_operands = | 545 size_t num_operands = |
541 1 + // Code object. | 546 1 + // Code object. |
542 1 + // Frame state deopt id | 547 1 + // Frame state deopt id |
543 5 + // One input for each value in frame state + context. | 548 6 + // One input for each value in frame state + context. |
544 4 + // One input for each value in the parent frame state + context. | 549 5 + // One input for each value in the parent frame state + context. |
545 1 + // Function. | 550 1 + // Function. |
546 1; // Context. | 551 1; // Context. |
547 EXPECT_EQ(num_operands, call_instr->InputCount()); | 552 EXPECT_EQ(num_operands, call_instr->InputCount()); |
548 // Code object. | 553 // Code object. |
549 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate()); | 554 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate()); |
550 | 555 |
551 // Deoptimization id. | 556 // Deoptimization id. |
552 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1)); | 557 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1)); |
553 FrameStateDescriptor* desc_before = | 558 FrameStateDescriptor* desc_before = |
554 s.GetFrameStateDescriptor(deopt_id_before); | 559 s.GetFrameStateDescriptor(deopt_id_before); |
555 FrameStateDescriptor* desc_before_outer = desc_before->outer_state(); | 560 FrameStateDescriptor* desc_before_outer = desc_before->outer_state(); |
556 EXPECT_EQ(bailout_id_before, desc_before->bailout_id()); | 561 EXPECT_EQ(bailout_id_before, desc_before->bailout_id()); |
557 EXPECT_EQ(1u, desc_before_outer->parameters_count()); | 562 EXPECT_EQ(1u, desc_before_outer->parameters_count()); |
558 EXPECT_EQ(1u, desc_before_outer->locals_count()); | 563 EXPECT_EQ(1u, desc_before_outer->locals_count()); |
559 EXPECT_EQ(1u, desc_before_outer->stack_count()); | 564 EXPECT_EQ(1u, desc_before_outer->stack_count()); |
560 // Values from parent environment. | 565 // Values from parent environment. |
561 EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(2))); | 566 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); |
562 EXPECT_EQ(kMachInt32, desc_before_outer->GetType(0)); | 567 EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(3))); |
| 568 EXPECT_EQ(kMachInt32, desc_before_outer->GetType(1)); |
563 // Context: | 569 // Context: |
564 EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(3))); | 570 EXPECT_EQ(66, s.ToInt32(call_instr->InputAt(4))); |
565 EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(1)); | 571 EXPECT_EQ(kMachAnyTagged, desc_before_outer->GetType(2)); |
566 EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(4))); | 572 EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(5))); |
567 EXPECT_EQ(kMachInt32, desc_before_outer->GetType(2)); | |
568 EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(5))); | |
569 EXPECT_EQ(kMachInt32, desc_before_outer->GetType(3)); | 573 EXPECT_EQ(kMachInt32, desc_before_outer->GetType(3)); |
| 574 EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(6))); |
| 575 EXPECT_EQ(kMachInt32, desc_before_outer->GetType(4)); |
570 // Values from the nested frame. | 576 // Values from the nested frame. |
571 EXPECT_EQ(1u, desc_before->parameters_count()); | 577 EXPECT_EQ(1u, desc_before->parameters_count()); |
572 EXPECT_EQ(1u, desc_before->locals_count()); | 578 EXPECT_EQ(1u, desc_before->locals_count()); |
573 EXPECT_EQ(2u, desc_before->stack_count()); | 579 EXPECT_EQ(2u, desc_before->stack_count()); |
574 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(6))); | 580 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(0)); |
575 EXPECT_EQ(kMachInt32, desc_before->GetType(0)); | 581 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(8))); |
576 EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(7))); | 582 EXPECT_EQ(kMachInt32, desc_before->GetType(1)); |
577 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(1)); | 583 EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(9))); |
578 EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(8))); | 584 EXPECT_EQ(kMachAnyTagged, desc_before->GetType(2)); |
579 EXPECT_EQ(kMachFloat64, desc_before->GetType(2)); | 585 EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(10))); |
580 EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(9))); | 586 EXPECT_EQ(kMachFloat64, desc_before->GetType(3)); |
581 EXPECT_EQ(kMachInt32, desc_before->GetType(3)); | 587 EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(11))); |
582 EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(10))); | |
583 EXPECT_EQ(kMachInt32, desc_before->GetType(4)); | 588 EXPECT_EQ(kMachInt32, desc_before->GetType(4)); |
| 589 EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(12))); |
| 590 EXPECT_EQ(kMachInt32, desc_before->GetType(5)); |
584 | 591 |
585 // Function. | 592 // Function. |
586 EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(11))); | 593 EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(13))); |
587 // Context. | 594 // Context. |
588 EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(12))); | 595 EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(14))); |
589 // Continuation. | 596 // Continuation. |
590 | 597 |
591 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); | 598 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); |
592 EXPECT_EQ(index, s.size()); | 599 EXPECT_EQ(index, s.size()); |
593 } | 600 } |
594 | 601 |
595 } // namespace compiler | 602 } // namespace compiler |
596 } // namespace internal | 603 } // namespace internal |
597 } // namespace v8 | 604 } // namespace v8 |
OLD | NEW |