Index: src/x64/deoptimizer-x64.cc |
diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc |
index 1f7c1ef60627a7cf064a671ba006340cd05d48eb..e058c2e49c19aa7d252e5c7821f137a45ed2250d 100644 |
--- a/src/x64/deoptimizer-x64.cc |
+++ b/src/x64/deoptimizer-x64.cc |
@@ -53,7 +53,9 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
code->InvalidateRelocation(); |
// For each return after a safepoint insert a absolute call to the |
- // corresponding deoptimization entry. |
+ // corresponding deoptimization entry, or a short call to an absolute |
+ // jump if space is short. |
+ unsigned jump_table = function->code()->safepoint_table_start(); |
unsigned last_pc_offset = 0; |
SafepointTable table(function->code()); |
for (unsigned i = 0; i < table.length(); i++) { |
@@ -63,27 +65,60 @@ void Deoptimizer::DeoptimizeFunction(JSFunction* function) { |
int gap_code_size = safepoint_entry.gap_code_size(); |
#ifdef DEBUG |
// Destroy the code which is not supposed to run again. |
+ CHECK(pc_offset >= last_pc_offset); |
unsigned instructions = pc_offset - last_pc_offset; |
CodePatcher destroyer(code->instruction_start() + last_pc_offset, |
instructions); |
- for (unsigned i = 0; i < instructions; i++) { |
+ while (instructions > 0) { |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
This whole code hunk in #ifdef DEBUG is repeated b
Lasse Reichstein
2011/02/03 14:14:12
Moved int3-writing to function called ZapInstructi
Kevin Millikin (Chromium)
2011/02/04 10:27:29
You can (but I'm not suggesting you do) write it a
|
destroyer.masm()->int3(); |
+ instructions--; |
} |
#endif |
last_pc_offset = pc_offset; |
if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) { |
- CodePatcher patcher( |
- code->instruction_start() + pc_offset + gap_code_size, |
- Assembler::kCallInstructionLength); |
- patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY), |
- RelocInfo::NONE); |
- last_pc_offset += gap_code_size + Assembler::kCallInstructionLength; |
+ int call_length = MacroAssembler::kCallInstructionLength; |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
I find all the code below confusing.
You only rea
Lasse Reichstein
2011/02/03 14:14:12
The code is generally confusing. I have refactored
|
+ // Check if the next entry (if any) is located so close that |
+ // we can't write a long Call sequence. |
+ int end_of_long_call = |
+ pc_offset + gap_code_size + MacroAssembler::kCallInstructionLength; |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
All of the code in this if (deoptimization_index !
|
+ for (unsigned j = i + 1; j < table.length(); j++) { |
+ // Stop if the next entry ends later than the call would. |
+ int next_pc = table.GetPcOffset(j); |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
Call this next_pc_offset of something so it's clea
Lasse Reichstein
2011/02/03 14:14:12
Done.
|
+ if (next_pc >= end_of_long_call) break; |
+ // Only care if the entry is a deoptimization point. |
+ if (table.GetEntry(j).deoptimization_index() != |
+ Safepoint::kNoDeoptimizationIndex) { |
+ call_length = next_pc - (pc_offset + gap_code_size); |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
fits = false;
break;
|
+ break; |
+ } |
+ } |
+ if (call_length >= MacroAssembler::kCallInstructionLength) { |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
if (fits) ...
|
+ CodePatcher patcher( |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
CodePatcher patcher(code->instruction_start() + la
|
+ code->instruction_start() + pc_offset + gap_code_size, |
+ Assembler::kCallInstructionLength); |
+ patcher.masm()->Call(GetDeoptimizationEntry(deoptimization_index, LAZY), |
+ RelocInfo::NONE); |
+ last_pc_offset += gap_code_size + Assembler::kCallInstructionLength; |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
last_pc_offset += Assembler::kCallInstructionLengt
|
+ } else { |
+ jump_table -= MacroAssembler::kJumpInstructionLength; |
+ CodePatcher jump_patcher(code->instruction_start() + jump_table, |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
It probably bears naming
Address jump_address = c
|
+ MacroAssembler::kJumpInstructionLength); |
+ jump_patcher.masm()->Jump( |
+ GetDeoptimizationEntry(deoptimization_index, LAZY), |
+ RelocInfo::NONE); |
+ |
+ CodePatcher call_patcher( |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
CodePatcher call_patcher(code->instruction_start +
Lasse Reichstein
2011/02/03 14:14:12
Fixed.
|
+ code->instruction_start() + pc_offset + gap_code_size, |
+ call_length); |
+ call_patcher.masm()->call(code->instruction_start() + jump_table); |
+ last_pc_offset += gap_code_size + call_patcher.masm()->pc_offset(); |
Kevin Millikin (Chromium)
2011/02/02 13:05:33
last_pc_offset += Assembler::kShortCallLength;
|
+ } |
} |
} |
#ifdef DEBUG |
// Destroy the code which is not supposed to run again. |
- CHECK(code->safepoint_table_start() >= last_pc_offset); |
- unsigned instructions = code->safepoint_table_start() - last_pc_offset; |
+ CHECK(jump_table >= last_pc_offset); |
+ unsigned instructions = jump_table - last_pc_offset; |
CodePatcher destroyer(code->instruction_start() + last_pc_offset, |
instructions); |
for (unsigned i = 0; i < instructions; i++) { |
@@ -384,7 +419,7 @@ void Deoptimizer::EntryGenerator::Generate() { |
__ pop(Operand(rbx, offset)); |
} |
- // Fill in the double input registers. |
+ // Fill in the double input registers. |
int double_regs_offset = FrameDescription::double_registers_offset(); |
for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { |
int dst_offset = i * kDoubleSize + double_regs_offset; |
@@ -398,7 +433,7 @@ void Deoptimizer::EntryGenerator::Generate() { |
__ addq(rsp, Immediate(2 * kPointerSize)); |
} |
- // Compute a pointer to the unwinding limit in register ecx; that is |
+ // Compute a pointer to the unwinding limit in register rcx; that is |
// the first stack slot not part of the input frame. |
__ movq(rcx, Operand(rbx, FrameDescription::frame_size_offset())); |
__ addq(rcx, rsp); |