Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: test/compiler-unittests/instruction-selector-unittest.cc

Issue 517323002: Make FrameStates recursive (to be used for inlining). (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix bug in GetParentCount Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 341
342 Node* state_node = 342 Node* state_node = m.NewNode(m.common()->FrameState(bailout_id), parameters,
343 m.NewNode(m.common()->FrameState(bailout_id), parameters, locals, stack); 343 locals, stack, m.UndefinedConstant());
344 m.Deoptimize(state_node); 344 m.Deoptimize(state_node);
345 345
346 Stream s = m.Build(kAllExceptNopInstructions); 346 Stream s = m.Build(kAllExceptNopInstructions);
347 347
348 // Skip until kArchCallJSFunction. 348 // Skip until kArchCallJSFunction.
349 size_t index = 0; 349 size_t index = 0;
350 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction; 350 for (; index < s.size() && s[index]->arch_opcode() != kArchCallJSFunction;
351 index++) { 351 index++) {
352 } 352 }
353 // Now we should have three instructions: call, return and deoptimize. 353 // Now we should have three instructions: call, return and deoptimize.
(...skipping 15 matching lines...) Expand all
369 369
370 // Some arguments for the call node. 370 // Some arguments for the call node.
371 Node* function_node = m.Parameter(0); 371 Node* function_node = m.Parameter(0);
372 Node* receiver = m.Parameter(1); 372 Node* receiver = m.Parameter(1);
373 Node* context = m.Int32Constant(1); // Context is ignored. 373 Node* context = m.Int32Constant(1); // Context is ignored.
374 374
375 // Build frame state for the state before the call. 375 // Build frame state for the state before the call.
376 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43)); 376 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
377 Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44)); 377 Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44));
378 Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45)); 378 Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45));
379 Node* frame_state_before = m.NewNode( 379 Node* frame_state_before =
380 m.common()->FrameState(bailout_id_before), parameters, locals, stack); 380 m.NewNode(m.common()->FrameState(bailout_id_before), parameters, locals,
381 stack, m.UndefinedConstant());
381 382
382 StreamBuilder::Label deopt, cont; 383 StreamBuilder::Label deopt, cont;
383 // Build the call. 384 // Build the call.
384 Node* call = 385 Node* call =
385 m.CallFunctionStub0(function_node, receiver, context, frame_state_before, 386 m.CallFunctionStub0(function_node, receiver, context, frame_state_before,
386 &cont, &deopt, CALL_AS_METHOD); 387 &cont, &deopt, CALL_AS_METHOD);
387 388
388 // Create the continuation branch. 389 // Create the continuation branch.
389 m.Bind(&cont); 390 m.Bind(&cont);
390 m.NewNode(m.common()->Continuation(), call); 391 m.NewNode(m.common()->Continuation(), call);
391 m.Return(call); 392 m.Return(call);
392 393
393 // Create the lazy deoptimization block (with a different frame state). 394 // Create the lazy deoptimization block (with a different frame state).
394 m.Bind(&deopt); 395 m.Bind(&deopt);
395 m.NewNode(m.common()->LazyDeoptimization(), call); 396 m.NewNode(m.common()->LazyDeoptimization(), call);
396 397
397 Node* stack_after = 398 Node* stack_after =
398 m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call); 399 m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call);
399 400
400 Node* frame_state_after = m.NewNode(m.common()->FrameState(bailout_id_after), 401 Node* frame_state_after =
401 parameters, locals, stack_after); 402 m.NewNode(m.common()->FrameState(bailout_id_after), parameters, locals,
403 stack_after, m.UndefinedConstant());
402 m.Deoptimize(frame_state_after); 404 m.Deoptimize(frame_state_after);
403 405
404 Stream s = m.Build(kAllExceptNopInstructions); 406 Stream s = m.Build(kAllExceptNopInstructions);
405 407
406 // Skip until kArchCallJSFunction. 408 // Skip until kArchCallJSFunction.
407 size_t index = 0; 409 size_t index = 0;
408 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject; 410 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject;
409 index++) { 411 index++) {
410 } 412 }
411 // Now we should have three instructions: call, return and deoptimize. 413 // Now we should have three instructions: call, return and deoptimize.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 EXPECT_EQ(1, desc_after->locals_count()); 461 EXPECT_EQ(1, desc_after->locals_count());
460 EXPECT_EQ(2, desc_after->stack_count()); 462 EXPECT_EQ(2, desc_after->stack_count());
461 // Parameter value from the frame state. 463 // Parameter value from the frame state.
462 EXPECT_EQ(43, s.ToInt32(deopt_instr->InputAt(1))); 464 EXPECT_EQ(43, s.ToInt32(deopt_instr->InputAt(1)));
463 EXPECT_EQ(44, s.ToInt32(deopt_instr->InputAt(2))); 465 EXPECT_EQ(44, s.ToInt32(deopt_instr->InputAt(2)));
464 EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(3))); 466 EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(3)));
465 EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(4))); 467 EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(4)));
466 EXPECT_EQ(index, s.size()); 468 EXPECT_EQ(index, s.size());
467 } 469 }
468 470
471
472 TARGET_TEST_F(InstructionSelectorTest,
473 CallFunctionStubDeoptRecursiveFrameState) {
474 StreamBuilder m(this, kMachAnyTagged, kMachAnyTagged, kMachAnyTagged,
475 kMachAnyTagged);
476
477 BailoutId bailout_id_before(42);
478 BailoutId bailout_id_after(54);
479 BailoutId bailout_id_parent(62);
480
481 // Some arguments for the call node.
482 Node* function_node = m.Parameter(0);
483 Node* receiver = m.Parameter(1);
484 Node* context = m.Int32Constant(1); // Context is ignored.
485
486 // Build frame state for the state before the call.
487 Node* parameters = m.NewNode(m.common()->StateValues(1), m.Int32Constant(63));
488 Node* locals = m.NewNode(m.common()->StateValues(1), m.Int32Constant(64));
489 Node* stack = m.NewNode(m.common()->StateValues(1), m.Int32Constant(65));
490 Node* frame_state_parent =
491 m.NewNode(m.common()->FrameState(bailout_id_parent), parameters, locals,
492 stack, m.UndefinedConstant());
493
494 Node* parameters2 =
495 m.NewNode(m.common()->StateValues(1), m.Int32Constant(43));
496 Node* locals2 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(44));
497 Node* stack2 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(45));
498 Node* frame_state_before =
499 m.NewNode(m.common()->FrameState(bailout_id_before), parameters2, locals2,
500 stack2, frame_state_parent);
501
502 StreamBuilder::Label deopt, cont;
503 // Build the call.
504 Node* call =
505 m.CallFunctionStub0(function_node, receiver, context, frame_state_before,
506 &cont, &deopt, CALL_AS_METHOD);
507
508 // Create the continuation branch.
509 m.Bind(&cont);
510 m.NewNode(m.common()->Continuation(), call);
511 m.Return(call);
512
513 // Create the lazy deoptimization block (with a different frame state).
514 m.Bind(&deopt);
515 m.NewNode(m.common()->LazyDeoptimization(), call);
516
517 Node* parameters3 =
518 m.NewNode(m.common()->StateValues(1), m.Int32Constant(53));
519 Node* locals3 = m.NewNode(m.common()->StateValues(1), m.Int32Constant(54));
520 Node* stack_after =
521 m.NewNode(m.common()->StateValues(2), m.Int32Constant(55), call);
522
523 Node* frame_state_after =
524 m.NewNode(m.common()->FrameState(bailout_id_after), parameters3, locals3,
525 stack_after, m.UndefinedConstant());
526 m.Deoptimize(frame_state_after);
527
528 Stream s = m.Build(kAllExceptNopInstructions);
529
530 // Skip until kArchCallJSFunction.
531 size_t index = 0;
532 for (; index < s.size() && s[index]->arch_opcode() != kArchCallCodeObject;
533 index++) {
534 }
535 // Now we should have three instructions: call, return and deoptimize.
536 ASSERT_EQ(index + 3, s.size());
537
538 // Check the call instruction
539 const Instruction* call_instr = s[index++];
540 EXPECT_EQ(kArchCallCodeObject, call_instr->arch_opcode());
541 size_t num_operands =
542 1 + // Code object.
543 1 + // Frame state deopt id
544 3 + // One input for each value in frame state.
545 3 + // One input for each value in the parent frame state.
546 1 + // Function.
547 1 + // Context.
548 2; // Continuation and deoptimization block labels.
549 ASSERT_EQ(num_operands, call_instr->InputCount());
550
551 // Code object.
552 EXPECT_TRUE(call_instr->InputAt(0)->IsImmediate());
553
554 // Deoptimization id.
555 int32_t deopt_id_before = s.ToInt32(call_instr->InputAt(1));
556 FrameStateDescriptor* desc_before = s.GetDeoptimizationEntry(deopt_id_before);
557 EXPECT_EQ(bailout_id_before, desc_before->bailout_id());
558 EXPECT_EQ(1, desc_before->parameters_count());
559 EXPECT_EQ(1, desc_before->locals_count());
560 EXPECT_EQ(1, desc_before->stack_count());
561 EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(2)));
Jarin 2014/08/29 15:07:07 Hmm, could we put the parent values first here?
sigurds 2014/09/01 08:48:18 Done.
562 EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(3)));
563 EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(4)));
564 // Values from parent environment should follow.
565 EXPECT_EQ(63, s.ToInt32(call_instr->InputAt(5)));
566 EXPECT_EQ(64, s.ToInt32(call_instr->InputAt(6)));
567 EXPECT_EQ(65, s.ToInt32(call_instr->InputAt(7)));
568
569 // Function.
570 EXPECT_EQ(function_node->id(), s.ToVreg(call_instr->InputAt(8)));
571 // Context.
572 EXPECT_EQ(context->id(), s.ToVreg(call_instr->InputAt(9)));
573 // Continuation.
574 EXPECT_EQ(cont.block()->id(), s.ToInt32(call_instr->InputAt(10)));
575 // Deoptimization.
576 EXPECT_EQ(deopt.block()->id(), s.ToInt32(call_instr->InputAt(11)));
577
578 EXPECT_EQ(kArchRet, s[index++]->arch_opcode());
579
580 // Check the deoptimize instruction.
581 const Instruction* deopt_instr = s[index++];
582 EXPECT_EQ(kArchDeoptimize, deopt_instr->arch_opcode());
583 ASSERT_EQ(5U, deopt_instr->InputCount());
584 int32_t deopt_id_after = s.ToInt32(deopt_instr->InputAt(0));
585 FrameStateDescriptor* desc_after = s.GetDeoptimizationEntry(deopt_id_after);
586 EXPECT_EQ(bailout_id_after, desc_after->bailout_id());
587 EXPECT_EQ(1, desc_after->parameters_count());
588 EXPECT_EQ(1, desc_after->locals_count());
589 EXPECT_EQ(2, desc_after->stack_count());
590 // Parameter value from the frame state.
591 EXPECT_EQ(53, s.ToInt32(deopt_instr->InputAt(1)));
592 EXPECT_EQ(54, s.ToInt32(deopt_instr->InputAt(2)));
593 EXPECT_EQ(55, s.ToInt32(deopt_instr->InputAt(3)));
594 EXPECT_EQ(call->id(), s.ToVreg(deopt_instr->InputAt(4)));
595 EXPECT_EQ(index, s.size());
596 }
597
469 } // namespace compiler 598 } // namespace compiler
470 } // namespace internal 599 } // namespace internal
471 } // namespace v8 600 } // namespace v8
OLDNEW
« src/compiler/instruction-selector.cc ('K') | « test/cctest/compiler/test-codegen-deopt.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698