Index: src/ia32/deoptimizer-ia32.cc |
diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc |
index 73961e1416deb7654e17845bddde94531d821c01..326207fbc6d8ec5c58e694fad51091b120f5db45 100644 |
--- a/src/ia32/deoptimizer-ia32.cc |
+++ b/src/ia32/deoptimizer-ia32.cc |
@@ -351,10 +351,12 @@ void Deoptimizer::DoComputeOsrOutputFrame() { |
PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", |
reinterpret_cast<intptr_t>(function_)); |
function_->PrintName(); |
- PrintF(" => node=%u, frame=%d->%d]\n", |
+ PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n", |
ast_id, |
input_frame_size, |
- output_frame_size); |
+ output_frame_size, |
+ input_->GetRegister(ebp.code()), |
+ input_->GetRegister(esp.code())); |
} |
// There's only one output frame in the OSR case. |
@@ -404,7 +406,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { |
name = "function"; |
break; |
} |
- PrintF(" [esp + %d] <- 0x%08x ; [esp + %d] (fixed part - %s)\n", |
+ PrintF(" [sp + %d] <- 0x%08x ; [sp + %d] (fixed part - %s)\n", |
output_offset, |
input_value, |
input_offset, |
@@ -415,6 +417,24 @@ void Deoptimizer::DoComputeOsrOutputFrame() { |
output_offset -= kPointerSize; |
} |
+ // All OSR stack frames are dynamically aligned to an 8-byte boundary. |
+ int frame_pointer = input_->GetRegister(ebp.code()); |
+ if ((frame_pointer & kPointerSize) != 0) { |
+ frame_pointer -= kPointerSize; |
+ has_alignment_padding_ = 1; |
+ } |
+ |
+ int32_t alignment_state = (has_alignment_padding_ == 1) ? |
+ kAlignmentPaddingPushed : |
+ kNoAlignmentPadding; |
+ if (FLAG_trace_osr) { |
+ PrintF(" [sp + %d] <- 0x%08x ; (alignment state)\n", |
+ output_offset, |
+ alignment_state); |
+ } |
+ output_[0]->SetFrameSlot(output_offset, alignment_state); |
+ output_offset -= kPointerSize; |
+ |
// Translate the rest of the frame. |
while (ok && input_offset >= 0) { |
ok = DoOsrTranslateCommand(&iterator, &input_offset); |
@@ -427,7 +447,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { |
output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); |
} else { |
// Set up the frame pointer and the context pointer. |
- output_[0]->SetRegister(ebp.code(), input_->GetRegister(ebp.code())); |
+ output_[0]->SetRegister(ebp.code(), frame_pointer); |
output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); |
unsigned pc_offset = data->OsrPcOffset()->value(); |
@@ -688,24 +708,38 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, |
ASSERT(output_[frame_index] == NULL); |
output_[frame_index] = output_frame; |
+ // Compute the incoming parameter translation. |
+ int parameter_count = function->shared()->formal_parameter_count() + 1; |
+ unsigned output_offset = output_frame_size; |
+ unsigned input_offset = input_frame_size; |
+ |
+ unsigned alignment_state_offset = |
+ input_offset - parameter_count * kPointerSize - |
+ StandardFrameConstants::kFixedFrameSize - |
+ kPointerSize; |
+ ASSERT(JavaScriptFrameConstants::kDynamicAlignmentStateOffset == |
+ JavaScriptFrameConstants::kLocal0Offset); |
+ |
// The top address for the bottommost output frame can be computed from |
// the input frame pointer and the output frame's height. For all |
// subsequent output frames, it can be computed from the previous one's |
// top address and the current frame's size. |
uint32_t top_address; |
if (is_bottommost) { |
+ int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset); |
+ has_alignment_padding_ = |
+ (alignment_state == kAlignmentPaddingPushed) ? 1 : 0; |
// 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; |
} |
output_frame->SetTop(top_address); |
- // Compute the incoming parameter translation. |
- int parameter_count = function->shared()->formal_parameter_count() + 1; |
- unsigned output_offset = output_frame_size; |
- unsigned input_offset = input_frame_size; |
for (int i = 0; i < parameter_count; ++i) { |
output_offset -= kPointerSize; |
DoTranslateCommand(iterator, frame_index, output_offset); |
@@ -747,13 +781,17 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, |
} |
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) { |
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", |
fp_value, output_offset, value); |
} |
+ ASSERT(!is_bottommost || !has_alignment_padding_ || |
+ (fp_value & kPointerSize) != 0); |
// For the bottommost output frame the context can be gotten from the input |
// frame. For all subsequent output frames it can be gotten from the function |
@@ -948,6 +986,28 @@ void Deoptimizer::EntryGenerator::Generate() { |
} |
__ pop(eax); |
+ if (type() != OSR) { |
+ // If frame was dynamically aligned, pop padding. |
+ Label no_padding; |
+ __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
+ Immediate(0)); |
+ __ j(equal, &no_padding); |
+ __ pop(ecx); |
+ if (FLAG_debug_code) { |
+ __ cmp(ecx, Immediate(kAlignmentZapValue)); |
+ __ Assert(equal, "alignment marker expected"); |
+ } |
+ __ bind(&no_padding); |
+ } else { |
+ // If frame needs dynamic alignment push padding. |
+ Label no_padding; |
+ __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
+ Immediate(0)); |
+ __ j(equal, &no_padding); |
+ __ push(Immediate(kAlignmentZapValue)); |
+ __ bind(&no_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 |