OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 | 462 |
463 Operand LCodeGen::ToOperand(LOperand* op) const { | 463 Operand LCodeGen::ToOperand(LOperand* op) const { |
464 // Does not handle registers. In X64 assembler, plain registers are not | 464 // Does not handle registers. In X64 assembler, plain registers are not |
465 // representable as an Operand. | 465 // representable as an Operand. |
466 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 466 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); |
467 return Operand(rbp, StackSlotOffset(op->index())); | 467 return Operand(rbp, StackSlotOffset(op->index())); |
468 } | 468 } |
469 | 469 |
470 | 470 |
471 void LCodeGen::WriteTranslation(LEnvironment* environment, | 471 void LCodeGen::WriteTranslation(LEnvironment* environment, |
472 Translation* translation) { | 472 Translation* translation, |
| 473 int* pushed_arguments_index, |
| 474 int* pushed_arguments_count) { |
473 if (environment == NULL) return; | 475 if (environment == NULL) return; |
474 | 476 |
475 // The translation includes one command per value in the environment. | 477 // The translation includes one command per value in the environment. |
476 int translation_size = environment->translation_size(); | 478 int translation_size = environment->values()->length(); |
477 // The output frame height does not include the parameters. | 479 // The output frame height does not include the parameters. |
478 int height = translation_size - environment->parameter_count(); | 480 int height = translation_size - environment->parameter_count(); |
479 | 481 |
480 WriteTranslation(environment->outer(), translation); | 482 // Function parameters are arguments to the outermost environment. The |
| 483 // arguments index points to the first element of a sequence of tagged |
| 484 // values on the stack that represent the arguments. This needs to be |
| 485 // kept in sync with the LArgumentsElements implementation. |
| 486 *pushed_arguments_index = -environment->parameter_count(); |
| 487 *pushed_arguments_count = environment->parameter_count(); |
| 488 |
| 489 WriteTranslation(environment->outer(), |
| 490 translation, |
| 491 pushed_arguments_index, |
| 492 pushed_arguments_count); |
481 bool has_closure_id = !info()->closure().is_null() && | 493 bool has_closure_id = !info()->closure().is_null() && |
482 !info()->closure().is_identical_to(environment->closure()); | 494 !info()->closure().is_identical_to(environment->closure()); |
483 int closure_id = has_closure_id | 495 int closure_id = has_closure_id |
484 ? DefineDeoptimizationLiteral(environment->closure()) | 496 ? DefineDeoptimizationLiteral(environment->closure()) |
485 : Translation::kSelfLiteralId; | 497 : Translation::kSelfLiteralId; |
486 | 498 |
487 switch (environment->frame_type()) { | 499 switch (environment->frame_type()) { |
488 case JS_FUNCTION: | 500 case JS_FUNCTION: |
489 translation->BeginJSFrame(environment->ast_id(), closure_id, height); | 501 translation->BeginJSFrame(environment->ast_id(), closure_id, height); |
490 break; | 502 break; |
(...skipping 11 matching lines...) Expand all Loading... |
502 translation->BeginSetterStubFrame(closure_id); | 514 translation->BeginSetterStubFrame(closure_id); |
503 break; | 515 break; |
504 case ARGUMENTS_ADAPTOR: | 516 case ARGUMENTS_ADAPTOR: |
505 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); | 517 translation->BeginArgumentsAdaptorFrame(closure_id, translation_size); |
506 break; | 518 break; |
507 case STUB: | 519 case STUB: |
508 translation->BeginCompiledStubFrame(); | 520 translation->BeginCompiledStubFrame(); |
509 break; | 521 break; |
510 } | 522 } |
511 | 523 |
| 524 // Inlined frames which push their arguments cause the index to be |
| 525 // bumped and another stack area to be used for materialization, |
| 526 // otherwise actual argument values are unknown for inlined frames. |
| 527 bool arguments_known = true; |
| 528 int arguments_index = *pushed_arguments_index; |
| 529 int arguments_count = *pushed_arguments_count; |
| 530 if (environment->entry() != NULL) { |
| 531 arguments_known = environment->entry()->arguments_pushed(); |
| 532 arguments_index = arguments_index < 0 |
| 533 ? GetStackSlotCount() : arguments_index + arguments_count; |
| 534 arguments_count = environment->entry()->arguments_count() + 1; |
| 535 if (environment->entry()->arguments_pushed()) { |
| 536 *pushed_arguments_index = arguments_index; |
| 537 *pushed_arguments_count = arguments_count; |
| 538 } |
| 539 } |
| 540 |
512 for (int i = 0; i < translation_size; ++i) { | 541 for (int i = 0; i < translation_size; ++i) { |
513 LOperand* value = environment->values()->at(i); | 542 LOperand* value = environment->values()->at(i); |
514 // spilled_registers_ and spilled_double_registers_ are either | 543 // spilled_registers_ and spilled_double_registers_ are either |
515 // both NULL or both set. | 544 // both NULL or both set. |
516 if (environment->spilled_registers() != NULL && value != NULL) { | 545 if (environment->spilled_registers() != NULL && value != NULL) { |
517 if (value->IsRegister() && | 546 if (value->IsRegister() && |
518 environment->spilled_registers()[value->index()] != NULL) { | 547 environment->spilled_registers()[value->index()] != NULL) { |
519 translation->MarkDuplicate(); | 548 translation->MarkDuplicate(); |
520 AddToTranslation(translation, | 549 AddToTranslation(translation, |
521 environment->spilled_registers()[value->index()], | 550 environment->spilled_registers()[value->index()], |
522 environment->HasTaggedValueAt(i), | 551 environment->HasTaggedValueAt(i), |
523 environment->HasUint32ValueAt(i)); | 552 environment->HasUint32ValueAt(i), |
| 553 arguments_known, |
| 554 arguments_index, |
| 555 arguments_count); |
524 } else if ( | 556 } else if ( |
525 value->IsDoubleRegister() && | 557 value->IsDoubleRegister() && |
526 environment->spilled_double_registers()[value->index()] != NULL) { | 558 environment->spilled_double_registers()[value->index()] != NULL) { |
527 translation->MarkDuplicate(); | 559 translation->MarkDuplicate(); |
528 AddToTranslation( | 560 AddToTranslation( |
529 translation, | 561 translation, |
530 environment->spilled_double_registers()[value->index()], | 562 environment->spilled_double_registers()[value->index()], |
531 false, | 563 false, |
532 false); | 564 false, |
| 565 arguments_known, |
| 566 arguments_index, |
| 567 arguments_count); |
533 } | 568 } |
534 } | 569 } |
535 | 570 |
536 // TODO(mstarzinger): Introduce marker operands to indicate that this value | |
537 // is not present and must be reconstructed from the deoptimizer. Currently | |
538 // this is only used for the arguments object. | |
539 if (value == NULL) { | |
540 int arguments_count = environment->values()->length() - translation_size; | |
541 translation->BeginArgumentsObject(arguments_count); | |
542 for (int i = 0; i < arguments_count; ++i) { | |
543 LOperand* value = environment->values()->at(translation_size + i); | |
544 ASSERT(environment->spilled_registers() == NULL || | |
545 !value->IsRegister() || | |
546 environment->spilled_registers()[value->index()] == NULL); | |
547 ASSERT(environment->spilled_registers() == NULL || | |
548 !value->IsDoubleRegister() || | |
549 environment->spilled_double_registers()[value->index()] == NULL); | |
550 AddToTranslation(translation, | |
551 value, | |
552 environment->HasTaggedValueAt(translation_size + i), | |
553 environment->HasUint32ValueAt(translation_size + i)); | |
554 } | |
555 continue; | |
556 } | |
557 | |
558 AddToTranslation(translation, | 571 AddToTranslation(translation, |
559 value, | 572 value, |
560 environment->HasTaggedValueAt(i), | 573 environment->HasTaggedValueAt(i), |
561 environment->HasUint32ValueAt(i)); | 574 environment->HasUint32ValueAt(i), |
| 575 arguments_known, |
| 576 arguments_index, |
| 577 arguments_count); |
562 } | 578 } |
563 } | 579 } |
564 | 580 |
565 | 581 |
566 void LCodeGen::AddToTranslation(Translation* translation, | 582 void LCodeGen::AddToTranslation(Translation* translation, |
567 LOperand* op, | 583 LOperand* op, |
568 bool is_tagged, | 584 bool is_tagged, |
569 bool is_uint32) { | 585 bool is_uint32, |
570 if (op->IsStackSlot()) { | 586 bool arguments_known, |
| 587 int arguments_index, |
| 588 int arguments_count) { |
| 589 if (op == NULL) { |
| 590 // TODO(twuerthinger): Introduce marker operands to indicate that this value |
| 591 // is not present and must be reconstructed from the deoptimizer. Currently |
| 592 // this is only used for the arguments object. |
| 593 translation->StoreArgumentsObject( |
| 594 arguments_known, arguments_index, arguments_count); |
| 595 } else if (op->IsStackSlot()) { |
571 if (is_tagged) { | 596 if (is_tagged) { |
572 translation->StoreStackSlot(op->index()); | 597 translation->StoreStackSlot(op->index()); |
573 } else if (is_uint32) { | 598 } else if (is_uint32) { |
574 translation->StoreUint32StackSlot(op->index()); | 599 translation->StoreUint32StackSlot(op->index()); |
575 } else { | 600 } else { |
576 translation->StoreInt32StackSlot(op->index()); | 601 translation->StoreInt32StackSlot(op->index()); |
577 } | 602 } |
578 } else if (op->IsDoubleStackSlot()) { | 603 } else if (op->IsDoubleStackSlot()) { |
579 translation->StoreDoubleStackSlot(op->index()); | 604 translation->StoreDoubleStackSlot(op->index()); |
580 } else if (op->IsArgument()) { | 605 } else if (op->IsArgument()) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 // 0 ..................................................... size-1 | 690 // 0 ..................................................... size-1 |
666 // [parameters] [locals] [expression stack including arguments] | 691 // [parameters] [locals] [expression stack including arguments] |
667 | 692 |
668 // Layout of the translation: | 693 // Layout of the translation: |
669 // 0 ........................................................ size - 1 + 4 | 694 // 0 ........................................................ size - 1 + 4 |
670 // [expression stack including arguments] [locals] [4 words] [parameters] | 695 // [expression stack including arguments] [locals] [4 words] [parameters] |
671 // |>------------ translation_size ------------<| | 696 // |>------------ translation_size ------------<| |
672 | 697 |
673 int frame_count = 0; | 698 int frame_count = 0; |
674 int jsframe_count = 0; | 699 int jsframe_count = 0; |
| 700 int args_index = 0; |
| 701 int args_count = 0; |
675 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { | 702 for (LEnvironment* e = environment; e != NULL; e = e->outer()) { |
676 ++frame_count; | 703 ++frame_count; |
677 if (e->frame_type() == JS_FUNCTION) { | 704 if (e->frame_type() == JS_FUNCTION) { |
678 ++jsframe_count; | 705 ++jsframe_count; |
679 } | 706 } |
680 } | 707 } |
681 Translation translation(&translations_, frame_count, jsframe_count, zone()); | 708 Translation translation(&translations_, frame_count, jsframe_count, zone()); |
682 WriteTranslation(environment, &translation); | 709 WriteTranslation(environment, &translation, &args_index, &args_count); |
683 int deoptimization_index = deoptimizations_.length(); | 710 int deoptimization_index = deoptimizations_.length(); |
684 int pc_offset = masm()->pc_offset(); | 711 int pc_offset = masm()->pc_offset(); |
685 environment->Register(deoptimization_index, | 712 environment->Register(deoptimization_index, |
686 translation.index(), | 713 translation.index(), |
687 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 714 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
688 deoptimizations_.Add(environment, environment->zone()); | 715 deoptimizations_.Add(environment, environment->zone()); |
689 } | 716 } |
690 } | 717 } |
691 | 718 |
692 | 719 |
(...skipping 4911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5604 FixedArray::kHeaderSize - kPointerSize)); | 5631 FixedArray::kHeaderSize - kPointerSize)); |
5605 __ bind(&done); | 5632 __ bind(&done); |
5606 } | 5633 } |
5607 | 5634 |
5608 | 5635 |
5609 #undef __ | 5636 #undef __ |
5610 | 5637 |
5611 } } // namespace v8::internal | 5638 } } // namespace v8::internal |
5612 | 5639 |
5613 #endif // V8_TARGET_ARCH_X64 | 5640 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |