| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 | 121 |
| 122 // For each return after a safepoint insert a absolute call to the | 122 // For each return after a safepoint insert a absolute call to the |
| 123 // corresponding deoptimization entry, or a short call to an absolute | 123 // corresponding deoptimization entry, or a short call to an absolute |
| 124 // jump if space is short. The absolute jumps are put in a table just | 124 // jump if space is short. The absolute jumps are put in a table just |
| 125 // before the safepoint table (space was allocated there when the Code | 125 // before the safepoint table (space was allocated there when the Code |
| 126 // object was created, if necessary). | 126 // object was created, if necessary). |
| 127 | 127 |
| 128 Address instruction_start = function->code()->instruction_start(); | 128 Address instruction_start = function->code()->instruction_start(); |
| 129 Address jump_table_address = | 129 Address jump_table_address = |
| 130 instruction_start + function->code()->safepoint_table_offset(); | 130 instruction_start + function->code()->safepoint_table_offset(); |
| 131 #ifdef DEBUG |
| 131 Address previous_pc = instruction_start; | 132 Address previous_pc = instruction_start; |
| 133 #endif |
| 132 | 134 |
| 133 SafepointTableDeoptimiztionEntryIterator deoptimizations(function->code()); | 135 SafepointTableDeoptimiztionEntryIterator deoptimizations(function->code()); |
| 134 Address entry_pc = NULL; | 136 Address entry_pc = NULL; |
| 135 | 137 |
| 136 SafepointEntry current_entry = deoptimizations.Next(&entry_pc); | 138 SafepointEntry current_entry = deoptimizations.Next(&entry_pc); |
| 137 while (current_entry.is_valid()) { | 139 while (current_entry.is_valid()) { |
| 138 int gap_code_size = current_entry.gap_code_size(); | 140 int gap_code_size = current_entry.gap_code_size(); |
| 139 unsigned deoptimization_index = current_entry.deoptimization_index(); | 141 unsigned deoptimization_index = current_entry.deoptimization_index(); |
| 140 | 142 |
| 141 #ifdef DEBUG | 143 #ifdef DEBUG |
| 142 // Destroy the code which is not supposed to run again. | 144 // Destroy the code which is not supposed to run again. |
| 143 ZapCodeRange(previous_pc, entry_pc); | 145 ZapCodeRange(previous_pc, entry_pc); |
| 144 #endif | 146 #endif |
| 145 // Position where Call will be patched in. | 147 // Position where Call will be patched in. |
| 146 Address call_address = entry_pc + gap_code_size; | 148 Address call_address = entry_pc + gap_code_size; |
| 147 // End of call instruction, if using a direct call to a 64-bit address. | 149 // End of call instruction, if using a direct call to a 64-bit address. |
| 148 Address call_end_address = | 150 Address call_end_address = |
| 149 call_address + MacroAssembler::kCallInstructionLength; | 151 call_address + MacroAssembler::kCallInstructionLength; |
| 150 | 152 |
| 151 // Find next deoptimization entry, if any. | 153 // Find next deoptimization entry, if any. |
| 152 Address next_pc = NULL; | 154 Address next_pc = NULL; |
| 153 SafepointEntry next_entry = deoptimizations.Next(&next_pc); | 155 SafepointEntry next_entry = deoptimizations.Next(&next_pc); |
| 154 | 156 |
| 155 if (!next_entry.is_valid() || next_pc >= call_end_address) { | 157 if (!next_entry.is_valid() || next_pc >= call_end_address) { |
| 156 // Room enough to write a long call instruction. | 158 // Room enough to write a long call instruction. |
| 157 CodePatcher patcher(call_address, Assembler::kCallInstructionLength); | 159 CodePatcher patcher(call_address, Assembler::kCallInstructionLength); |
| 158 patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY), | 160 patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY), |
| 159 RelocInfo::NONE); | 161 RelocInfo::NONE); |
| 162 #ifdef DEBUG |
| 160 previous_pc = call_end_address; | 163 previous_pc = call_end_address; |
| 164 #endif |
| 161 } else { | 165 } else { |
| 162 // Not room enough for a long Call instruction. Write a short call | 166 // Not room enough for a long Call instruction. Write a short call |
| 163 // instruction to a long jump placed elsewhere in the code. | 167 // instruction to a long jump placed elsewhere in the code. |
| 168 #ifdef DEBUG |
| 164 Address short_call_end_address = | 169 Address short_call_end_address = |
| 165 call_address + MacroAssembler::kShortCallInstructionLength; | 170 call_address + MacroAssembler::kShortCallInstructionLength; |
| 171 #endif |
| 166 ASSERT(next_pc >= short_call_end_address); | 172 ASSERT(next_pc >= short_call_end_address); |
| 167 | 173 |
| 168 // Write jump in jump-table. | 174 // Write jump in jump-table. |
| 169 jump_table_address -= MacroAssembler::kJumpInstructionLength; | 175 jump_table_address -= MacroAssembler::kJumpInstructionLength; |
| 170 CodePatcher jump_patcher(jump_table_address, | 176 CodePatcher jump_patcher(jump_table_address, |
| 171 MacroAssembler::kJumpInstructionLength); | 177 MacroAssembler::kJumpInstructionLength); |
| 172 jump_patcher.masm()->Jump( | 178 jump_patcher.masm()->Jump( |
| 173 GetDeoptimizationEntry(deoptimization_index, LAZY), | 179 GetDeoptimizationEntry(deoptimization_index, LAZY), |
| 174 RelocInfo::NONE); | 180 RelocInfo::NONE); |
| 175 | 181 |
| 176 // Write call to jump at call_offset. | 182 // Write call to jump at call_offset. |
| 177 CodePatcher call_patcher(call_address, | 183 CodePatcher call_patcher(call_address, |
| 178 MacroAssembler::kShortCallInstructionLength); | 184 MacroAssembler::kShortCallInstructionLength); |
| 179 call_patcher.masm()->call(jump_table_address); | 185 call_patcher.masm()->call(jump_table_address); |
| 186 #ifdef DEBUG |
| 180 previous_pc = short_call_end_address; | 187 previous_pc = short_call_end_address; |
| 188 #endif |
| 181 } | 189 } |
| 182 | 190 |
| 183 // Continue with next deoptimization entry. | 191 // Continue with next deoptimization entry. |
| 184 current_entry = next_entry; | 192 current_entry = next_entry; |
| 185 entry_pc = next_pc; | 193 entry_pc = next_pc; |
| 186 } | 194 } |
| 187 | 195 |
| 188 #ifdef DEBUG | 196 #ifdef DEBUG |
| 189 // Destroy the code which is not supposed to run again. | 197 // Destroy the code which is not supposed to run again. |
| 190 ZapCodeRange(previous_pc, jump_table_address); | 198 ZapCodeRange(previous_pc, jump_table_address); |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 | 645 |
| 638 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 646 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
| 639 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 647 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
| 640 int offset = i * kDoubleSize; | 648 int offset = i * kDoubleSize; |
| 641 __ movsd(Operand(rsp, offset), xmm_reg); | 649 __ movsd(Operand(rsp, offset), xmm_reg); |
| 642 } | 650 } |
| 643 | 651 |
| 644 // We push all registers onto the stack, even though we do not need | 652 // We push all registers onto the stack, even though we do not need |
| 645 // to restore all later. | 653 // to restore all later. |
| 646 for (int i = 0; i < kNumberOfRegisters; i++) { | 654 for (int i = 0; i < kNumberOfRegisters; i++) { |
| 647 Register r = Register::toRegister(i); | 655 Register r = Register::from_code(i); |
| 648 __ push(r); | 656 __ push(r); |
| 649 } | 657 } |
| 650 | 658 |
| 651 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + | 659 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + |
| 652 kDoubleRegsSize; | 660 kDoubleRegsSize; |
| 653 | 661 |
| 654 // When calling new_deoptimizer_function we need to pass the last argument | 662 // When calling new_deoptimizer_function we need to pass the last argument |
| 655 // on the stack on windows and in r8 on linux. The remaining arguments are | 663 // on the stack on windows and in r8 on linux. The remaining arguments are |
| 656 // all passed in registers (different ones on linux and windows though). | 664 // all passed in registers (different ones on linux and windows though). |
| 657 | 665 |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 __ push(Operand(rbx, FrameDescription::continuation_offset())); | 803 __ push(Operand(rbx, FrameDescription::continuation_offset())); |
| 796 | 804 |
| 797 // Push the registers from the last output frame. | 805 // Push the registers from the last output frame. |
| 798 for (int i = 0; i < kNumberOfRegisters; i++) { | 806 for (int i = 0; i < kNumberOfRegisters; i++) { |
| 799 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 807 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
| 800 __ push(Operand(rbx, offset)); | 808 __ push(Operand(rbx, offset)); |
| 801 } | 809 } |
| 802 | 810 |
| 803 // Restore the registers from the stack. | 811 // Restore the registers from the stack. |
| 804 for (int i = kNumberOfRegisters - 1; i >= 0 ; i--) { | 812 for (int i = kNumberOfRegisters - 1; i >= 0 ; i--) { |
| 805 Register r = Register::toRegister(i); | 813 Register r = Register::from_code(i); |
| 806 // Do not restore rsp, simply pop the value into the next register | 814 // Do not restore rsp, simply pop the value into the next register |
| 807 // and overwrite this afterwards. | 815 // and overwrite this afterwards. |
| 808 if (r.is(rsp)) { | 816 if (r.is(rsp)) { |
| 809 ASSERT(i > 0); | 817 ASSERT(i > 0); |
| 810 r = Register::toRegister(i - 1); | 818 r = Register::from_code(i - 1); |
| 811 } | 819 } |
| 812 __ pop(r); | 820 __ pop(r); |
| 813 } | 821 } |
| 814 | 822 |
| 815 // Set up the roots register. | 823 // Set up the roots register. |
| 816 __ InitializeRootRegister(); | 824 __ InitializeRootRegister(); |
| 817 __ InitializeSmiConstantRegister(); | 825 __ InitializeSmiConstantRegister(); |
| 818 | 826 |
| 819 // Return to the continuation point. | 827 // Return to the continuation point. |
| 820 __ ret(0); | 828 __ ret(0); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 833 } | 841 } |
| 834 __ bind(&done); | 842 __ bind(&done); |
| 835 } | 843 } |
| 836 | 844 |
| 837 #undef __ | 845 #undef __ |
| 838 | 846 |
| 839 | 847 |
| 840 } } // namespace v8::internal | 848 } } // namespace v8::internal |
| 841 | 849 |
| 842 #endif // V8_TARGET_ARCH_X64 | 850 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |