Commit 75ca3e33 authored by vegorov@chromium.org's avatar vegorov@chromium.org

Reimplement dynamic frame alignment for frames that are compiled via OSR or...

Reimplement dynamic frame alignment for frames that are compiled via OSR or have more than 2 double spill slots.

The first spill slot is now reserved on all optimized frames to distinguish frames that were aligned.

Review URL: https://chromiumcodereview.appspot.com/10532066

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11772 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e6f2eab7
...@@ -1451,7 +1451,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) { ...@@ -1451,7 +1451,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
// Remember source position and frame to handle step next. // Remember source position and frame to handle step next.
thread_local_.last_statement_position_ = thread_local_.last_statement_position_ =
debug_info->code()->SourceStatementPosition(frame->pc()); debug_info->code()->SourceStatementPosition(frame->pc());
thread_local_.last_fp_ = frame->fp(); thread_local_.last_fp_ = frame->UnpaddedFP();
} else { } else {
// If there's restarter frame on top of the stack, just get the pointer // If there's restarter frame on top of the stack, just get the pointer
// to function which is going to be restarted. // to function which is going to be restarted.
...@@ -1520,7 +1520,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) { ...@@ -1520,7 +1520,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
// propagated on the next Debug::Break. // propagated on the next Debug::Break.
thread_local_.last_statement_position_ = thread_local_.last_statement_position_ =
debug_info->code()->SourceStatementPosition(frame->pc()); debug_info->code()->SourceStatementPosition(frame->pc());
thread_local_.last_fp_ = frame->fp(); thread_local_.last_fp_ = frame->UnpaddedFP();
} }
// Step in or Step in min // Step in or Step in min
...@@ -1555,7 +1555,7 @@ bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator, ...@@ -1555,7 +1555,7 @@ bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
// Continue if we are still on the same frame and in the same statement. // Continue if we are still on the same frame and in the same statement.
int current_statement_position = int current_statement_position =
break_location_iterator->code()->SourceStatementPosition(frame->pc()); break_location_iterator->code()->SourceStatementPosition(frame->pc());
return thread_local_.last_fp_ == frame->fp() && return thread_local_.last_fp_ == frame->UnpaddedFP() &&
thread_local_.last_statement_position_ == current_statement_position; thread_local_.last_statement_position_ == current_statement_position;
} }
...@@ -1756,7 +1756,7 @@ void Debug::ClearOneShot() { ...@@ -1756,7 +1756,7 @@ void Debug::ClearOneShot() {
void Debug::ActivateStepIn(StackFrame* frame) { void Debug::ActivateStepIn(StackFrame* frame) {
ASSERT(!StepOutActive()); ASSERT(!StepOutActive());
thread_local_.step_into_fp_ = frame->fp(); thread_local_.step_into_fp_ = frame->UnpaddedFP();
} }
...@@ -1767,7 +1767,7 @@ void Debug::ClearStepIn() { ...@@ -1767,7 +1767,7 @@ void Debug::ClearStepIn() {
void Debug::ActivateStepOut(StackFrame* frame) { void Debug::ActivateStepOut(StackFrame* frame) {
ASSERT(!StepInActive()); ASSERT(!StepInActive());
thread_local_.step_out_fp_ = frame->fp(); thread_local_.step_out_fp_ = frame->UnpaddedFP();
} }
......
...@@ -354,6 +354,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate, ...@@ -354,6 +354,7 @@ Deoptimizer::Deoptimizer(Isolate* isolate,
bailout_type_(type), bailout_type_(type),
from_(from), from_(from),
fp_to_sp_delta_(fp_to_sp_delta), fp_to_sp_delta_(fp_to_sp_delta),
has_alignment_padding_(0),
input_(NULL), input_(NULL),
output_count_(0), output_count_(0),
jsframe_count_(0), jsframe_count_(0),
...@@ -594,12 +595,14 @@ void Deoptimizer::DoComputeOutputFrames() { ...@@ -594,12 +595,14 @@ void Deoptimizer::DoComputeOutputFrames() {
PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ", PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ",
reinterpret_cast<intptr_t>(function)); reinterpret_cast<intptr_t>(function));
function->PrintName(); function->PrintName();
PrintF(" => node=%u, pc=0x%08" V8PRIxPTR ", state=%s, took %0.3f ms]\n", PrintF(" => node=%u, pc=0x%08" V8PRIxPTR ", state=%s, alignment=%s,"
" took %0.3f ms]\n",
node_id, node_id,
output_[index]->GetPc(), output_[index]->GetPc(),
FullCodeGenerator::State2String( FullCodeGenerator::State2String(
static_cast<FullCodeGenerator::State>( static_cast<FullCodeGenerator::State>(
output_[index]->GetState()->value())), output_[index]->GetState()->value())),
has_alignment_padding_ ? "with padding" : "no padding",
ms); ms);
} }
} }
...@@ -770,7 +773,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, ...@@ -770,7 +773,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": ", PrintF(" 0x%08" V8PRIxPTR ": ",
output_[frame_index]->GetTop() + output_offset); output_[frame_index]->GetTop() + output_offset);
PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d] ", PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d] ",
output_offset, output_offset,
input_value, input_value,
input_offset); input_offset);
...@@ -790,7 +793,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, ...@@ -790,7 +793,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": ", PrintF(" 0x%08" V8PRIxPTR ": ",
output_[frame_index]->GetTop() + output_offset); output_[frame_index]->GetTop() + output_offset);
PrintF("[top + %d] <- %" V8PRIdPTR " ; [esp + %d] (%s)\n", PrintF("[top + %d] <- %" V8PRIdPTR " ; [sp + %d] (%s)\n",
output_offset, output_offset,
value, value,
input_offset, input_offset,
...@@ -816,7 +819,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, ...@@ -816,7 +819,7 @@ void Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
input_->GetOffsetFromSlotIndex(input_slot_index); input_->GetOffsetFromSlotIndex(input_slot_index);
double value = input_->GetDoubleFrameSlot(input_offset); double value = input_->GetDoubleFrameSlot(input_offset);
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n", PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [sp + %d]\n",
output_[frame_index]->GetTop() + output_offset, output_[frame_index]->GetTop() + output_offset,
output_offset, output_offset,
value, value,
......
...@@ -221,6 +221,10 @@ class Deoptimizer : public Malloced { ...@@ -221,6 +221,10 @@ class Deoptimizer : public Malloced {
} }
static int output_offset() { return OFFSET_OF(Deoptimizer, output_); } static int output_offset() { return OFFSET_OF(Deoptimizer, output_); }
static int has_alignment_padding_offset() {
return OFFSET_OF(Deoptimizer, has_alignment_padding_);
}
static int GetDeoptimizedCodeCount(Isolate* isolate); static int GetDeoptimizedCodeCount(Isolate* isolate);
static const int kNotDeoptimizationEntry = -1; static const int kNotDeoptimizationEntry = -1;
...@@ -322,6 +326,7 @@ class Deoptimizer : public Malloced { ...@@ -322,6 +326,7 @@ class Deoptimizer : public Malloced {
BailoutType bailout_type_; BailoutType bailout_type_;
Address from_; Address from_;
int fp_to_sp_delta_; int fp_to_sp_delta_;
int has_alignment_padding_;
// Input frame description. // Input frame description.
FrameDescription* input_; FrameDescription* input_;
......
...@@ -469,6 +469,20 @@ StackFrame::Type StackFrame::GetCallerState(State* state) const { ...@@ -469,6 +469,20 @@ StackFrame::Type StackFrame::GetCallerState(State* state) const {
} }
Address StackFrame::UnpaddedFP() const {
#if defined(V8_TARGET_ARCH_IA32) || defined(V8_HOST_ARCH_IA32)
if (!is_optimized()) return fp();
int32_t alignment_state = Memory::int32_at(
fp() + JavaScriptFrameConstants::kDynamicAlignmentStateOffset);
return (alignment_state == kAlignmentPaddingPushed) ?
(fp() + kPointerSize) : fp();
#else
return fp();
#endif
}
Code* EntryFrame::unchecked_code() const { Code* EntryFrame::unchecked_code() const {
return HEAP->raw_unchecked_js_entry_code(); return HEAP->raw_unchecked_js_entry_code();
} }
......
...@@ -206,6 +206,11 @@ class StackFrame BASE_EMBEDDED { ...@@ -206,6 +206,11 @@ class StackFrame BASE_EMBEDDED {
Address fp() const { return state_.fp; } Address fp() const { return state_.fp; }
Address caller_sp() const { return GetCallerStackPointer(); } Address caller_sp() const { return GetCallerStackPointer(); }
// If this frame is optimized and was dynamically aligned return its old
// unaligned frame pointer. When the frame is deoptimized its FP will shift
// up one word and become unaligned.
Address UnpaddedFP() const;
Address pc() const { return *pc_address(); } Address pc() const { return *pc_address(); }
void set_pc(Address pc) { *pc_address() = pc; } void set_pc(Address pc) { *pc_address() = pc; }
......
...@@ -681,7 +681,8 @@ HGraph::HGraph(CompilationInfo* info, Zone* zone) ...@@ -681,7 +681,8 @@ HGraph::HGraph(CompilationInfo* info, Zone* zone)
blocks_(8, zone), blocks_(8, zone),
values_(16, zone), values_(16, zone),
phi_list_(NULL), phi_list_(NULL),
zone_(zone) { zone_(zone),
is_recursive_(false) {
start_environment_ = start_environment_ =
new(zone) HEnvironment(NULL, info->scope(), info->closure(), zone); new(zone) HEnvironment(NULL, info->scope(), info->closure(), zone);
start_environment_->set_ast_id(AstNode::kFunctionEntryId); start_environment_->set_ast_id(AstNode::kFunctionEntryId);
...@@ -6927,6 +6928,11 @@ void HGraphBuilder::VisitCall(Call* expr) { ...@@ -6927,6 +6928,11 @@ void HGraphBuilder::VisitCall(Call* expr) {
return; return;
} }
if (TryInlineCall(expr)) return; if (TryInlineCall(expr)) return;
if (expr->target().is_identical_to(info()->closure())) {
graph()->MarkRecursive();
}
call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(),
argument_count)); argument_count));
} else { } else {
......
...@@ -336,6 +336,14 @@ class HGraph: public ZoneObject { ...@@ -336,6 +336,14 @@ class HGraph: public ZoneObject {
osr_values_.set(values); osr_values_.set(values);
} }
void MarkRecursive() {
is_recursive_ = true;
}
bool is_recursive() const {
return is_recursive_;
}
private: private:
void Postorder(HBasicBlock* block, void Postorder(HBasicBlock* block,
BitVector* visited, BitVector* visited,
...@@ -382,6 +390,8 @@ class HGraph: public ZoneObject { ...@@ -382,6 +390,8 @@ class HGraph: public ZoneObject {
Zone* zone_; Zone* zone_;
bool is_recursive_;
DISALLOW_COPY_AND_ASSIGN(HGraph); DISALLOW_COPY_AND_ASSIGN(HGraph);
}; };
......
...@@ -351,10 +351,12 @@ void Deoptimizer::DoComputeOsrOutputFrame() { ...@@ -351,10 +351,12 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ",
reinterpret_cast<intptr_t>(function_)); reinterpret_cast<intptr_t>(function_));
function_->PrintName(); function_->PrintName();
PrintF(" => node=%u, frame=%d->%d]\n", PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n",
ast_id, ast_id,
input_frame_size, 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. // There's only one output frame in the OSR case.
...@@ -404,7 +406,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { ...@@ -404,7 +406,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
name = "function"; name = "function";
break; 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, output_offset,
input_value, input_value,
input_offset, input_offset,
...@@ -415,6 +417,24 @@ void Deoptimizer::DoComputeOsrOutputFrame() { ...@@ -415,6 +417,24 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
output_offset -= kPointerSize; 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. // Translate the rest of the frame.
while (ok && input_offset >= 0) { while (ok && input_offset >= 0) {
ok = DoOsrTranslateCommand(&iterator, &input_offset); ok = DoOsrTranslateCommand(&iterator, &input_offset);
...@@ -427,7 +447,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() { ...@@ -427,7 +447,7 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); output_[0]->SetPc(reinterpret_cast<uint32_t>(from_));
} else { } else {
// Set up the frame pointer and the context pointer. // 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())); output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code()));
unsigned pc_offset = data->OsrPcOffset()->value(); unsigned pc_offset = data->OsrPcOffset()->value();
...@@ -688,24 +708,38 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, ...@@ -688,24 +708,38 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
ASSERT(output_[frame_index] == NULL); ASSERT(output_[frame_index] == NULL);
output_[frame_index] = output_frame; 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 top address for the bottommost output frame can be computed from
// the input frame pointer and the output frame's height. For all // the input frame pointer and the output frame's height. For all
// subsequent output frames, it can be computed from the previous one's // subsequent output frames, it can be computed from the previous one's
// top address and the current frame's size. // top address and the current frame's size.
uint32_t top_address; uint32_t top_address;
if (is_bottommost) { 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. // 2 = context and function in the frame.
top_address = // If the optimized frame had alignment padding, adjust the frame pointer
input_->GetRegister(ebp.code()) - (2 * kPointerSize) - height_in_bytes; // 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 { } else {
top_address = output_[frame_index - 1]->GetTop() - output_frame_size; top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
} }
output_frame->SetTop(top_address); 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) { for (int i = 0; i < parameter_count; ++i) {
output_offset -= kPointerSize; output_offset -= kPointerSize;
DoTranslateCommand(iterator, frame_index, output_offset); DoTranslateCommand(iterator, frame_index, output_offset);
...@@ -747,13 +781,17 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, ...@@ -747,13 +781,17 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
} }
output_frame->SetFrameSlot(output_offset, value); output_frame->SetFrameSlot(output_offset, value);
intptr_t fp_value = top_address + output_offset; 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); output_frame->SetFp(fp_value);
if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value); if (is_topmost) output_frame->SetRegister(ebp.code(), fp_value);
if (FLAG_trace_deopt) { if (FLAG_trace_deopt) {
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
fp_value, output_offset, value); 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 // 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 // frame. For all subsequent output frames it can be gotten from the function
...@@ -948,6 +986,28 @@ void Deoptimizer::EntryGenerator::Generate() { ...@@ -948,6 +986,28 @@ void Deoptimizer::EntryGenerator::Generate() {
} }
__ pop(eax); __ 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. // Replace the current frame with the output frames.
Label outer_push_loop, inner_push_loop; Label outer_push_loop, inner_push_loop;
// Outer loop state: eax = current FrameDescription**, edx = one past the // Outer loop state: eax = current FrameDescription**, edx = one past the
......
...@@ -53,6 +53,10 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved]; ...@@ -53,6 +53,10 @@ typedef Object* JSCallerSavedBuffer[kNumJSCallerSaved];
// Number of registers for which space is reserved in safepoints. // Number of registers for which space is reserved in safepoints.
const int kNumSafepointRegisters = 8; const int kNumSafepointRegisters = 8;
const int kNoAlignmentPadding = 0;
const int kAlignmentPaddingPushed = 2;
const int kAlignmentZapValue = 0x12345678; // Not heap object tagged.
// ---------------------------------------------------- // ----------------------------------------------------
...@@ -119,6 +123,8 @@ class JavaScriptFrameConstants : public AllStatic { ...@@ -119,6 +123,8 @@ class JavaScriptFrameConstants : public AllStatic {
// Caller SP-relative. // Caller SP-relative.
static const int kParam0Offset = -2 * kPointerSize; static const int kParam0Offset = -2 * kPointerSize;
static const int kReceiverOffset = -1 * kPointerSize; static const int kReceiverOffset = -1 * kPointerSize;
static const int kDynamicAlignmentStateOffset = kLocal0Offset;
}; };
......
...@@ -79,6 +79,10 @@ bool LCodeGen::GenerateCode() { ...@@ -79,6 +79,10 @@ bool LCodeGen::GenerateCode() {
// the frame (that is done in GeneratePrologue). // the frame (that is done in GeneratePrologue).
FrameScope frame_scope(masm_, StackFrame::MANUAL); FrameScope frame_scope(masm_, StackFrame::MANUAL);
dynamic_frame_alignment_ = (chunk()->num_double_slots() > 2 &&
!chunk()->graph()->is_recursive()) ||
info()->osr_ast_id() != AstNode::kNoNumber;
return GeneratePrologue() && return GeneratePrologue() &&
GenerateBody() && GenerateBody() &&
GenerateDeferredCode() && GenerateDeferredCode() &&
...@@ -153,14 +157,52 @@ bool LCodeGen::GeneratePrologue() { ...@@ -153,14 +157,52 @@ bool LCodeGen::GeneratePrologue() {
__ bind(&ok); __ bind(&ok);
} }
if (dynamic_frame_alignment_) {
// Move state of dynamic frame alignment into edx.
__ mov(edx, Immediate(kNoAlignmentPadding));
Label do_not_pad, align_loop;
STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
// Align esp + 4 to a multiple of 2 * kPointerSize.
__ test(esp, Immediate(kPointerSize));
__ j(not_zero, &do_not_pad, Label::kNear);
__ push(Immediate(0));
__ mov(ebx, esp);
__ mov(edx, Immediate(kAlignmentPaddingPushed));
// Copy arguments, receiver, and return address.
__ mov(ecx, Immediate(scope()->num_parameters() + 2));
__ bind(&align_loop);
__ mov(eax, Operand(ebx, 1 * kPointerSize));
__ mov(Operand(ebx, 0), eax);
__ add(Operand(ebx), Immediate(kPointerSize));
__ dec(ecx);
__ j(not_zero, &align_loop, Label::kNear);
__ mov(Operand(ebx, 0), Immediate(kAlignmentZapValue));
__ bind(&do_not_pad);
}
__ push(ebp); // Caller's frame pointer. __ push(ebp); // Caller's frame pointer.
__ mov(ebp, esp); __ mov(ebp, esp);
__ push(esi); // Callee's context. __ push(esi); // Callee's context.
__ push(edi); // Callee's JS function. __ push(edi); // Callee's JS function.
if (dynamic_frame_alignment_ && FLAG_debug_code) {
__ test(esp, Immediate(kPointerSize));
__ Assert(zero, "frame is expected to be aligned");
}
// Reserve space for the stack slots needed by the code. // Reserve space for the stack slots needed by the code.
int slots = GetStackSlotCount(); int slots = GetStackSlotCount();
if (slots > 0) { ASSERT_GE(slots, 1);
if (slots == 1) {
if (dynamic_frame_alignment_) {
__ push(edx);
} else {
__ push(Immediate(kNoAlignmentPadding));
}
} else {
if (FLAG_debug_code) { if (FLAG_debug_code) {
__ mov(Operand(eax), Immediate(slots)); __ mov(Operand(eax), Immediate(slots));
Label loop; Label loop;
...@@ -170,7 +212,7 @@ bool LCodeGen::GeneratePrologue() { ...@@ -170,7 +212,7 @@ bool LCodeGen::GeneratePrologue() {
__ j(not_zero, &loop); __ j(not_zero, &loop);
} else { } else {
__ sub(Operand(esp), Immediate(slots * kPointerSize)); __ sub(Operand(esp), Immediate(slots * kPointerSize));
#ifdef _MSC_VER #ifdef _MSC_VER
// On windows, you may not access the stack more than one page below // On windows, you may not access the stack more than one page below
// the most recently mapped page. To make the allocated area randomly // the most recently mapped page. To make the allocated area randomly
// accessible, we write to each page in turn (the value is irrelevant). // accessible, we write to each page in turn (the value is irrelevant).
...@@ -180,7 +222,18 @@ bool LCodeGen::GeneratePrologue() { ...@@ -180,7 +222,18 @@ bool LCodeGen::GeneratePrologue() {
offset -= kPageSize) { offset -= kPageSize) {
__ mov(Operand(esp, offset), eax); __ mov(Operand(esp, offset), eax);
} }
#endif #endif
}
// Store dynamic frame alignment state in the first local.
if (dynamic_frame_alignment_) {
__ mov(Operand(ebp,
JavaScriptFrameConstants::kDynamicAlignmentStateOffset),
edx);
} else {
__ mov(Operand(ebp,
JavaScriptFrameConstants::kDynamicAlignmentStateOffset),
Immediate(kNoAlignmentPadding));
} }
} }
...@@ -2101,8 +2154,25 @@ void LCodeGen::DoReturn(LReturn* instr) { ...@@ -2101,8 +2154,25 @@ void LCodeGen::DoReturn(LReturn* instr) {
__ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
__ CallRuntime(Runtime::kTraceExit, 1); __ CallRuntime(Runtime::kTraceExit, 1);
} }
if (dynamic_frame_alignment_) {
// Fetch the state of the dynamic frame alignment.
__ mov(edx, Operand(ebp,
JavaScriptFrameConstants::kDynamicAlignmentStateOffset));
}
__ mov(esp, ebp); __ mov(esp, ebp);
__ pop(ebp); __ pop(ebp);
if (dynamic_frame_alignment_) {
Label no_padding;
__ cmp(edx, Immediate(kNoAlignmentPadding));
__ j(equal, &no_padding);
if (FLAG_debug_code) {
__ cmp(Operand(esp, (GetParameterCount() + 2) * kPointerSize),
Immediate(kAlignmentZapValue));
__ Assert(equal, "expected alignment marker");
}
__ Ret((GetParameterCount() + 2) * kPointerSize, ecx);
__ bind(&no_padding);
}
__ Ret((GetParameterCount() + 1) * kPointerSize, ecx); __ Ret((GetParameterCount() + 1) * kPointerSize, ecx);
} }
......
...@@ -61,6 +61,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -61,6 +61,7 @@ class LCodeGen BASE_EMBEDDED {
status_(UNUSED), status_(UNUSED),
translations_(zone), translations_(zone),
deferred_(8, zone), deferred_(8, zone),
dynamic_frame_alignment_(false),
osr_pc_offset_(-1), osr_pc_offset_(-1),
last_lazy_deopt_pc_(0), last_lazy_deopt_pc_(0),
safepoints_(zone), safepoints_(zone),
...@@ -342,6 +343,7 @@ class LCodeGen BASE_EMBEDDED { ...@@ -342,6 +343,7 @@ class LCodeGen BASE_EMBEDDED {
Status status_; Status status_;
TranslationBuffer translations_; TranslationBuffer translations_;
ZoneList<LDeferredCode*> deferred_; ZoneList<LDeferredCode*> deferred_;
bool dynamic_frame_alignment_;
int osr_pc_offset_; int osr_pc_offset_;
int last_lazy_deopt_pc_; int last_lazy_deopt_pc_;
......
...@@ -368,7 +368,11 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { ...@@ -368,7 +368,11 @@ void LAccessArgumentsAt::PrintDataTo(StringStream* stream) {
int LChunk::GetNextSpillIndex(bool is_double) { int LChunk::GetNextSpillIndex(bool is_double) {
// Skip a slot if for a double-width slot. // Skip a slot if for a double-width slot.
if (is_double) spill_slot_count_++; if (is_double) {
spill_slot_count_++;
spill_slot_count_ |= 1;
num_double_slots_++;
}
return spill_slot_count_++; return spill_slot_count_++;
} }
...@@ -550,6 +554,12 @@ LChunk* LChunkBuilder::Build() { ...@@ -550,6 +554,12 @@ LChunk* LChunkBuilder::Build() {
chunk_ = new(zone()) LChunk(info(), graph()); chunk_ = new(zone()) LChunk(info(), graph());
HPhase phase("L_Building chunk", chunk_); HPhase phase("L_Building chunk", chunk_);
status_ = BUILDING; status_ = BUILDING;
// Reserve the first spill slot for the state of dynamic alignment.
int alignment_state_index = chunk_->GetNextSpillIndex(false);
ASSERT_EQ(alignment_state_index, 0);
USE(alignment_state_index);
const ZoneList<HBasicBlock*>* blocks = graph()->blocks(); const ZoneList<HBasicBlock*>* blocks = graph()->blocks();
for (int i = 0; i < blocks->length(); i++) { for (int i = 0; i < blocks->length(); i++) {
HBasicBlock* next = NULL; HBasicBlock* next = NULL;
......
...@@ -2307,6 +2307,7 @@ class LChunk: public ZoneObject { ...@@ -2307,6 +2307,7 @@ class LChunk: public ZoneObject {
public: public:
LChunk(CompilationInfo* info, HGraph* graph) LChunk(CompilationInfo* info, HGraph* graph)
: spill_slot_count_(0), : spill_slot_count_(0),
num_double_slots_(0),
info_(info), info_(info),
graph_(graph), graph_(graph),
instructions_(32, graph->zone()), instructions_(32, graph->zone()),
...@@ -2324,6 +2325,7 @@ class LChunk: public ZoneObject { ...@@ -2324,6 +2325,7 @@ class LChunk: public ZoneObject {
int ParameterAt(int index); int ParameterAt(int index);
int GetParameterStackSlot(int index) const; int GetParameterStackSlot(int index) const;
int spill_slot_count() const { return spill_slot_count_; } int spill_slot_count() const { return spill_slot_count_; }
int num_double_slots() const { return num_double_slots_; }
CompilationInfo* info() const { return info_; } CompilationInfo* info() const { return info_; }
HGraph* graph() const { return graph_; } HGraph* graph() const { return graph_; }
const ZoneList<LInstruction*>* instructions() const { return &instructions_; } const ZoneList<LInstruction*>* instructions() const { return &instructions_; }
...@@ -2363,6 +2365,7 @@ class LChunk: public ZoneObject { ...@@ -2363,6 +2365,7 @@ class LChunk: public ZoneObject {
private: private:
int spill_slot_count_; int spill_slot_count_;
int num_double_slots_;
CompilationInfo* info_; CompilationInfo* info_;
HGraph* const graph_; HGraph* const graph_;
ZoneList<LInstruction*> instructions_; ZoneList<LInstruction*> instructions_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment