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/code-factory.h" |
7 #include "src/compiler/graph.h" | 8 #include "src/compiler/graph.h" |
8 #include "src/compiler/schedule.h" | 9 #include "src/compiler/schedule.h" |
9 #include "src/flags.h" | 10 #include "src/flags.h" |
10 #include "test/unittests/compiler/compiler-test-utils.h" | 11 #include "test/unittests/compiler/compiler-test-utils.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace compiler { | 15 namespace compiler { |
15 | 16 |
16 namespace { | 17 namespace { |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 Node* function_node = m.Parameter(0); | 365 Node* function_node = m.Parameter(0); |
365 Node* receiver = m.Parameter(1); | 366 Node* receiver = m.Parameter(1); |
366 Node* context = m.Parameter(2); | 367 Node* context = m.Parameter(2); |
367 | 368 |
368 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); | 369 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); |
369 ZoneVector<MachineType> empty_types(zone()); | 370 ZoneVector<MachineType> empty_types(zone()); |
370 | 371 |
371 CallDescriptor* descriptor = Linkage::GetJSCallDescriptor( | 372 CallDescriptor* descriptor = Linkage::GetJSCallDescriptor( |
372 zone(), false, 1, CallDescriptor::kNeedsFrameState); | 373 zone(), false, 1, CallDescriptor::kNeedsFrameState); |
373 | 374 |
| 375 // Build frame state for the state before the call. |
374 Node* parameters = | 376 Node* parameters = |
375 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(1)); | 377 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(1)); |
376 Node* locals = m.AddNode(m.common()->TypedStateValues(&empty_types)); | 378 Node* locals = m.AddNode(m.common()->TypedStateValues(&empty_types)); |
377 Node* stack = m.AddNode(m.common()->TypedStateValues(&empty_types)); | 379 Node* stack = m.AddNode(m.common()->TypedStateValues(&empty_types)); |
378 Node* context_dummy = m.Int32Constant(0); | 380 Node* context_sentinel = m.Int32Constant(0); |
379 | |
380 Node* state_node = m.AddNode( | 381 Node* state_node = m.AddNode( |
381 m.common()->FrameState(bailout_id, OutputFrameStateCombine::Push(), | 382 m.common()->FrameState(bailout_id, OutputFrameStateCombine::Push(), |
382 m.GetFrameStateFunctionInfo(1, 0)), | 383 m.GetFrameStateFunctionInfo(1, 0)), |
383 parameters, locals, stack, context_dummy, function_node, | 384 parameters, locals, stack, context_sentinel, function_node, |
384 m.UndefinedConstant()); | 385 m.UndefinedConstant()); |
| 386 |
| 387 // Build the call. |
385 Node* args[] = {receiver, m.Int32Constant(1), context}; | 388 Node* args[] = {receiver, m.Int32Constant(1), context}; |
386 Node* call = | 389 Node* call = |
387 m.CallNWithFrameState(descriptor, function_node, args, state_node); | 390 m.CallNWithFrameState(descriptor, function_node, args, state_node); |
388 m.Return(call); | 391 m.Return(call); |
389 | 392 |
390 Stream s = m.Build(kAllExceptNopInstructions); | 393 Stream s = m.Build(kAllExceptNopInstructions); |
391 | 394 |
392 // Skip until kArchCallJSFunction. | 395 // Skip until kArchCallJSFunction. |
393 size_t index = 0; | 396 size_t index = 0; |
394 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction; | 397 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction; |
395 index++) { | 398 index++) { |
396 } | 399 } |
397 // Now we should have two instructions: call and return. | 400 // Now we should have two instructions: call and return. |
398 ASSERT_EQ(index + 2, s.size()); | 401 ASSERT_EQ(index + 2, s.size()); |
399 | 402 |
400 EXPECT_EQ(kArchCallJSFunction, s[index++]->arch_opcode()); | 403 EXPECT_EQ(kArchCallJSFunction, s[index++]->arch_opcode()); |
401 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); | 404 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); |
402 | 405 |
403 // TODO(jarin) Check deoptimization table. | 406 // TODO(jarin) Check deoptimization table. |
404 } | 407 } |
405 | 408 |
406 | 409 |
407 TARGET_TEST_F(InstructionSelectorTest, CallFunctionStubWithDeopt) { | 410 TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeopt) { |
408 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, | 411 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, |
409 kMachAnyTagged); | 412 kMachAnyTagged); |
410 | 413 |
411 BailoutId bailout_id_before(42); | 414 BailoutId bailout_id_before(42); |
412 | 415 |
413 // Some arguments for the call node. | 416 // Some arguments for the call node. |
414 Node* function_node = m.Parameter(0); | 417 Node* function_node = m.Parameter(0); |
415 Node* receiver = m.Parameter(1); | 418 Node* receiver = m.Parameter(1); |
416 Node* context = m.Int32Constant(1); // Context is ignored. | 419 Node* context = m.Int32Constant(1); // Context is ignored. |
417 | 420 |
418 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); | 421 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); |
419 ZoneVector<MachineType> float64_type(1, kMachFloat64, zone()); | 422 ZoneVector<MachineType> float64_type(1, kMachFloat64, zone()); |
420 ZoneVector<MachineType> tagged_type(1, kMachAnyTagged, zone()); | 423 ZoneVector<MachineType> tagged_type(1, kMachAnyTagged, zone()); |
421 | 424 |
| 425 Callable callable = CodeFactory::ToObject(isolate()); |
| 426 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( |
| 427 isolate(), zone(), callable.descriptor(), 1, |
| 428 CallDescriptor::kNeedsFrameState, Operator::kNoProperties); |
| 429 |
422 // Build frame state for the state before the call. | 430 // Build frame state for the state before the call. |
423 Node* parameters = | 431 Node* parameters = |
424 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); | 432 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); |
425 Node* locals = m.AddNode(m.common()->TypedStateValues(&float64_type), | 433 Node* locals = m.AddNode(m.common()->TypedStateValues(&float64_type), |
426 m.Float64Constant(0.5)); | 434 m.Float64Constant(0.5)); |
427 Node* stack = m.AddNode(m.common()->TypedStateValues(&tagged_type), | 435 Node* stack = m.AddNode(m.common()->TypedStateValues(&tagged_type), |
428 m.UndefinedConstant()); | 436 m.UndefinedConstant()); |
429 | |
430 Node* context_sentinel = m.Int32Constant(0); | 437 Node* context_sentinel = m.Int32Constant(0); |
431 Node* frame_state_before = m.AddNode( | 438 Node* state_node = m.AddNode( |
432 m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(), | 439 m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(), |
433 m.GetFrameStateFunctionInfo(1, 1)), | 440 m.GetFrameStateFunctionInfo(1, 1)), |
434 parameters, locals, stack, context_sentinel, function_node, | 441 parameters, locals, stack, context_sentinel, function_node, |
435 m.UndefinedConstant()); | 442 m.UndefinedConstant()); |
436 | 443 |
437 // Build the call. | 444 // Build the call. |
438 Node* call = m.CallFunctionStub0(function_node, receiver, context, | 445 Node* args[] = {function_node, receiver, context}; |
439 frame_state_before, CALL_AS_METHOD); | 446 Node* stub_code = m.HeapConstant(callable.code()); |
440 | 447 Node* call = m.CallNWithFrameState(descriptor, stub_code, args, state_node); |
441 m.Return(call); | 448 m.Return(call); |
442 | 449 |
443 Stream s = m.Build(kAllExceptNopInstructions); | 450 Stream s = m.Build(kAllExceptNopInstructions); |
444 | 451 |
445 // Skip until kArchCallJSFunction. | 452 // Skip until kArchCallJSFunction. |
446 size_t index = 0; | 453 size_t index = 0; |
447 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; | 454 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; |
448 index++) { | 455 index++) { |
449 } | 456 } |
450 // Now we should have two instructions: call, return. | 457 // Now we should have two instructions: call, return. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(7))); | 498 EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(7))); |
492 // Context. | 499 // Context. |
493 EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(8))); | 500 EXPECT_EQ(s.ToVreg(context), s.ToVreg(call_instr->InputAt(8))); |
494 | 501 |
495 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); | 502 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); |
496 | 503 |
497 EXPECT_EQ(index, s.size()); | 504 EXPECT_EQ(index, s.size()); |
498 } | 505 } |
499 | 506 |
500 | 507 |
501 TARGET_TEST_F(InstructionSelectorTest, | 508 TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) { |
502 CallFunctionStubDeoptRecursiveFrameState) { | |
503 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, | 509 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged, |
504 kMachAnyTagged); | 510 kMachAnyTagged); |
505 | 511 |
506 BailoutId bailout_id_before(42); | 512 BailoutId bailout_id_before(42); |
507 BailoutId bailout_id_parent(62); | 513 BailoutId bailout_id_parent(62); |
508 | 514 |
509 // Some arguments for the call node. | 515 // Some arguments for the call node. |
510 Node* function_node = m.Parameter(0); | 516 Node* function_node = m.Parameter(0); |
511 Node* receiver = m.Parameter(1); | 517 Node* receiver = m.Parameter(1); |
512 Node* context = m.Int32Constant(66); | 518 Node* context = m.Int32Constant(66); |
| 519 Node* context2 = m.Int32Constant(46); |
513 | 520 |
514 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); | 521 ZoneVector<MachineType> int32_type(1, kMachInt32, zone()); |
515 ZoneVector<MachineType> int32x2_type(2, kMachInt32, zone()); | 522 ZoneVector<MachineType> int32x2_type(2, kMachInt32, zone()); |
516 ZoneVector<MachineType> float64_type(1, kMachFloat64, zone()); | 523 ZoneVector<MachineType> float64_type(1, kMachFloat64, zone()); |
517 | 524 |
| 525 Callable callable = CodeFactory::ToObject(isolate()); |
| 526 CallDescriptor* descriptor = Linkage::GetStubCallDescriptor( |
| 527 isolate(), zone(), callable.descriptor(), 1, |
| 528 CallDescriptor::kNeedsFrameState, Operator::kNoProperties); |
| 529 |
518 // Build frame state for the state before the call. | 530 // Build frame state for the state before the call. |
519 Node* parameters = | 531 Node* parameters = |
520 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(63)); | 532 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(63)); |
521 Node* locals = | 533 Node* locals = |
522 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64)); | 534 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(64)); |
523 Node* stack = | 535 Node* stack = |
524 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65)); | 536 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(65)); |
525 Node* frame_state_parent = m.AddNode( | 537 Node* frame_state_parent = m.AddNode( |
526 m.common()->FrameState(bailout_id_parent, | 538 m.common()->FrameState(bailout_id_parent, |
527 OutputFrameStateCombine::Ignore(), | 539 OutputFrameStateCombine::Ignore(), |
528 m.GetFrameStateFunctionInfo(1, 1)), | 540 m.GetFrameStateFunctionInfo(1, 1)), |
529 parameters, locals, stack, context, function_node, m.UndefinedConstant()); | 541 parameters, locals, stack, context, function_node, m.UndefinedConstant()); |
530 | 542 |
531 Node* context2 = m.Int32Constant(46); | |
532 Node* parameters2 = | 543 Node* parameters2 = |
533 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); | 544 m.AddNode(m.common()->TypedStateValues(&int32_type), m.Int32Constant(43)); |
534 Node* locals2 = m.AddNode(m.common()->TypedStateValues(&float64_type), | 545 Node* locals2 = m.AddNode(m.common()->TypedStateValues(&float64_type), |
535 m.Float64Constant(0.25)); | 546 m.Float64Constant(0.25)); |
536 Node* stack2 = m.AddNode(m.common()->TypedStateValues(&int32x2_type), | 547 Node* stack2 = m.AddNode(m.common()->TypedStateValues(&int32x2_type), |
537 m.Int32Constant(44), m.Int32Constant(45)); | 548 m.Int32Constant(44), m.Int32Constant(45)); |
538 Node* frame_state_before = m.AddNode( | 549 Node* state_node = m.AddNode( |
539 m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(), | 550 m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::Push(), |
540 m.GetFrameStateFunctionInfo(1, 1)), | 551 m.GetFrameStateFunctionInfo(1, 1)), |
541 parameters2, locals2, stack2, context2, function_node, | 552 parameters2, locals2, stack2, context2, function_node, |
542 frame_state_parent); | 553 frame_state_parent); |
543 | 554 |
544 // Build the call. | 555 // Build the call. |
545 Node* call = m.CallFunctionStub0(function_node, receiver, context2, | 556 Node* args[] = {function_node, receiver, context2}; |
546 frame_state_before, CALL_AS_METHOD); | 557 Node* stub_code = m.HeapConstant(callable.code()); |
547 | 558 Node* call = m.CallNWithFrameState(descriptor, stub_code, args, state_node); |
548 m.Return(call); | 559 m.Return(call); |
549 | 560 |
550 Stream s = m.Build(kAllExceptNopInstructions); | 561 Stream s = m.Build(kAllExceptNopInstructions); |
551 | 562 |
552 // Skip until kArchCallJSFunction. | 563 // Skip until kArchCallJSFunction. |
553 size_t index = 0; | 564 size_t index = 0; |
554 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; | 565 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; |
555 index++) { | 566 index++) { |
556 } | 567 } |
557 // Now we should have three instructions: call, return. | 568 // Now we should have three instructions: call, return. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(14))); | 624 EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(14))); |
614 // Continuation. | 625 // Continuation. |
615 | 626 |
616 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); | 627 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); |
617 EXPECT_EQ(index, s.size()); | 628 EXPECT_EQ(index, s.size()); |
618 } | 629 } |
619 | 630 |
620 } // namespace compiler | 631 } // namespace compiler |
621 } // namespace internal | 632 } // namespace internal |
622 } // namespace v8 | 633 } // namespace v8 |
OLD | NEW |