Unify deoptimizer for accessor and arguments frames.
This unifies the translation of artificial accessor stub and arguments adaptor frames. The frame layout is the same on all architectures and the computation code can be shared. R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/12374044 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13784 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
764e1a0fcf
commit
05f1be1bb3
@ -356,102 +356,6 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
unsigned height = iterator->Next();
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
|
||||
}
|
||||
|
||||
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
|
||||
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::ARGUMENTS_ADAPTOR);
|
||||
|
||||
// Arguments adaptor can not be topmost or bottommost.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous
|
||||
// frame's top and this frame's size.
|
||||
uint32_t top_address;
|
||||
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
// Compute the incoming parameter translation.
|
||||
int parameter_count = height;
|
||||
unsigned output_offset = output_frame_size;
|
||||
for (int i = 0; i < parameter_count; ++i) {
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the context.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t context = reinterpret_cast<intptr_t>(
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
output_frame->SetFrameSlot(output_offset, context);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context (adaptor sentinel)\n",
|
||||
top_address + output_offset, output_offset, context);
|
||||
}
|
||||
|
||||
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(function);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Number of incoming arguments.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
|
||||
top_address + output_offset, output_offset, value, height - 1);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Builtins* builtins = isolate_->builtins();
|
||||
Code* adaptor_trampoline =
|
||||
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
|
||||
uint32_t pc = reinterpret_cast<uint32_t>(
|
||||
adaptor_trampoline->instruction_start() +
|
||||
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
//
|
||||
@ -755,124 +659,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||
int frame_index,
|
||||
bool is_setter_stub_frame) {
|
||||
JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
// The receiver (and the implicit return value, if any) are expected in
|
||||
// registers by the LoadIC/StoreIC, so they don't belong to the output stack
|
||||
// frame. This means that we have to use a height of 0.
|
||||
unsigned height = 0;
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
const char* kind = is_setter_stub_frame ? "setter" : "getter";
|
||||
if (trace_) {
|
||||
PrintF(" translating %s stub => height=%u\n", kind, height_in_bytes);
|
||||
}
|
||||
|
||||
// We need 5 stack entries from StackFrame::INTERNAL (lr, fp, cp, frame type,
|
||||
// code object, see MacroAssembler::EnterFrame). For a setter stub frames we
|
||||
// need one additional entry for the implicit return value, see
|
||||
// StoreStubCompiler::CompileStoreViaSetter.
|
||||
unsigned fixed_frame_entries = 5 + (is_setter_stub_frame ? 1 : 0);
|
||||
unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
|
||||
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, accessor);
|
||||
output_frame->SetFrameType(StackFrame::INTERNAL);
|
||||
|
||||
// A frame for an accessor stub can not be the topmost or bottommost one.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous frame's top and
|
||||
// this frame's size.
|
||||
uint32_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
unsigned output_offset = output_frame_size;
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// The context can be gotten from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetContext();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; context\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the function.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; function (%s sentinel)\n",
|
||||
top_address + output_offset, output_offset, value, kind);
|
||||
}
|
||||
|
||||
// Get Code object from accessor stub.
|
||||
output_offset -= kPointerSize;
|
||||
Builtins::Name name = is_setter_stub_frame ?
|
||||
Builtins::kStoreIC_Setter_ForDeopt :
|
||||
Builtins::kLoadIC_Getter_ForDeopt;
|
||||
Code* accessor_stub = isolate_->builtins()->builtin(name);
|
||||
value = reinterpret_cast<intptr_t>(accessor_stub);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; code object\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Skip receiver.
|
||||
Translation::Opcode opcode =
|
||||
static_cast<Translation::Opcode>(iterator->Next());
|
||||
iterator->Skip(Translation::NumberOfOperandsFor(opcode));
|
||||
|
||||
if (is_setter_stub_frame) {
|
||||
// The implicit return value was part of the artificial setter stub
|
||||
// environment.
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Smi* offset = is_setter_stub_frame ?
|
||||
isolate_->heap()->setter_stub_deopt_pc_offset() :
|
||||
isolate_->heap()->getter_stub_deopt_pc_offset();
|
||||
intptr_t pc = reinterpret_cast<intptr_t>(
|
||||
accessor_stub->instruction_start() + offset->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
// 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,
|
||||
|
@ -821,6 +821,226 @@ void Deoptimizer::DoComputeOutputFrames() {
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
unsigned height = iterator->Next();
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
if (trace_) {
|
||||
PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
|
||||
}
|
||||
|
||||
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
|
||||
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::ARGUMENTS_ADAPTOR);
|
||||
|
||||
// Arguments adaptor can not be topmost or bottommost.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous
|
||||
// frame's top and this frame's size.
|
||||
intptr_t top_address;
|
||||
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
// Compute the incoming parameter translation.
|
||||
int parameter_count = height;
|
||||
unsigned output_offset = output_frame_size;
|
||||
for (int i = 0; i < parameter_count; ++i) {
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the context.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t context = reinterpret_cast<intptr_t>(
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
output_frame->SetFrameSlot(output_offset, context);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; context (adaptor sentinel)\n",
|
||||
top_address + output_offset, output_offset, context);
|
||||
}
|
||||
|
||||
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(function);
|
||||
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);
|
||||
}
|
||||
|
||||
// Number of incoming arguments.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; argc (%d)\n",
|
||||
top_address + output_offset, output_offset, value, height - 1);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Builtins* builtins = isolate_->builtins();
|
||||
Code* adaptor_trampoline =
|
||||
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
|
||||
intptr_t pc_value = reinterpret_cast<intptr_t>(
|
||||
adaptor_trampoline->instruction_start() +
|
||||
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
|
||||
output_frame->SetPc(pc_value);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||
int frame_index,
|
||||
bool is_setter_stub_frame) {
|
||||
JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
// The receiver (and the implicit return value, if any) are expected in
|
||||
// registers by the LoadIC/StoreIC, so they don't belong to the output stack
|
||||
// frame. This means that we have to use a height of 0.
|
||||
unsigned height = 0;
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
const char* kind = is_setter_stub_frame ? "setter" : "getter";
|
||||
if (trace_) {
|
||||
PrintF(" translating %s stub => height=%u\n", kind, height_in_bytes);
|
||||
}
|
||||
|
||||
// We need 1 stack entry for the return address + 4 stack entries from
|
||||
// StackFrame::INTERNAL (FP, context, frame type, code object, see
|
||||
// MacroAssembler::EnterFrame). For a setter stub frame we need one additional
|
||||
// entry for the implicit return value, see
|
||||
// StoreStubCompiler::CompileStoreViaSetter.
|
||||
unsigned fixed_frame_entries = 1 + 4 + (is_setter_stub_frame ? 1 : 0);
|
||||
unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
|
||||
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, accessor);
|
||||
output_frame->SetFrameType(StackFrame::INTERNAL);
|
||||
|
||||
// A frame for an accessor stub can not be the topmost or bottommost one.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous frame's top and
|
||||
// this frame's size.
|
||||
intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
unsigned output_offset = output_frame_size;
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// The context can be gotten from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetContext();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; context\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the function.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; function (%s sentinel)\n",
|
||||
top_address + output_offset, output_offset, value, kind);
|
||||
}
|
||||
|
||||
// Get Code object from accessor stub.
|
||||
output_offset -= kPointerSize;
|
||||
Builtins::Name name = is_setter_stub_frame ?
|
||||
Builtins::kStoreIC_Setter_ForDeopt :
|
||||
Builtins::kLoadIC_Getter_ForDeopt;
|
||||
Code* accessor_stub = isolate_->builtins()->builtin(name);
|
||||
value = reinterpret_cast<intptr_t>(accessor_stub);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; code object\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Skip receiver.
|
||||
Translation::Opcode opcode =
|
||||
static_cast<Translation::Opcode>(iterator->Next());
|
||||
iterator->Skip(Translation::NumberOfOperandsFor(opcode));
|
||||
|
||||
if (is_setter_stub_frame) {
|
||||
// The implicit return value was part of the artificial setter stub
|
||||
// environment.
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Smi* offset = is_setter_stub_frame ?
|
||||
isolate_->heap()->setter_stub_deopt_pc_offset() :
|
||||
isolate_->heap()->getter_stub_deopt_pc_offset();
|
||||
intptr_t pc = reinterpret_cast<intptr_t>(
|
||||
accessor_stub->instruction_start() + offset->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
|
||||
ASSERT_NE(DEBUGGER, bailout_type_);
|
||||
|
||||
|
@ -463,102 +463,6 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
unsigned height = iterator->Next();
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
if (trace_) {
|
||||
PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
|
||||
}
|
||||
|
||||
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
|
||||
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::ARGUMENTS_ADAPTOR);
|
||||
|
||||
// Arguments adaptor can not be topmost or bottommost.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous
|
||||
// frame's top and this frame's size.
|
||||
uint32_t top_address;
|
||||
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
// Compute the incoming parameter translation.
|
||||
int parameter_count = height;
|
||||
unsigned output_offset = output_frame_size;
|
||||
for (int i = 0; i < parameter_count; ++i) {
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the context.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t context = reinterpret_cast<intptr_t>(
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
output_frame->SetFrameSlot(output_offset, context);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context (adaptor sentinel)\n",
|
||||
top_address + output_offset, output_offset, context);
|
||||
}
|
||||
|
||||
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(function);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Number of incoming arguments.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
|
||||
top_address + output_offset, output_offset, value, height - 1);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Builtins* builtins = isolate_->builtins();
|
||||
Code* adaptor_trampoline =
|
||||
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
|
||||
uint32_t pc = reinterpret_cast<uint32_t>(
|
||||
adaptor_trampoline->instruction_start() +
|
||||
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
//
|
||||
@ -852,125 +756,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||
int frame_index,
|
||||
bool is_setter_stub_frame) {
|
||||
JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
// The receiver (and the implicit return value, if any) are expected in
|
||||
// registers by the LoadIC/StoreIC, so they don't belong to the output stack
|
||||
// frame. This means that we have to use a height of 0.
|
||||
unsigned height = 0;
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
const char* kind = is_setter_stub_frame ? "setter" : "getter";
|
||||
if (trace_) {
|
||||
PrintF(" translating %s stub => height=%u\n", kind, height_in_bytes);
|
||||
}
|
||||
|
||||
// We need 1 stack entry for the return address + 4 stack entries from
|
||||
// StackFrame::INTERNAL (FP, context, frame type, code object, see
|
||||
// MacroAssembler::EnterFrame). For a setter stub frame we need one additional
|
||||
// entry for the implicit return value, see
|
||||
// StoreStubCompiler::CompileStoreViaSetter.
|
||||
unsigned fixed_frame_entries = 1 + 4 + (is_setter_stub_frame ? 1 : 0);
|
||||
unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
|
||||
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, accessor);
|
||||
output_frame->SetFrameType(StackFrame::INTERNAL);
|
||||
|
||||
// A frame for an accessor stub can not be the topmost or bottommost one.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous frame's top and
|
||||
// this frame's size.
|
||||
intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
unsigned output_offset = output_frame_size;
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// The context can be gotten from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetContext();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; context\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the function.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; function (%s sentinel)\n",
|
||||
top_address + output_offset, output_offset, value, kind);
|
||||
}
|
||||
|
||||
// Get Code object from accessor stub.
|
||||
output_offset -= kPointerSize;
|
||||
Builtins::Name name = is_setter_stub_frame ?
|
||||
Builtins::kStoreIC_Setter_ForDeopt :
|
||||
Builtins::kLoadIC_Getter_ForDeopt;
|
||||
Code* accessor_stub = isolate_->builtins()->builtin(name);
|
||||
value = reinterpret_cast<intptr_t>(accessor_stub);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; code object\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Skip receiver.
|
||||
Translation::Opcode opcode =
|
||||
static_cast<Translation::Opcode>(iterator->Next());
|
||||
iterator->Skip(Translation::NumberOfOperandsFor(opcode));
|
||||
|
||||
if (is_setter_stub_frame) {
|
||||
// The implicit return value was part of the artificial setter stub
|
||||
// environment.
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Smi* offset = is_setter_stub_frame ?
|
||||
isolate_->heap()->setter_stub_deopt_pc_offset() :
|
||||
isolate_->heap()->getter_stub_deopt_pc_offset();
|
||||
intptr_t pc = reinterpret_cast<intptr_t>(
|
||||
accessor_stub->instruction_start() + offset->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
BailoutId node_id = BailoutId(iterator->Next());
|
||||
|
@ -349,102 +349,6 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
unsigned height = iterator->Next();
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
|
||||
}
|
||||
|
||||
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
|
||||
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::ARGUMENTS_ADAPTOR);
|
||||
|
||||
// Arguments adaptor can not be topmost or bottommost.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous
|
||||
// frame's top and this frame's size.
|
||||
uint32_t top_address;
|
||||
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
// Compute the incoming parameter translation.
|
||||
int parameter_count = height;
|
||||
unsigned output_offset = output_frame_size;
|
||||
for (int i = 0; i < parameter_count; ++i) {
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the context.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t context = reinterpret_cast<intptr_t>(
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
output_frame->SetFrameSlot(output_offset, context);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context (adaptor sentinel)\n",
|
||||
top_address + output_offset, output_offset, context);
|
||||
}
|
||||
|
||||
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(function);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Number of incoming arguments.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (FLAG_trace_deopt) {
|
||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n",
|
||||
top_address + output_offset, output_offset, value, height - 1);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Builtins* builtins = isolate_->builtins();
|
||||
Code* adaptor_trampoline =
|
||||
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
|
||||
uint32_t pc = reinterpret_cast<uint32_t>(
|
||||
adaptor_trampoline->instruction_start() +
|
||||
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
//
|
||||
@ -706,124 +610,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||
int frame_index,
|
||||
bool is_setter_stub_frame) {
|
||||
JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
// The receiver (and the implicit return value, if any) are expected in
|
||||
// registers by the LoadIC/StoreIC, so they don't belong to the output stack
|
||||
// frame. This means that we have to use a height of 0.
|
||||
unsigned height = 0;
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
const char* kind = is_setter_stub_frame ? "setter" : "getter";
|
||||
if (trace_) {
|
||||
PrintF(" translating %s stub => height=%u\n", kind, height_in_bytes);
|
||||
}
|
||||
|
||||
// We need 5 stack entries from StackFrame::INTERNAL (ra, fp, cp, frame type,
|
||||
// code object, see MacroAssembler::EnterFrame). For a setter stub frame we
|
||||
// need one additional entry for the implicit return value, see
|
||||
// StoreStubCompiler::CompileStoreViaSetter.
|
||||
unsigned fixed_frame_entries = 5 + (is_setter_stub_frame ? 1 : 0);
|
||||
unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
|
||||
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, accessor);
|
||||
output_frame->SetFrameType(StackFrame::INTERNAL);
|
||||
|
||||
// A frame for an accessor stub can not be the topmost or bottommost one.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous frame's top and
|
||||
// this frame's size.
|
||||
uint32_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
unsigned output_offset = output_frame_size;
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// The context can be gotten from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetContext();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; context\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the function.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; function (%s sentinel)\n",
|
||||
top_address + output_offset, output_offset, value, kind);
|
||||
}
|
||||
|
||||
// Get Code object from accessor stub.
|
||||
output_offset -= kPointerSize;
|
||||
Builtins::Name name = is_setter_stub_frame ?
|
||||
Builtins::kStoreIC_Setter_ForDeopt :
|
||||
Builtins::kLoadIC_Getter_ForDeopt;
|
||||
Code* accessor_stub = isolate_->builtins()->builtin(name);
|
||||
value = reinterpret_cast<intptr_t>(accessor_stub);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; code object\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Skip receiver.
|
||||
Translation::Opcode opcode =
|
||||
static_cast<Translation::Opcode>(iterator->Next());
|
||||
iterator->Skip(Translation::NumberOfOperandsFor(opcode));
|
||||
|
||||
if (is_setter_stub_frame) {
|
||||
// The implicit return value was part of the artificial setter stub
|
||||
// environment.
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Smi* offset = is_setter_stub_frame ?
|
||||
isolate_->heap()->setter_stub_deopt_pc_offset() :
|
||||
isolate_->heap()->getter_stub_deopt_pc_offset();
|
||||
intptr_t pc = reinterpret_cast<intptr_t>(
|
||||
accessor_stub->instruction_start() + offset->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
// This code is very similar to ia32/arm code, but relies on register names
|
||||
// (fp, sp) and how the frame is laid out.
|
||||
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||
|
@ -348,107 +348,6 @@ void Deoptimizer::DoComputeOsrOutputFrame() {
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
unsigned height = iterator->Next();
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
if (trace_) {
|
||||
PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes);
|
||||
}
|
||||
|
||||
unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
|
||||
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::ARGUMENTS_ADAPTOR);
|
||||
|
||||
// Arguments adaptor can not be topmost or bottommost.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous
|
||||
// frame's top and this frame's size.
|
||||
intptr_t top_address;
|
||||
top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
// Compute the incoming parameter translation.
|
||||
int parameter_count = height;
|
||||
unsigned output_offset = output_frame_size;
|
||||
for (int i = 0; i < parameter_count; ++i) {
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the context.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t context = reinterpret_cast<intptr_t>(
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
output_frame->SetFrameSlot(output_offset, context);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; context (adaptor sentinel)\n",
|
||||
top_address + output_offset, output_offset, context);
|
||||
}
|
||||
|
||||
// The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(function);
|
||||
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);
|
||||
}
|
||||
|
||||
// Number of incoming arguments.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; argc (%d)\n",
|
||||
top_address + output_offset, output_offset, value, height - 1);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Builtins* builtins = isolate_->builtins();
|
||||
Code* adaptor_trampoline =
|
||||
builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
|
||||
intptr_t pc_value = reinterpret_cast<intptr_t>(
|
||||
adaptor_trampoline->instruction_start() +
|
||||
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
|
||||
output_frame->SetPc(pc_value);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
//
|
||||
@ -756,125 +655,6 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||
int frame_index,
|
||||
bool is_setter_stub_frame) {
|
||||
JSFunction* accessor = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||
// The receiver (and the implicit return value, if any) are expected in
|
||||
// registers by the LoadIC/StoreIC, so they don't belong to the output stack
|
||||
// frame. This means that we have to use a height of 0.
|
||||
unsigned height = 0;
|
||||
unsigned height_in_bytes = height * kPointerSize;
|
||||
const char* kind = is_setter_stub_frame ? "setter" : "getter";
|
||||
if (trace_) {
|
||||
PrintF(" translating %s stub => height=%u\n", kind, height_in_bytes);
|
||||
}
|
||||
|
||||
// We need 1 stack entry for the return address + 4 stack entries from
|
||||
// StackFrame::INTERNAL (FP, context, frame type, code object, see
|
||||
// MacroAssembler::EnterFrame). For a setter stub frame we need one additional
|
||||
// entry for the implicit return value, see
|
||||
// StoreStubCompiler::CompileStoreViaSetter.
|
||||
unsigned fixed_frame_entries = 1 + 4 + (is_setter_stub_frame ? 1 : 0);
|
||||
unsigned fixed_frame_size = fixed_frame_entries * kPointerSize;
|
||||
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, accessor);
|
||||
output_frame->SetFrameType(StackFrame::INTERNAL);
|
||||
|
||||
// A frame for an accessor stub can not be the topmost or bottommost one.
|
||||
ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
|
||||
ASSERT(output_[frame_index] == NULL);
|
||||
output_[frame_index] = output_frame;
|
||||
|
||||
// The top address of the frame is computed from the previous frame's top and
|
||||
// this frame's size.
|
||||
intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
|
||||
output_frame->SetTop(top_address);
|
||||
|
||||
unsigned output_offset = output_frame_size;
|
||||
|
||||
// Read caller's PC from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t callers_pc = output_[frame_index - 1]->GetPc();
|
||||
output_frame->SetFrameSlot(output_offset, callers_pc);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's pc\n",
|
||||
top_address + output_offset, output_offset, callers_pc);
|
||||
}
|
||||
|
||||
// Read caller's FP from the previous frame, and set this frame's FP.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t value = output_[frame_index - 1]->GetFp();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
intptr_t fp_value = top_address + output_offset;
|
||||
output_frame->SetFp(fp_value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; caller's fp\n",
|
||||
fp_value, output_offset, value);
|
||||
}
|
||||
|
||||
// The context can be gotten from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetContext();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; context\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// A marker value is used in place of the function.
|
||||
output_offset -= kPointerSize;
|
||||
value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::INTERNAL));
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; function (%s sentinel)\n",
|
||||
top_address + output_offset, output_offset, value, kind);
|
||||
}
|
||||
|
||||
// Get Code object from accessor stub.
|
||||
output_offset -= kPointerSize;
|
||||
Builtins::Name name = is_setter_stub_frame ?
|
||||
Builtins::kStoreIC_Setter_ForDeopt :
|
||||
Builtins::kLoadIC_Getter_ForDeopt;
|
||||
Code* accessor_stub = isolate_->builtins()->builtin(name);
|
||||
value = reinterpret_cast<intptr_t>(accessor_stub);
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
if (trace_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %u] <- 0x%08" V8PRIxPTR
|
||||
" ; code object\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
|
||||
// Skip receiver.
|
||||
Translation::Opcode opcode =
|
||||
static_cast<Translation::Opcode>(iterator->Next());
|
||||
iterator->Skip(Translation::NumberOfOperandsFor(opcode));
|
||||
|
||||
if (is_setter_stub_frame) {
|
||||
// The implicit return value was part of the artificial setter stub
|
||||
// environment.
|
||||
output_offset -= kPointerSize;
|
||||
DoTranslateCommand(iterator, frame_index, output_offset);
|
||||
}
|
||||
|
||||
ASSERT(0 == output_offset);
|
||||
|
||||
Smi* offset = is_setter_stub_frame ?
|
||||
isolate_->heap()->setter_stub_deopt_pc_offset() :
|
||||
isolate_->heap()->getter_stub_deopt_pc_offset();
|
||||
intptr_t pc = reinterpret_cast<intptr_t>(
|
||||
accessor_stub->instruction_start() + offset->value());
|
||||
output_frame->SetPc(pc);
|
||||
}
|
||||
|
||||
|
||||
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||
int frame_index) {
|
||||
BailoutId node_id = BailoutId(iterator->Next());
|
||||
|
Loading…
Reference in New Issue
Block a user