Unify deoptimizer for construct stub frames.
This unifies the translation of artificial construct stub frames. The frame layout is almost the same on all architectures and only differs in the presence of a slot holding the constructor function. R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/12379042 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13843 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
07e2494735
commit
2b7891c303
@ -537,128 +537,6 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
|
||||||
int frame_index) {
|
|
||||||
Builtins* builtins = isolate_->builtins();
|
|
||||||
Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
|
|
||||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
|
||||||
unsigned height = iterator->Next();
|
|
||||||
unsigned height_in_bytes = height * kPointerSize;
|
|
||||||
if (FLAG_trace_deopt) {
|
|
||||||
PrintF(" translating construct stub => height=%d\n", height_in_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned fixed_frame_size = 8 * 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, function);
|
|
||||||
output_frame->SetFrameType(StackFrame::CONSTRUCT);
|
|
||||||
|
|
||||||
// Construct stub 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 (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; 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%08x: [top + %d] <- 0x%08x ; 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::CONSTRUCT));
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The output frame reflects a JSConstructStubGeneric frame.
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = reinterpret_cast<intptr_t>(construct_stub);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; code object\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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor function being invoked by the stub.
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = reinterpret_cast<intptr_t>(function);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; constructor function\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The newly allocated object was passed as receiver in the artificial
|
|
||||||
// constructor stub environment created by HEnvironment::CopyForInlining().
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(0 == output_offset);
|
|
||||||
|
|
||||||
uint32_t pc = reinterpret_cast<uint32_t>(
|
|
||||||
construct_stub->instruction_start() +
|
|
||||||
isolate_->heap()->construct_stub_deopt_pc_offset()->value());
|
|
||||||
output_frame->SetPc(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This code is very similar to ia32 code, but relies on register names (fp, sp)
|
// This code is very similar to ia32 code, but relies on register names (fp, sp)
|
||||||
// and how the frame is laid out.
|
// and how the frame is laid out.
|
||||||
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||||
|
@ -149,14 +149,30 @@ class JavaScriptFrameConstants : public AllStatic {
|
|||||||
|
|
||||||
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
static const int kFrameSize =
|
static const int kFrameSize =
|
||||||
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ConstructFrameConstants : public AllStatic {
|
||||||
|
public:
|
||||||
|
// FP-relative.
|
||||||
|
static const int kImplicitReceiverOffset = -6 * kPointerSize;
|
||||||
|
static const int kConstructorOffset = -5 * kPointerSize;
|
||||||
|
static const int kLengthOffset = -4 * kPointerSize;
|
||||||
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
|
static const int kFrameSize =
|
||||||
|
StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class InternalFrameConstants : public AllStatic {
|
class InternalFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -922,6 +922,139 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
||||||
|
int frame_index) {
|
||||||
|
Builtins* builtins = isolate_->builtins();
|
||||||
|
Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
|
||||||
|
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
||||||
|
unsigned height = iterator->Next();
|
||||||
|
unsigned height_in_bytes = height * kPointerSize;
|
||||||
|
if (trace_) {
|
||||||
|
PrintF(" translating construct stub => height=%d\n", height_in_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned fixed_frame_size = ConstructFrameConstants::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::CONSTRUCT);
|
||||||
|
|
||||||
|
// Construct stub 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 + %d] <- 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::CONSTRUCT));
|
||||||
|
output_frame->SetFrameSlot(output_offset, value);
|
||||||
|
if (trace_) {
|
||||||
|
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||||
|
V8PRIxPTR " ; function (construct sentinel)\n",
|
||||||
|
top_address + output_offset, output_offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The output frame reflects a JSConstructStubGeneric frame.
|
||||||
|
output_offset -= kPointerSize;
|
||||||
|
value = reinterpret_cast<intptr_t>(construct_stub);
|
||||||
|
output_frame->SetFrameSlot(output_offset, value);
|
||||||
|
if (trace_) {
|
||||||
|
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||||
|
V8PRIxPTR " ; code object\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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor function being invoked by the stub (only present on some
|
||||||
|
// architectures, indicated by kConstructorOffset).
|
||||||
|
if (ConstructFrameConstants::kConstructorOffset != kMinInt) {
|
||||||
|
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 " ; constructor function\n",
|
||||||
|
top_address + output_offset, output_offset, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The newly allocated object was passed as receiver in the artificial
|
||||||
|
// constructor stub environment created by HEnvironment::CopyForInlining().
|
||||||
|
output_offset -= kPointerSize;
|
||||||
|
value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
|
||||||
|
output_frame->SetFrameSlot(output_offset, value);
|
||||||
|
if (trace_) {
|
||||||
|
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||||
|
V8PRIxPTR " ; allocated receiver\n",
|
||||||
|
top_address + output_offset, output_offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(0 == output_offset);
|
||||||
|
|
||||||
|
intptr_t pc = reinterpret_cast<intptr_t>(
|
||||||
|
construct_stub->instruction_start() +
|
||||||
|
isolate_->heap()->construct_stub_deopt_pc_offset()->value());
|
||||||
|
output_frame->SetPc(pc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||||
int frame_index,
|
int frame_index,
|
||||||
bool is_setter_stub_frame) {
|
bool is_setter_stub_frame) {
|
||||||
|
@ -643,119 +643,6 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
|
||||||
int frame_index) {
|
|
||||||
Builtins* builtins = isolate_->builtins();
|
|
||||||
Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
|
|
||||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
|
||||||
unsigned height = iterator->Next();
|
|
||||||
unsigned height_in_bytes = height * kPointerSize;
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" translating construct stub => height=%d\n", height_in_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned fixed_frame_size = 7 * 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, function);
|
|
||||||
output_frame->SetFrameType(StackFrame::CONSTRUCT);
|
|
||||||
|
|
||||||
// Construct stub 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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%08x: [top + %d] <- 0x%08x ; 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::CONSTRUCT));
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The output frame reflects a JSConstructStubGeneric frame.
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = reinterpret_cast<intptr_t>(construct_stub);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; code object\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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The newly allocated object was passed as receiver in the artificial
|
|
||||||
// constructor stub environment created by HEnvironment::CopyForInlining().
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(0 == output_offset);
|
|
||||||
|
|
||||||
uint32_t pc = reinterpret_cast<uint32_t>(
|
|
||||||
construct_stub->instruction_start() +
|
|
||||||
isolate_->heap()->construct_stub_deopt_pc_offset()->value());
|
|
||||||
output_frame->SetPc(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||||
int frame_index) {
|
int frame_index) {
|
||||||
BailoutId node_id = BailoutId(iterator->Next());
|
BailoutId node_id = BailoutId(iterator->Next());
|
||||||
|
@ -114,14 +114,30 @@ class JavaScriptFrameConstants : public AllStatic {
|
|||||||
|
|
||||||
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
static const int kFrameSize =
|
static const int kFrameSize =
|
||||||
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ConstructFrameConstants : public AllStatic {
|
||||||
|
public:
|
||||||
|
// FP-relative.
|
||||||
|
static const int kImplicitReceiverOffset = -5 * kPointerSize;
|
||||||
|
static const int kConstructorOffset = kMinInt;
|
||||||
|
static const int kLengthOffset = -4 * kPointerSize;
|
||||||
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
|
static const int kFrameSize =
|
||||||
|
StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class InternalFrameConstants : public AllStatic {
|
class InternalFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -531,128 +531,6 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
|
||||||
int frame_index) {
|
|
||||||
Builtins* builtins = isolate_->builtins();
|
|
||||||
Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
|
|
||||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
|
||||||
unsigned height = iterator->Next();
|
|
||||||
unsigned height_in_bytes = height * kPointerSize;
|
|
||||||
if (FLAG_trace_deopt) {
|
|
||||||
PrintF(" translating construct stub => height=%d\n", height_in_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned fixed_frame_size = 8 * 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, function);
|
|
||||||
output_frame->SetFrameType(StackFrame::CONSTRUCT);
|
|
||||||
|
|
||||||
// Construct stub 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 (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; 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%08x: [top + %d] <- 0x%08x ; 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::CONSTRUCT));
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The output frame reflects a JSConstructStubGeneric frame.
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = reinterpret_cast<intptr_t>(construct_stub);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; code object\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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Constructor function being invoked by the stub.
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = reinterpret_cast<intptr_t>(function);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; constructor function\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The newly allocated object was passed as receiver in the artificial
|
|
||||||
// constructor stub environment created by HEnvironment::CopyForInlining().
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(0 == output_offset);
|
|
||||||
|
|
||||||
uint32_t pc = reinterpret_cast<uint32_t>(
|
|
||||||
construct_stub->instruction_start() +
|
|
||||||
isolate_->heap()->construct_stub_deopt_pc_offset()->value());
|
|
||||||
output_frame->SetPc(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// This code is very similar to ia32/arm code, but relies on register names
|
// This code is very similar to ia32/arm code, but relies on register names
|
||||||
// (fp, sp) and how the frame is laid out.
|
// (fp, sp) and how the frame is laid out.
|
||||||
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||||
|
@ -208,14 +208,30 @@ class JavaScriptFrameConstants : public AllStatic {
|
|||||||
|
|
||||||
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
static const int kFrameSize =
|
static const int kFrameSize =
|
||||||
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ConstructFrameConstants : public AllStatic {
|
||||||
|
public:
|
||||||
|
// FP-relative.
|
||||||
|
static const int kImplicitReceiverOffset = -6 * kPointerSize;
|
||||||
|
static const int kConstructorOffset = -5 * kPointerSize;
|
||||||
|
static const int kLengthOffset = -4 * kPointerSize;
|
||||||
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
|
static const int kFrameSize =
|
||||||
|
StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class InternalFrameConstants : public AllStatic {
|
class InternalFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -535,126 +535,6 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
|
||||||
int frame_index) {
|
|
||||||
Builtins* builtins = isolate_->builtins();
|
|
||||||
Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
|
|
||||||
JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
|
|
||||||
unsigned height = iterator->Next();
|
|
||||||
unsigned height_in_bytes = height * kPointerSize;
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" translating construct stub => height=%d\n", height_in_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned fixed_frame_size = 7 * 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, function);
|
|
||||||
output_frame->SetFrameType(StackFrame::CONSTRUCT);
|
|
||||||
|
|
||||||
// Construct stub 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 + %d] <- 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::CONSTRUCT));
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
|
||||||
V8PRIxPTR " ; function (construct sentinel)\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The output frame reflects a JSConstructStubGeneric frame.
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = reinterpret_cast<intptr_t>(construct_stub);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
|
||||||
V8PRIxPTR " ; code object\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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The newly allocated object was passed as receiver in the artificial
|
|
||||||
// constructor stub environment created by HEnvironment::CopyForInlining().
|
|
||||||
output_offset -= kPointerSize;
|
|
||||||
value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
|
|
||||||
output_frame->SetFrameSlot(output_offset, value);
|
|
||||||
if (trace_) {
|
|
||||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
|
||||||
V8PRIxPTR " ; allocated receiver\n",
|
|
||||||
top_address + output_offset, output_offset, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(0 == output_offset);
|
|
||||||
|
|
||||||
intptr_t pc = reinterpret_cast<intptr_t>(
|
|
||||||
construct_stub->instruction_start() +
|
|
||||||
isolate_->heap()->construct_stub_deopt_pc_offset()->value());
|
|
||||||
output_frame->SetPc(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||||
int frame_index) {
|
int frame_index) {
|
||||||
BailoutId node_id = BailoutId(iterator->Next());
|
BailoutId node_id = BailoutId(iterator->Next());
|
||||||
|
@ -100,14 +100,30 @@ class JavaScriptFrameConstants : public AllStatic {
|
|||||||
|
|
||||||
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
class ArgumentsAdaptorFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
static const int kFrameSize =
|
static const int kFrameSize =
|
||||||
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
StandardFrameConstants::kFixedFrameSize + kPointerSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ConstructFrameConstants : public AllStatic {
|
||||||
|
public:
|
||||||
|
// FP-relative.
|
||||||
|
static const int kImplicitReceiverOffset = -5 * kPointerSize;
|
||||||
|
static const int kConstructorOffset = kMinInt;
|
||||||
|
static const int kLengthOffset = -4 * kPointerSize;
|
||||||
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
|
|
||||||
|
static const int kFrameSize =
|
||||||
|
StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class InternalFrameConstants : public AllStatic {
|
class InternalFrameConstants : public AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// FP-relative.
|
||||||
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user