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 |