Index: src/deoptimizer.cc |
diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc |
index 1bf27f17b41bc972846eefce018180b2390e772e..6b77e51ef16b82c21dc63544a2344ae811401bdd 100644 |
--- a/src/deoptimizer.cc |
+++ b/src/deoptimizer.cc |
@@ -820,6 +820,193 @@ void Deoptimizer::DoComputeOutputFrames() { |
} |
+void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, |
+ int frame_index) { |
+ BailoutId node_id = BailoutId(iterator->Next()); |
+ JSFunction* function; |
+ if (frame_index != 0) { |
+ function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
+ } else { |
+ int closure_id = iterator->Next(); |
+ USE(closure_id); |
+ ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
+ function = function_; |
+ } |
+ unsigned height = iterator->Next(); |
+ unsigned height_in_bytes = height * kPointerSize; |
+ if (trace_) { |
+ PrintF(" translating "); |
+ function->PrintName(); |
+ PrintF(" => node=%d, height=%d\n", node_id.ToInt(), height_in_bytes); |
+ } |
+ |
+ // The 'fixed' part of the frame consists of the incoming parameters and |
+ // the part described by JavaScriptFrameConstants. |
+ unsigned fixed_frame_size = ComputeFixedSize(function); |
+ unsigned input_frame_size = input_->GetFrameSize(); |
+ unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
+ |
+ // Allocate and store the output frame description. |
+ FrameDescription* output_frame = |
+ new(output_frame_size) FrameDescription(output_frame_size, function); |
+ output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); |
+ |
+ bool is_bottommost = (0 == frame_index); |
+ bool is_topmost = (output_count_ - 1 == frame_index); |
+ ASSERT(frame_index >= 0 && frame_index < output_count_); |
+ ASSERT(output_[frame_index] == NULL); |
+ output_[frame_index] = output_frame; |
+ |
+ // 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. |
+ Register fp_reg = JavaScriptFrame::fp_register(); |
+ intptr_t top_address; |
+ if (is_bottommost) { |
+ // Determine whether the input frame contains alignment padding. |
+ has_alignment_padding_ = HasAlignmentPadding(function) ? 1 : 0; |
+ // 2 = context and function in the frame. |
+ // 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(fp_reg.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); |
+ } |
+ input_offset -= (parameter_count * kPointerSize); |
+ |
+ // There are no translation commands for the caller's pc and fp, the |
+ // context, and the function. Synthesize their values and set them up |
+ // explicitly. |
+ // |
+ // The caller's pc for the bottommost output frame is the same as in the |
+ // input frame. For all subsequent output frames, it can be read from the |
+ // previous one. This frame's pc can be computed from the non-optimized |
+ // function code and AST id of the bailout. |
+ output_offset -= kPointerSize; |
+ input_offset -= kPointerSize; |
+ intptr_t value; |
+ if (is_bottommost) { |
+ value = input_->GetFrameSlot(input_offset); |
+ } else { |
+ value = output_[frame_index - 1]->GetPc(); |
+ } |
+ output_frame->SetFrameSlot(output_offset, value); |
+ if (trace_) { |
+ PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
+ V8PRIxPTR " ; caller's pc\n", |
+ top_address + output_offset, output_offset, value); |
+ } |
+ |
+ // The caller's frame pointer for the bottommost output frame is the same |
+ // as in the input frame. For all subsequent output frames, it can be |
+ // read from the previous one. Also compute and set this frame's frame |
+ // pointer. |
+ output_offset -= kPointerSize; |
+ input_offset -= kPointerSize; |
+ if (is_bottommost) { |
+ value = input_->GetFrameSlot(input_offset); |
+ } else { |
+ value = output_[frame_index - 1]->GetFp(); |
+ } |
+ output_frame->SetFrameSlot(output_offset, value); |
+ intptr_t fp_value = top_address + output_offset; |
+ ASSERT(!is_bottommost || (input_->GetRegister(fp_reg.code()) + |
+ has_alignment_padding_ * kPointerSize) == fp_value); |
+ output_frame->SetFp(fp_value); |
+ if (is_topmost) output_frame->SetRegister(fp_reg.code(), fp_value); |
+ if (trace_) { |
+ PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
+ V8PRIxPTR " ; 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 |
+ // so long as we don't inline functions that need local contexts. |
+ Register context_reg = JavaScriptFrame::context_register(); |
+ output_offset -= kPointerSize; |
+ input_offset -= kPointerSize; |
+ if (is_bottommost) { |
+ value = input_->GetFrameSlot(input_offset); |
+ } else { |
+ value = reinterpret_cast<intptr_t>(function->context()); |
+ } |
+ output_frame->SetFrameSlot(output_offset, value); |
+ output_frame->SetContext(value); |
+ if (is_topmost) output_frame->SetRegister(context_reg.code(), value); |
+ if (trace_) { |
+ PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
+ V8PRIxPTR "; context\n", |
+ top_address + output_offset, output_offset, value); |
+ } |
+ |
+ // The function was mentioned explicitly in the BEGIN_FRAME. |
+ output_offset -= kPointerSize; |
+ input_offset -= kPointerSize; |
+ value = reinterpret_cast<intptr_t>(function); |
+ // The function for the bottommost output frame should also agree with the |
+ // input frame. |
+ ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value); |
+ output_frame->SetFrameSlot(output_offset, value); |
+ if (trace_) { |
+ PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" |
+ V8PRIxPTR "; function\n", |
+ top_address + output_offset, output_offset, value); |
+ } |
+ |
+ // Translate the rest of the frame. |
+ for (unsigned i = 0; i < height; ++i) { |
+ output_offset -= kPointerSize; |
+ DoTranslateCommand(iterator, frame_index, output_offset); |
+ } |
+ ASSERT(0 == output_offset); |
+ |
+ // Compute this frame's PC, state, and continuation. |
+ Code* non_optimized_code = function->shared()->code(); |
+ FixedArray* raw_data = non_optimized_code->deoptimization_data(); |
+ DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); |
+ Address start = non_optimized_code->instruction_start(); |
+ unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); |
+ unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); |
+ intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); |
+ output_frame->SetPc(pc_value); |
+ |
+ FullCodeGenerator::State state = |
+ FullCodeGenerator::StateField::decode(pc_and_state); |
+ output_frame->SetState(Smi::FromInt(state)); |
+ |
+ // Set the continuation for the topmost frame. |
+ if (is_topmost && bailout_type_ != DEBUGGER) { |
+ Builtins* builtins = isolate_->builtins(); |
+ Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized); |
+ if (bailout_type_ == LAZY) { |
+ continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
+ } else if (bailout_type_ == SOFT) { |
+ continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized); |
+ } else { |
+ ASSERT(bailout_type_ == EAGER); |
+ } |
+ output_frame->SetContinuation( |
+ reinterpret_cast<intptr_t>(continuation->entry())); |
+ } |
+} |
+ |
+ |
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, |
int frame_index) { |
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |