| 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 |