| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 600 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 output_offset); | 611 output_offset); |
| 612 literal->ShortPrint(); | 612 literal->ShortPrint(); |
| 613 PrintF(" ; literal\n"); | 613 PrintF(" ; literal\n"); |
| 614 } | 614 } |
| 615 intptr_t value = reinterpret_cast<intptr_t>(literal); | 615 intptr_t value = reinterpret_cast<intptr_t>(literal); |
| 616 output_[frame_index]->SetFrameSlot(output_offset, value); | 616 output_[frame_index]->SetFrameSlot(output_offset, value); |
| 617 return; | 617 return; |
| 618 } | 618 } |
| 619 | 619 |
| 620 case Translation::ARGUMENTS_OBJECT: { | 620 case Translation::ARGUMENTS_OBJECT: { |
| 621 // Use the hole value as a sentinel and fill in the arguments object | 621 // Use the arguments marker value as a sentinel and fill in the arguments |
| 622 // after the deoptimized frame is built. | 622 // object after the deoptimized frame is built. |
| 623 ASSERT(frame_index == 0); // Only supported for first frame. | 623 ASSERT(frame_index == 0); // Only supported for first frame. |
| 624 if (FLAG_trace_deopt) { | 624 if (FLAG_trace_deopt) { |
| 625 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", | 625 PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", |
| 626 output_[frame_index]->GetTop() + output_offset, | 626 output_[frame_index]->GetTop() + output_offset, |
| 627 output_offset); | 627 output_offset); |
| 628 Heap::the_hole_value()->ShortPrint(); | 628 Heap::arguments_marker()->ShortPrint(); |
| 629 PrintF(" ; arguments object\n"); | 629 PrintF(" ; arguments object\n"); |
| 630 } | 630 } |
| 631 intptr_t value = reinterpret_cast<intptr_t>(Heap::the_hole_value()); | 631 intptr_t value = reinterpret_cast<intptr_t>(Heap::arguments_marker()); |
| 632 output_[frame_index]->SetFrameSlot(output_offset, value); | 632 output_[frame_index]->SetFrameSlot(output_offset, value); |
| 633 return; | 633 return; |
| 634 } | 634 } |
| 635 } | 635 } |
| 636 } | 636 } |
| 637 | 637 |
| 638 | 638 |
| 639 bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, | 639 bool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, |
| 640 int* input_offset) { | 640 int* input_offset) { |
| 641 disasm::NameConverter converter; | 641 disasm::NameConverter converter; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 656 switch (opcode) { | 656 switch (opcode) { |
| 657 case Translation::BEGIN: | 657 case Translation::BEGIN: |
| 658 case Translation::FRAME: | 658 case Translation::FRAME: |
| 659 case Translation::DUPLICATE: | 659 case Translation::DUPLICATE: |
| 660 UNREACHABLE(); // Malformed input. | 660 UNREACHABLE(); // Malformed input. |
| 661 return false; | 661 return false; |
| 662 | 662 |
| 663 case Translation::REGISTER: { | 663 case Translation::REGISTER: { |
| 664 int output_reg = iterator->Next(); | 664 int output_reg = iterator->Next(); |
| 665 if (FLAG_trace_osr) { | 665 if (FLAG_trace_osr) { |
| 666 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [esp + %d]\n", | 666 PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", |
| 667 converter.NameOfCPURegister(output_reg), | 667 converter.NameOfCPURegister(output_reg), |
| 668 input_value, | 668 input_value, |
| 669 *input_offset); | 669 *input_offset); |
| 670 } | 670 } |
| 671 output->SetRegister(output_reg, input_value); | 671 output->SetRegister(output_reg, input_value); |
| 672 break; | 672 break; |
| 673 } | 673 } |
| 674 | 674 |
| 675 case Translation::INT32_REGISTER: { | 675 case Translation::INT32_REGISTER: { |
| 676 // Abort OSR if we don't have a number. | 676 // Abort OSR if we don't have a number. |
| 677 if (!input_object->IsNumber()) return false; | 677 if (!input_object->IsNumber()) return false; |
| 678 | 678 |
| 679 int output_reg = iterator->Next(); | 679 int output_reg = iterator->Next(); |
| 680 int int32_value = input_object->IsSmi() | 680 int int32_value = input_object->IsSmi() |
| 681 ? Smi::cast(input_object)->value() | 681 ? Smi::cast(input_object)->value() |
| 682 : FastD2I(input_object->Number()); | 682 : FastD2I(input_object->Number()); |
| 683 // Abort the translation if the conversion lost information. | 683 // Abort the translation if the conversion lost information. |
| 684 if (!input_object->IsSmi() && | 684 if (!input_object->IsSmi() && |
| 685 FastI2D(int32_value) != input_object->Number()) { | 685 FastI2D(int32_value) != input_object->Number()) { |
| 686 if (FLAG_trace_osr) { | 686 if (FLAG_trace_osr) { |
| 687 PrintF("**** %g could not be converted to int32 ****\n", | 687 PrintF("**** %g could not be converted to int32 ****\n", |
| 688 input_object->Number()); | 688 input_object->Number()); |
| 689 } | 689 } |
| 690 return false; | 690 return false; |
| 691 } | 691 } |
| 692 if (FLAG_trace_osr) { | 692 if (FLAG_trace_osr) { |
| 693 PrintF(" %s <- %d (int32) ; [esp + %d]\n", | 693 PrintF(" %s <- %d (int32) ; [sp + %d]\n", |
| 694 converter.NameOfCPURegister(output_reg), | 694 converter.NameOfCPURegister(output_reg), |
| 695 int32_value, | 695 int32_value, |
| 696 *input_offset); | 696 *input_offset); |
| 697 } | 697 } |
| 698 output->SetRegister(output_reg, int32_value); | 698 output->SetRegister(output_reg, int32_value); |
| 699 break; | 699 break; |
| 700 } | 700 } |
| 701 | 701 |
| 702 case Translation::DOUBLE_REGISTER: { | 702 case Translation::DOUBLE_REGISTER: { |
| 703 // Abort OSR if we don't have a number. | 703 // Abort OSR if we don't have a number. |
| 704 if (!input_object->IsNumber()) return false; | 704 if (!input_object->IsNumber()) return false; |
| 705 | 705 |
| 706 int output_reg = iterator->Next(); | 706 int output_reg = iterator->Next(); |
| 707 double double_value = input_object->Number(); | 707 double double_value = input_object->Number(); |
| 708 if (FLAG_trace_osr) { | 708 if (FLAG_trace_osr) { |
| 709 PrintF(" %s <- %g (double) ; [esp + %d]\n", | 709 PrintF(" %s <- %g (double) ; [sp + %d]\n", |
| 710 DoubleRegister::AllocationIndexToString(output_reg), | 710 DoubleRegister::AllocationIndexToString(output_reg), |
| 711 double_value, | 711 double_value, |
| 712 *input_offset); | 712 *input_offset); |
| 713 } | 713 } |
| 714 output->SetDoubleRegister(output_reg, double_value); | 714 output->SetDoubleRegister(output_reg, double_value); |
| 715 break; | 715 break; |
| 716 } | 716 } |
| 717 | 717 |
| 718 case Translation::STACK_SLOT: { | 718 case Translation::STACK_SLOT: { |
| 719 int output_index = iterator->Next(); | 719 int output_index = iterator->Next(); |
| 720 unsigned output_offset = | 720 unsigned output_offset = |
| 721 output->GetOffsetFromSlotIndex(this, output_index); | 721 output->GetOffsetFromSlotIndex(this, output_index); |
| 722 if (FLAG_trace_osr) { | 722 if (FLAG_trace_osr) { |
| 723 PrintF(" [esp + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d]\n", | 723 PrintF(" [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", |
| 724 output_offset, | 724 output_offset, |
| 725 input_value, | 725 input_value, |
| 726 *input_offset); | 726 *input_offset); |
| 727 } | 727 } |
| 728 output->SetFrameSlot(output_offset, input_value); | 728 output->SetFrameSlot(output_offset, input_value); |
| 729 break; | 729 break; |
| 730 } | 730 } |
| 731 | 731 |
| 732 case Translation::INT32_STACK_SLOT: { | 732 case Translation::INT32_STACK_SLOT: { |
| 733 // Abort OSR if we don't have a number. | 733 // Abort OSR if we don't have a number. |
| 734 if (!input_object->IsNumber()) return false; | 734 if (!input_object->IsNumber()) return false; |
| 735 | 735 |
| 736 int output_index = iterator->Next(); | 736 int output_index = iterator->Next(); |
| 737 unsigned output_offset = | 737 unsigned output_offset = |
| 738 output->GetOffsetFromSlotIndex(this, output_index); | 738 output->GetOffsetFromSlotIndex(this, output_index); |
| 739 int int32_value = input_object->IsSmi() | 739 int int32_value = input_object->IsSmi() |
| 740 ? Smi::cast(input_object)->value() | 740 ? Smi::cast(input_object)->value() |
| 741 : DoubleToInt32(input_object->Number()); | 741 : DoubleToInt32(input_object->Number()); |
| 742 // Abort the translation if the conversion lost information. | 742 // Abort the translation if the conversion lost information. |
| 743 if (!input_object->IsSmi() && | 743 if (!input_object->IsSmi() && |
| 744 FastI2D(int32_value) != input_object->Number()) { | 744 FastI2D(int32_value) != input_object->Number()) { |
| 745 if (FLAG_trace_osr) { | 745 if (FLAG_trace_osr) { |
| 746 PrintF("**** %g could not be converted to int32 ****\n", | 746 PrintF("**** %g could not be converted to int32 ****\n", |
| 747 input_object->Number()); | 747 input_object->Number()); |
| 748 } | 748 } |
| 749 return false; | 749 return false; |
| 750 } | 750 } |
| 751 if (FLAG_trace_osr) { | 751 if (FLAG_trace_osr) { |
| 752 PrintF(" [esp + %d] <- %d (int32) ; [esp + %d]\n", | 752 PrintF(" [sp + %d] <- %d (int32) ; [sp + %d]\n", |
| 753 output_offset, | 753 output_offset, |
| 754 int32_value, | 754 int32_value, |
| 755 *input_offset); | 755 *input_offset); |
| 756 } | 756 } |
| 757 output->SetFrameSlot(output_offset, int32_value); | 757 output->SetFrameSlot(output_offset, int32_value); |
| 758 break; | 758 break; |
| 759 } | 759 } |
| 760 | 760 |
| 761 case Translation::DOUBLE_STACK_SLOT: { | 761 case Translation::DOUBLE_STACK_SLOT: { |
| 762 static const int kLowerOffset = 0 * kPointerSize; | 762 static const int kLowerOffset = 0 * kPointerSize; |
| 763 static const int kUpperOffset = 1 * kPointerSize; | 763 static const int kUpperOffset = 1 * kPointerSize; |
| 764 | 764 |
| 765 // Abort OSR if we don't have a number. | 765 // Abort OSR if we don't have a number. |
| 766 if (!input_object->IsNumber()) return false; | 766 if (!input_object->IsNumber()) return false; |
| 767 | 767 |
| 768 int output_index = iterator->Next(); | 768 int output_index = iterator->Next(); |
| 769 unsigned output_offset = | 769 unsigned output_offset = |
| 770 output->GetOffsetFromSlotIndex(this, output_index); | 770 output->GetOffsetFromSlotIndex(this, output_index); |
| 771 double double_value = input_object->Number(); | 771 double double_value = input_object->Number(); |
| 772 uint64_t int_value = BitCast<uint64_t, double>(double_value); | 772 uint64_t int_value = BitCast<uint64_t, double>(double_value); |
| 773 int32_t lower = static_cast<int32_t>(int_value); | 773 int32_t lower = static_cast<int32_t>(int_value); |
| 774 int32_t upper = static_cast<int32_t>(int_value >> kBitsPerInt); | 774 int32_t upper = static_cast<int32_t>(int_value >> kBitsPerInt); |
| 775 if (FLAG_trace_osr) { | 775 if (FLAG_trace_osr) { |
| 776 PrintF(" [esp + %d] <- 0x%08x (upper bits of %g) ; [esp + %d]\n", | 776 PrintF(" [sp + %d] <- 0x%08x (upper bits of %g) ; [sp + %d]\n", |
| 777 output_offset + kUpperOffset, | 777 output_offset + kUpperOffset, |
| 778 upper, | 778 upper, |
| 779 double_value, | 779 double_value, |
| 780 *input_offset); | 780 *input_offset); |
| 781 PrintF(" [esp + %d] <- 0x%08x (lower bits of %g) ; [esp + %d]\n", | 781 PrintF(" [sp + %d] <- 0x%08x (lower bits of %g) ; [sp + %d]\n", |
| 782 output_offset + kLowerOffset, | 782 output_offset + kLowerOffset, |
| 783 lower, | 783 lower, |
| 784 double_value, | 784 double_value, |
| 785 *input_offset); | 785 *input_offset); |
| 786 } | 786 } |
| 787 output->SetFrameSlot(output_offset + kLowerOffset, lower); | 787 output->SetFrameSlot(output_offset + kLowerOffset, lower); |
| 788 output->SetFrameSlot(output_offset + kUpperOffset, upper); | 788 output->SetFrameSlot(output_offset + kUpperOffset, upper); |
| 789 break; | 789 break; |
| 790 } | 790 } |
| 791 | 791 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 803 UNREACHABLE(); | 803 UNREACHABLE(); |
| 804 return false; | 804 return false; |
| 805 } | 805 } |
| 806 } | 806 } |
| 807 | 807 |
| 808 if (!duplicate) *input_offset -= kPointerSize; | 808 if (!duplicate) *input_offset -= kPointerSize; |
| 809 return true; | 809 return true; |
| 810 } | 810 } |
| 811 | 811 |
| 812 | 812 |
| 813 void Deoptimizer::PatchStackCheckCode(Code* unoptimized_code, |
| 814 Code* check_code, |
| 815 Code* replacement_code) { |
| 816 // Iterate over the stack check table and patch every stack check |
| 817 // call to an unconditional call to the replacement code. |
| 818 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 819 Address stack_check_cursor = unoptimized_code->instruction_start() + |
| 820 unoptimized_code->stack_check_table_offset(); |
| 821 uint32_t table_length = Memory::uint32_at(stack_check_cursor); |
| 822 stack_check_cursor += kIntSize; |
| 823 for (uint32_t i = 0; i < table_length; ++i) { |
| 824 uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize); |
| 825 Address pc_after = unoptimized_code->instruction_start() + pc_offset; |
| 826 PatchStackCheckCodeAt(pc_after, check_code, replacement_code); |
| 827 stack_check_cursor += 2 * kIntSize; |
| 828 } |
| 829 } |
| 830 |
| 831 |
| 832 void Deoptimizer::RevertStackCheckCode(Code* unoptimized_code, |
| 833 Code* check_code, |
| 834 Code* replacement_code) { |
| 835 // Iterate over the stack check table and revert the patched |
| 836 // stack check calls. |
| 837 ASSERT(unoptimized_code->kind() == Code::FUNCTION); |
| 838 Address stack_check_cursor = unoptimized_code->instruction_start() + |
| 839 unoptimized_code->stack_check_table_offset(); |
| 840 uint32_t table_length = Memory::uint32_at(stack_check_cursor); |
| 841 stack_check_cursor += kIntSize; |
| 842 for (uint32_t i = 0; i < table_length; ++i) { |
| 843 uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize); |
| 844 Address pc_after = unoptimized_code->instruction_start() + pc_offset; |
| 845 RevertStackCheckCodeAt(pc_after, check_code, replacement_code); |
| 846 stack_check_cursor += 2 * kIntSize; |
| 847 } |
| 848 } |
| 849 |
| 850 |
| 813 unsigned Deoptimizer::ComputeInputFrameSize() const { | 851 unsigned Deoptimizer::ComputeInputFrameSize() const { |
| 814 unsigned fixed_size = ComputeFixedSize(function_); | 852 unsigned fixed_size = ComputeFixedSize(function_); |
| 815 // The fp-to-sp delta already takes the context and the function | 853 // The fp-to-sp delta already takes the context and the function |
| 816 // into account so we have to avoid double counting them (-2). | 854 // into account so we have to avoid double counting them (-2). |
| 817 unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize); | 855 unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize); |
| 818 #ifdef DEBUG | 856 #ifdef DEBUG |
| 819 if (bailout_type_ == OSR) { | 857 if (bailout_type_ == OSR) { |
| 820 // TODO(kasperl): It would be nice if we could verify that the | 858 // TODO(kasperl): It would be nice if we could verify that the |
| 821 // size matches with the stack height we can compute based on the | 859 // size matches with the stack height we can compute based on the |
| 822 // environment at the OSR entry. The code for that his built into | 860 // environment at the OSR entry. The code for that his built into |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 Deoptimizer::HandleWeakDeoptimizedCode); | 1177 Deoptimizer::HandleWeakDeoptimizedCode); |
| 1140 } | 1178 } |
| 1141 | 1179 |
| 1142 | 1180 |
| 1143 DeoptimizingCodeListNode::~DeoptimizingCodeListNode() { | 1181 DeoptimizingCodeListNode::~DeoptimizingCodeListNode() { |
| 1144 GlobalHandles::Destroy(reinterpret_cast<Object**>(code_.location())); | 1182 GlobalHandles::Destroy(reinterpret_cast<Object**>(code_.location())); |
| 1145 } | 1183 } |
| 1146 | 1184 |
| 1147 | 1185 |
| 1148 } } // namespace v8::internal | 1186 } } // namespace v8::internal |
| OLD | NEW |