Index: src/ia32/deoptimizer-ia32.cc |
=================================================================== |
--- src/ia32/deoptimizer-ia32.cc (revision 9531) |
+++ src/ia32/deoptimizer-ia32.cc (working copy) |
@@ -116,7 +116,7 @@ |
new_reloc->GetDataStartAddress() + padding, 0); |
intptr_t comment_string |
= reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString); |
- RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string); |
+ RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string, NULL); |
for (int i = 0; i < additional_comments; ++i) { |
#ifdef DEBUG |
byte* pos_before = reloc_info_writer.pos(); |
@@ -174,7 +174,8 @@ |
// We use RUNTIME_ENTRY for deoptimization bailouts. |
RelocInfo rinfo(curr_address + 1, // 1 after the call opcode. |
RelocInfo::RUNTIME_ENTRY, |
- reinterpret_cast<intptr_t>(deopt_entry)); |
+ reinterpret_cast<intptr_t>(deopt_entry), |
+ NULL); |
reloc_info_writer.Write(&rinfo); |
ASSERT_GE(reloc_info_writer.pos(), |
reloc_info->address() + ByteArray::kHeaderSize); |
@@ -205,6 +206,11 @@ |
node->set_next(data->deoptimizing_code_list_); |
data->deoptimizing_code_list_ = node; |
+ // We might be in the middle of incremental marking with compaction. |
+ // Tell collector to treat this code object in a special way and |
+ // ignore all slots that might have been recorded on it. |
+ isolate->heap()->mark_compact_collector()->InvalidateCode(code); |
+ |
// Set the code for the function to non-optimized version. |
function->ReplaceCode(function->shared()->code()); |
@@ -221,7 +227,8 @@ |
} |
-void Deoptimizer::PatchStackCheckCodeAt(Address pc_after, |
+void Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code, |
+ Address pc_after, |
Code* check_code, |
Code* replacement_code) { |
Address call_target_address = pc_after - kIntSize; |
@@ -250,6 +257,13 @@ |
*(call_target_address - 2) = 0x90; // nop |
Assembler::set_target_address_at(call_target_address, |
replacement_code->entry()); |
+ |
+ RelocInfo rinfo(call_target_address, |
+ RelocInfo::CODE_TARGET, |
+ 0, |
+ unoptimized_code); |
+ unoptimized_code->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
+ unoptimized_code, &rinfo, replacement_code); |
} |
@@ -268,6 +282,9 @@ |
*(call_target_address - 2) = 0x07; // offset |
Assembler::set_target_address_at(call_target_address, |
check_code->entry()); |
+ |
+ check_code->GetHeap()->incremental_marking()-> |
+ RecordCodeTargetPatch(call_target_address, check_code); |
} |
@@ -415,7 +432,14 @@ |
output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); |
} else { |
// Setup the frame pointer and the context pointer. |
- output_[0]->SetRegister(ebp.code(), input_->GetRegister(ebp.code())); |
+ // All OSR stack frames are dynamically aligned to an 8-byte boundary. |
+ int frame_pointer = input_->GetRegister(ebp.code()); |
+ if ((frame_pointer & 0x4) == 0) { |
+ // Return address at FP + 4 should be aligned, so FP mod 8 should be 4. |
+ frame_pointer -= kPointerSize; |
+ has_alignment_padding_ = 1; |
+ } |
+ output_[0]->SetRegister(ebp.code(), frame_pointer); |
output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); |
unsigned pc_offset = data->OsrPcOffset()->value(); |
@@ -480,9 +504,11 @@ |
// top address and the current frame's size. |
uint32_t top_address; |
if (is_bottommost) { |
- // 2 = context and function in the frame. |
- top_address = |
- input_->GetRegister(ebp.code()) - (2 * kPointerSize) - height_in_bytes; |
+ // If the optimized frame had alignment padding, adjust the frame pointer |
+ // to point to the new position of the old frame pointer after padding |
+ // is removed. Subtract 2 * kPointerSize for the context and function slots. |
+ top_address = input_->GetRegister(ebp.code()) - (2 * kPointerSize) - |
+ height_in_bytes + has_alignment_padding_ * kPointerSize; |
} else { |
top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
} |
@@ -533,7 +559,9 @@ |
} |
output_frame->SetFrameSlot(output_offset, value); |
intptr_t fp_value = top_address + output_offset; |
- ASSERT(!is_bottommost || input_->GetRegister(ebp.code()) == fp_value); |
+ ASSERT(!is_bottommost || |
+ input_->GetRegister(ebp.code()) + has_alignment_padding_ * kPointerSize |
+ == fp_value); |
output_frame->SetFp(fp_value); |
if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value); |
if (FLAG_trace_deopt) { |
@@ -638,7 +666,7 @@ |
const int kDoubleRegsSize = kDoubleSize * |
XMMRegister::kNumAllocatableRegisters; |
- __ sub(Operand(esp), Immediate(kDoubleRegsSize)); |
+ __ sub(esp, Immediate(kDoubleRegsSize)); |
for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
int offset = i * kDoubleSize; |
@@ -662,7 +690,7 @@ |
__ mov(ecx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize)); |
__ lea(edx, Operand(esp, kSavedRegistersAreaSize + 2 * kPointerSize)); |
} |
- __ sub(edx, Operand(ebp)); |
+ __ sub(edx, ebp); |
__ neg(edx); |
// Allocate a new deoptimizer object. |
@@ -675,7 +703,10 @@ |
__ mov(Operand(esp, 4 * kPointerSize), edx); // Fp-to-sp delta. |
__ mov(Operand(esp, 5 * kPointerSize), |
Immediate(ExternalReference::isolate_address())); |
- __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); |
+ { |
+ AllowExternalCallThatCantCauseGC scope(masm()); |
+ __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); |
+ } |
// Preserve deoptimizer object in register eax and get the input |
// frame descriptor pointer. |
@@ -698,15 +729,15 @@ |
// Remove the bailout id and the double registers from the stack. |
if (type() == EAGER) { |
- __ add(Operand(esp), Immediate(kDoubleRegsSize + kPointerSize)); |
+ __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); |
} else { |
- __ add(Operand(esp), Immediate(kDoubleRegsSize + 2 * kPointerSize)); |
+ __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); |
} |
// Compute a pointer to the unwinding limit in register ecx; that is |
// the first stack slot not part of the input frame. |
__ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
- __ add(ecx, Operand(esp)); |
+ __ add(ecx, esp); |
// Unwind the stack down to - but not including - the unwinding |
// limit and copy the contents of the activation frame to the input |
@@ -715,18 +746,43 @@ |
Label pop_loop; |
__ bind(&pop_loop); |
__ pop(Operand(edx, 0)); |
- __ add(Operand(edx), Immediate(sizeof(uint32_t))); |
- __ cmp(ecx, Operand(esp)); |
+ __ add(edx, Immediate(sizeof(uint32_t))); |
+ __ cmp(ecx, esp); |
__ j(not_equal, &pop_loop); |
+ // If frame was dynamically aligned, pop padding. |
+ Label sentinel, sentinel_done; |
+ __ pop(ecx); |
+ __ cmp(ecx, Operand(eax, Deoptimizer::frame_alignment_marker_offset())); |
+ __ j(equal, &sentinel); |
+ __ push(ecx); |
+ __ jmp(&sentinel_done); |
+ __ bind(&sentinel); |
+ __ mov(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
+ Immediate(1)); |
+ __ bind(&sentinel_done); |
// Compute the output frame in the deoptimizer. |
__ push(eax); |
__ PrepareCallCFunction(1, ebx); |
__ mov(Operand(esp, 0 * kPointerSize), eax); |
- __ CallCFunction( |
- ExternalReference::compute_output_frames_function(isolate), 1); |
+ { |
+ AllowExternalCallThatCantCauseGC scope(masm()); |
+ __ CallCFunction( |
+ ExternalReference::compute_output_frames_function(isolate), 1); |
+ } |
__ pop(eax); |
+ if (type() == OSR) { |
+ // If alignment padding is added, push the sentinel. |
+ Label no_osr_padding; |
+ __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
+ Immediate(0)); |
+ __ j(equal, &no_osr_padding, Label::kNear); |
+ __ push(Operand(eax, Deoptimizer::frame_alignment_marker_offset())); |
+ __ bind(&no_osr_padding); |
+ } |
+ |
+ |
// Replace the current frame with the output frames. |
Label outer_push_loop, inner_push_loop; |
// Outer loop state: eax = current FrameDescription**, edx = one past the |
@@ -739,12 +795,12 @@ |
__ mov(ebx, Operand(eax, 0)); |
__ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
__ bind(&inner_push_loop); |
- __ sub(Operand(ecx), Immediate(sizeof(uint32_t))); |
+ __ sub(ecx, Immediate(sizeof(uint32_t))); |
__ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); |
- __ test(ecx, Operand(ecx)); |
+ __ test(ecx, ecx); |
__ j(not_zero, &inner_push_loop); |
- __ add(Operand(eax), Immediate(kPointerSize)); |
- __ cmp(eax, Operand(edx)); |
+ __ add(eax, Immediate(kPointerSize)); |
+ __ cmp(eax, edx); |
__ j(below, &outer_push_loop); |
// In case of OSR, we have to restore the XMM registers. |