| 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/compiler-unittests/instruction-selector-unittest.h" | 5 #include "test/compiler-unittests/instruction-selector-unittest.h" |
| 6 | 6 |
| 7 #include "src/flags.h" | 7 #include "src/flags.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 331 m.Bind(&cont); | 331 m.Bind(&cont); |
| 332 m.NewNode(m.common()->Continuation(), call); | 332 m.NewNode(m.common()->Continuation(), call); |
| 333 m.Return(call); | 333 m.Return(call); |
| 334 | 334 |
| 335 m.Bind(&deopt); | 335 m.Bind(&deopt); |
| 336 m.NewNode(m.common()->LazyDeoptimization(), call); | 336 m.NewNode(m.common()->LazyDeoptimization(), call); |
| 337 | 337 |
| 338 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(1)); | 338 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(1)); |
| 339 Node* locals = m.NewNode(m.common()->StateValues(0)); | 339 Node* locals = m.NewNode(m.common()->StateValues(0)); |
| 340 Node* stack = m.NewNode(m.common()->StateValues(0)); | 340 Node* stack = m.NewNode(m.common()->StateValues(0)); |
| 341 Node* context_sentinel = m.Int32Constant(0); |
| 341 | 342 |
| 342 Node* state_node = | 343 Node* state_node = m.NewNode(m.common()->FrameState(bailout_id), parameters, |
| 343 m.NewNode(m.common()->FrameState(bailout_id), parameters, locals, stack); | 344 locals, stack, context_sentinel); |
| 344 m.Deoptimize(state_node); | 345 m.Deoptimize(state_node); |
| 345 | 346 |
| 346 Stream s = m.Build(kAllExceptNopInstructions); | 347 Stream s = m.Build(kAllExceptNopInstructions); |
| 347 | 348 |
| 348 // Skip until kArchCallJSFunction. | 349 // Skip until kArchCallJSFunction. |
| 349 size_t index = 0; | 350 size_t index = 0; |
| 350 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction; | 351 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction; |
| 351 index++) { | 352 index++) { |
| 352 } | 353 } |
| 353 // Now we should have three instructions: call, return and deoptimize. | 354 // Now we should have three instructions: call, return and deoptimize. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 369 | 370 |
| 370 // Some arguments for the call node. | 371 // Some arguments for the call node. |
| 371 Node* function_node = m.Parameter(0); | 372 Node* function_node = m.Parameter(0); |
| 372 Node* receiver = m.Parameter(1); | 373 Node* receiver = m.Parameter(1); |
| 373 Node* context = m.Int32Constant(1); // Context is ignored. | 374 Node* context = m.Int32Constant(1); // Context is ignored. |
| 374 | 375 |
| 375 // Build frame state for the state before the call. | 376 // Build frame state for the state before the call. |
| 376 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43)); | 377 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43)); |
| 377 Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44)); | 378 Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44)); |
| 378 Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45)); | 379 Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45)); |
| 379 Node* frame_state_before = m.NewNode( | 380 Node* context_sentinel = m.Int32Constant(0); |
| 380 m.common()->FrameState(bailout_id_before), parameters, locals, stack); | 381 Node* frame_state_before = |
| 382 m.NewNode(m.common()->FrameState(bailout_id_before), parameters, locals, |
| 383 stack, context_sentinel); |
| 381 | 384 |
| 382 StreamBuilder::Label deopt, cont; | 385 StreamBuilder::Label deopt, cont; |
| 383 // Build the call. | 386 // Build the call. |
| 384 Node* call = | 387 Node* call = |
| 385 m.CallFunctionStub0(function_node, receiver, context, frame_state_before, | 388 m.CallFunctionStub0(function_node, receiver, context, frame_state_before, |
| 386 &cont, &deopt, CALL_AS_METHOD); | 389 &cont, &deopt, CALL_AS_METHOD); |
| 387 | 390 |
| 388 // Create the continuation branch. | 391 // Create the continuation branch. |
| 389 m.Bind(&cont); | 392 m.Bind(&cont); |
| 390 m.NewNode(m.common()->Continuation(), call); | 393 m.NewNode(m.common()->Continuation(), call); |
| 391 m.Return(call); | 394 m.Return(call); |
| 392 | 395 |
| 393 // Create the lazy deoptimization block (with a different frame state). | 396 // Create the lazy deoptimization block (with a different frame state). |
| 394 m.Bind(&deopt); | 397 m.Bind(&deopt); |
| 395 m.NewNode(m.common()->LazyDeoptimization(), call); | 398 m.NewNode(m.common()->LazyDeoptimization(), call); |
| 396 | 399 |
| 397 Node* stack_after = | 400 Node* stack_after = |
| 398 m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call); | 401 m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call); |
| 399 | 402 |
| 400 Node* frame_state_after = m.NewNode(m.common()->FrameState(bailout_id_after), | 403 Node* frame_state_after = |
| 401 parameters, locals, stack_after); | 404 m.NewNode(m.common()->FrameState(bailout_id_after), parameters, locals, |
| 405 stack_after, context_sentinel); |
| 402 m.Deoptimize(frame_state_after); | 406 m.Deoptimize(frame_state_after); |
| 403 | 407 |
| 404 Stream s = m.Build(kAllExceptNopInstructions); | 408 Stream s = m.Build(kAllExceptNopInstructions); |
| 405 | 409 |
| 406 // Skip until kArchCallJSFunction. | 410 // Skip until kArchCallJSFunction. |
| 407 size_t index = 0; | 411 size_t index = 0; |
| 408 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; | 412 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; |
| 409 index++) { | 413 index++) { |
| 410 } | 414 } |
| 411 // Now we should have three instructions: call, return and deoptimize. | 415 // Now we should have three instructions: call, return and deoptimize. |
| 412 ASSERT_EQ(index + 3, s.size()); | 416 ASSERT_EQ(index + 3, s.size()); |
| 413 | 417 |
| 414 // Check the call instruction | 418 // Check the call instruction |
| 415 const Instruction* call_instr = s[index++]; | 419 const Instruction* call_instr = s[index++]; |
| 416 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode()); | 420 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode()); |
| 417 size_t num_operands = | 421 size_t num_operands = |
| 418 1 + // Code object. | 422 1 + // Code object. |
| 419 1 + | 423 1 + |
| 420 3 + // Frame state deopt id + one input for each value in frame state. | 424 4 + // Frame state deopt id + one input for each value in frame state. |
| 421 1 + // Function. | 425 1 + // Function. |
| 422 1 + // Context. | 426 1 + // Context. |
| 423 2; // Continuation and deoptimization block labels. | 427 2; // Continuation and deoptimization block labels. |
| 424 ASSERT_EQ(num_operands, call_instr->InputCount()); | 428 ASSERT_EQ(num_operands, call_instr->InputCount()); |
| 425 | 429 |
| 426 // Code object. | 430 // Code object. |
| 427 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate()); | 431 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate()); |
| 428 | 432 |
| 429 // Deoptimization id. | 433 // Deoptimization id. |
| 430 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1)); | 434 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1)); |
| 431 FrameStateDescriptor* desc_before = s.GetDeoptimizationEntry(deopt_id_before); | 435 FrameStateDescriptor* desc_before = s.GetDeoptimizationEntry(deopt_id_before); |
| 432 EXPECT_EQ(bailout_id_before, desc_before->bailout_id()); | 436 EXPECT_EQ(bailout_id_before, desc_before->bailout_id()); |
| 433 EXPECT_EQ(1, desc_before->parameters_count()); | 437 EXPECT_EQ(1, desc_before->parameters_count()); |
| 434 EXPECT_EQ(1, desc_before->locals_count()); | 438 EXPECT_EQ(1, desc_before->locals_count()); |
| 435 EXPECT_EQ(1, desc_before->stack_count()); | 439 EXPECT_EQ(1, desc_before->stack_count()); |
| 436 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2))); | 440 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2))); |
| 437 EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(3))); | 441 EXPECT_EQ(0, s.ToInt32(call_instr->InputAt(3))); |
| 438 EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(4))); | 442 EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(4))); |
| 443 EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(5))); |
| 439 | 444 |
| 440 // Function. | 445 // Function. |
| 441 EXPECT_EQ(function_node->id(), s.ToVreg(call_instr->InputAt(5))); | 446 EXPECT_EQ(function_node->id(), s.ToVreg(call_instr->InputAt(6))); |
| 442 // Context. | 447 // Context. |
| 443 EXPECT_EQ(context->id(), s.ToVreg(call_instr->InputAt(6))); | 448 EXPECT_EQ(context->id(), s.ToVreg(call_instr->InputAt(7))); |
| 444 // Continuation. | 449 // Continuation. |
| 445 EXPECT_EQ(cont.block()->id(), s.ToInt32(call_instr->InputAt(7))); | 450 EXPECT_EQ(cont.block()->id(), s.ToInt32(call_instr->InputAt(8))); |
| 446 // Deoptimization. | 451 // Deoptimization. |
| 447 EXPECT_EQ(deopt.block()->id(), s.ToInt32(call_instr->InputAt(8))); | 452 EXPECT_EQ(deopt.block()->id(), s.ToInt32(call_instr->InputAt(9))); |
| 448 | 453 |
| 449 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); | 454 EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); |
| 450 | 455 |
| 451 // Check the deoptimize instruction. | 456 // Check the deoptimize instruction. |
| 452 const Instruction* deopt_instr = s[index++]; | 457 const Instruction* deopt_instr = s[index++]; |
| 453 EXPECT_EQ(kArchDeoptimize, deopt_instr->arch_opcode()); | 458 EXPECT_EQ(kArchDeoptimize, deopt_instr->arch_opcode()); |
| 454 ASSERT_EQ(5U, deopt_instr->InputCount()); | 459 ASSERT_EQ(6U, deopt_instr->InputCount()); |
| 455 int32_t deopt_id_after = s.ToInt32(deopt_instr->InputAt(0)); | 460 int32_t deopt_id_after = s.ToInt32(deopt_instr->InputAt(0)); |
| 456 FrameStateDescriptor* desc_after = s.GetDeoptimizationEntry(deopt_id_after); | 461 FrameStateDescriptor* desc_after = s.GetDeoptimizationEntry(deopt_id_after); |
| 457 EXPECT_EQ(bailout_id_after, desc_after->bailout_id()); | 462 EXPECT_EQ(bailout_id_after, desc_after->bailout_id()); |
| 458 EXPECT_EQ(1, desc_after->parameters_count()); | 463 EXPECT_EQ(1, desc_after->parameters_count()); |
| 459 EXPECT_EQ(1, desc_after->locals_count()); | 464 EXPECT_EQ(1, desc_after->locals_count()); |
| 460 EXPECT_EQ(2, desc_after->stack_count()); | 465 EXPECT_EQ(2, desc_after->stack_count()); |
| 461 // Parameter value from the frame state. | 466 // Parameter value from the frame state. |
| 462 EXPECT_EQ(43, s.ToInt32(deopt_instr->InputAt(1))); | 467 EXPECT_EQ(43, s.ToInt32(deopt_instr->InputAt(1))); |
| 463 EXPECT_EQ(44, s.ToInt32(deopt_instr->InputAt(2))); | 468 EXPECT_EQ(0, s.ToInt32(deopt_instr->InputAt(2))); |
| 464 EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(3))); | 469 EXPECT_EQ(44, s.ToInt32(deopt_instr->InputAt(3))); |
| 465 EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(4))); | 470 EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(4))); |
| 471 EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(5))); |
| 466 EXPECT_EQ(index, s.size()); | 472 EXPECT_EQ(index, s.size()); |
| 467 } | 473 } |
| 468 | 474 |
| 469 } // namespace compiler | 475 } // namespace compiler |
| 470 } // namespace internal | 476 } // namespace internal |
| 471 } // namespace v8 | 477 } // namespace v8 |
| OLD | NEW |