From 80da843e229a29179c4f0c87f1cc6da2ec57dbe1 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Fri, 17 May 2013 08:27:56 +0000 Subject: [PATCH] Unify deoptimizer for JavaScript frames. This unifies the translation of an optimized frame to a full JavaScript frame. Only the frame's context and fp register as well as alignment padding are different on each architecture and can be factored out. R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/14843020 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14715 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/deoptimizer-arm.cc | 188 ++------------------------------------- src/arm/frames-arm.cc | 4 + src/deoptimizer.cc | 187 +++++++++++++++++++++++++++++++++++++++ src/deoptimizer.h | 4 + src/frames.h | 4 + src/ia32/deoptimizer-ia32.cc | 205 +++---------------------------------------- src/ia32/frames-ia32.cc | 4 + src/x64/deoptimizer-x64.cc | 183 ++------------------------------------ src/x64/frames-x64.cc | 4 + 9 files changed, 233 insertions(+), 550 deletions(-) diff --git a/src/arm/deoptimizer-arm.cc b/src/arm/deoptimizer-arm.cc index 374be35..d973889 100644 --- a/src/arm/deoptimizer-arm.cc +++ b/src/arm/deoptimizer-arm.cc @@ -376,188 +376,6 @@ void Deoptimizer::DoComputeOsrOutputFrame() { } -// This code is very similar to ia32 code, but relies on register names (fp, sp) -// and how the frame is laid out. -void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, - int frame_index) { - // Read the ast node id, function, and frame height for this output frame. - 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. - uint32_t top_address; - if (is_bottommost) { - // 2 = context and function in the frame. - top_address = - input_->GetRegister(fp.code()) - (2 * kPointerSize) - height_in_bytes; - } 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%08x: [top + %d] <- 0x%08x ; 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.code()) == fp_value); - output_frame->SetFp(fp_value); - if (is_topmost) { - output_frame->SetRegister(fp.code(), fp_value); - } - if (trace_) { - PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", - fp_value, output_offset, value); - } - - // 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. - output_offset -= kPointerSize; - input_offset -= kPointerSize; - if (is_bottommost) { - value = input_->GetFrameSlot(input_offset); - } else { - value = reinterpret_cast(function->context()); - } - output_frame->SetFrameSlot(output_offset, value); - output_frame->SetContext(value); - if (is_topmost) output_frame->SetRegister(cp.code(), value); - if (trace_) { - PrintF(" 0x%08x: [top + %d] <- 0x%08x ; 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(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%08x: [top + %d] <- 0x%08x ; 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); - uint32_t pc_value = reinterpret_cast(start + pc_offset); - output_frame->SetPc(pc_value); - if (is_topmost) { - output_frame->SetRegister(pc.code(), 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(continuation->entry())); - } -} - - void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { // Set the register values. The values are not important as there are no // callee saved registers in JavaScript frames, so all registers are @@ -601,6 +419,12 @@ void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { } +bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { + // There is no dynamic alignment padding on ARM in the input frame. + return false; +} + + #define __ masm()-> // This code tries to be close to ia32 code so that any changes can be diff --git a/src/arm/frames-arm.cc b/src/arm/frames-arm.cc index 5cbe77a..f5a7dbd 100644 --- a/src/arm/frames-arm.cc +++ b/src/arm/frames-arm.cc @@ -45,6 +45,10 @@ Address ExitFrame::ComputeStackPointer(Address fp) { } +Register JavaScriptFrame::fp_register() { return v8::internal::fp; } +Register JavaScriptFrame::context_register() { return cp; } + + Register StubFailureTrampolineFrame::fp_register() { return v8::internal::fp; } Register StubFailureTrampolineFrame::context_register() { return cp; } diff --git a/src/deoptimizer.cc b/src/deoptimizer.cc index 50967ca..26410e9 100644 --- a/src/deoptimizer.cc +++ b/src/deoptimizer.cc @@ -808,6 +808,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(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(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(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(continuation->entry())); + } +} + + void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, int frame_index) { JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); diff --git a/src/deoptimizer.h b/src/deoptimizer.h index ecae9e5..c1b3a9d 100644 --- a/src/deoptimizer.h +++ b/src/deoptimizer.h @@ -406,6 +406,10 @@ class Deoptimizer : public Malloced { // from the input frame's double registers. void CopyDoubleRegisters(FrameDescription* output_frame); + // Determines whether the input frame contains alignment padding by looking + // at the dynamic alignment state slot inside the frame. + bool HasAlignmentPadding(JSFunction* function); + Isolate* isolate_; JSFunction* function_; Code* compiled_code_; diff --git a/src/frames.h b/src/frames.h index 3c44f5e..f09c24a 100644 --- a/src/frames.h +++ b/src/frames.h @@ -584,6 +584,10 @@ class JavaScriptFrame: public StandardFrame { // Build a list with summaries for this frame including all inlined frames. virtual void Summarize(List* frames); + // Architecture-specific register description. + static Register fp_register(); + static Register context_register(); + static JavaScriptFrame* cast(StackFrame* frame) { ASSERT(frame->is_java_script()); return static_cast(frame); diff --git a/src/ia32/deoptimizer-ia32.cc b/src/ia32/deoptimizer-ia32.cc index cb38e25..9f3c4e9 100644 --- a/src/ia32/deoptimizer-ia32.cc +++ b/src/ia32/deoptimizer-ia32.cc @@ -482,197 +482,6 @@ void Deoptimizer::DoComputeOsrOutputFrame() { } -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; - - // 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. - // 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); - - 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%08x: [top + %d] <- 0x%08x ; 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(ebp.code()) + has_alignment_padding_ * kPointerSize) == - fp_value); - output_frame->SetFp(fp_value); - if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value); - if (trace_) { - 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 - // so long as we don't inline functions that need local contexts. - output_offset -= kPointerSize; - input_offset -= kPointerSize; - if (is_bottommost) { - value = input_->GetFrameSlot(input_offset); - } else { - value = reinterpret_cast(function->context()); - } - output_frame->SetFrameSlot(output_offset, value); - output_frame->SetContext(value); - if (is_topmost) output_frame->SetRegister(esi.code(), value); - if (trace_) { - PrintF(" 0x%08x: [top + %d] <- 0x%08x ; 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(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%08x: [top + %d] <- 0x%08x ; 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); - uint32_t pc_value = reinterpret_cast(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(continuation->entry())); - } -} - - void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { // Set the register values. The values are not important as there are no // callee saved registers in JavaScript frames, so all registers are @@ -715,6 +524,20 @@ void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { } +bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { + int parameter_count = function->shared()->formal_parameter_count() + 1; + unsigned input_frame_size = input_->GetFrameSize(); + unsigned alignment_state_offset = + input_frame_size - parameter_count * kPointerSize - + StandardFrameConstants::kFixedFrameSize - + kPointerSize; + ASSERT(JavaScriptFrameConstants::kDynamicAlignmentStateOffset == + JavaScriptFrameConstants::kLocal0Offset); + int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset); + return (alignment_state == kAlignmentPaddingPushed); +} + + #define __ masm()-> void Deoptimizer::EntryGenerator::Generate() { diff --git a/src/ia32/frames-ia32.cc b/src/ia32/frames-ia32.cc index 4932fa3..ea19e9f 100644 --- a/src/ia32/frames-ia32.cc +++ b/src/ia32/frames-ia32.cc @@ -43,6 +43,10 @@ Address ExitFrame::ComputeStackPointer(Address fp) { } +Register JavaScriptFrame::fp_register() { return ebp; } +Register JavaScriptFrame::context_register() { return esi; } + + Register StubFailureTrampolineFrame::fp_register() { return ebp; } Register StubFailureTrampolineFrame::context_register() { return esi; } diff --git a/src/x64/deoptimizer-x64.cc b/src/x64/deoptimizer-x64.cc index 4fdc7f9..a579f52 100644 --- a/src/x64/deoptimizer-x64.cc +++ b/src/x64/deoptimizer-x64.cc @@ -368,183 +368,6 @@ void Deoptimizer::DoComputeOsrOutputFrame() { } -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. - intptr_t top_address; - if (is_bottommost) { - // 2 = context and function in the frame. - top_address = - input_->GetRegister(rbp.code()) - (2 * kPointerSize) - height_in_bytes; - } 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(rbp.code()) == fp_value); - output_frame->SetFp(fp_value); - if (is_topmost) output_frame->SetRegister(rbp.code(), fp_value); - if (trace_) { - PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" - V8PRIxPTR " ; caller's fp\n", - fp_value, output_offset, value); - } - - // 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. - output_offset -= kPointerSize; - input_offset -= kPointerSize; - if (is_bottommost) { - value = input_->GetFrameSlot(input_offset); - } else { - value = reinterpret_cast(function->context()); - } - output_frame->SetFrameSlot(output_offset, value); - output_frame->SetContext(value); - if (is_topmost) output_frame->SetRegister(rsi.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(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(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(continuation->entry())); - } -} - - void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { // Set the register values. The values are not important as there are no // callee saved registers in JavaScript frames, so all registers are @@ -586,6 +409,12 @@ void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) { } +bool Deoptimizer::HasAlignmentPadding(JSFunction* function) { + // There is no dynamic alignment padding on x64 in the input frame. + return false; +} + + #define __ masm()-> void Deoptimizer::EntryGenerator::Generate() { diff --git a/src/x64/frames-x64.cc b/src/x64/frames-x64.cc index 1d6adfd..a811a34 100644 --- a/src/x64/frames-x64.cc +++ b/src/x64/frames-x64.cc @@ -43,6 +43,10 @@ Address ExitFrame::ComputeStackPointer(Address fp) { } +Register JavaScriptFrame::fp_register() { return rbp; } +Register JavaScriptFrame::context_register() { return rsi; } + + Register StubFailureTrampolineFrame::fp_register() { return rbp; } Register StubFailureTrampolineFrame::context_register() { return rsi; } -- 2.7.4