Fix deoptimization for out-of-line constant pool.
Ensure that the stack contains the correct constant pool pointer when a function deopts. This CL depends on https://codereview.chromium.org/183803022/ landing first. R=ulan@chromium.org Review URL: https://codereview.chromium.org/188063002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19940 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
eb2003da3f
commit
f1f6d3095a
@ -377,6 +377,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
|
||||
}
|
||||
|
||||
|
||||
void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) {
|
||||
// No out-of-line constant pool support.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -40,10 +40,18 @@ namespace internal {
|
||||
|
||||
Register JavaScriptFrame::fp_register() { return v8::internal::fp; }
|
||||
Register JavaScriptFrame::context_register() { return cp; }
|
||||
Register JavaScriptFrame::constant_pool_pointer_register() {
|
||||
UNREACHABLE();
|
||||
return no_reg;
|
||||
}
|
||||
|
||||
|
||||
Register StubFailureTrampolineFrame::fp_register() { return v8::internal::fp; }
|
||||
Register StubFailureTrampolineFrame::context_register() { return cp; }
|
||||
Register StubFailureTrampolineFrame::constant_pool_pointer_register() {
|
||||
UNREACHABLE();
|
||||
return no_reg;
|
||||
}
|
||||
|
||||
|
||||
Object*& ExitFrame::constant_pool_slot() const {
|
||||
|
@ -1353,8 +1353,14 @@ static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) {
|
||||
// then tear down the parameters.
|
||||
__ ldr(r1, MemOperand(fp, -(StandardFrameConstants::kFixedFrameSizeFromFp +
|
||||
kPointerSize)));
|
||||
__ mov(sp, fp);
|
||||
__ ldm(ia_w, sp, fp.bit() | lr.bit());
|
||||
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
__ add(sp, fp, Operand(StandardFrameConstants::kConstantPoolOffset));
|
||||
__ ldm(ia_w, sp, pp.bit() | fp.bit() | lr.bit());
|
||||
} else {
|
||||
__ mov(sp, fp);;
|
||||
__ ldm(ia_w, sp, fp.bit() | lr.bit());
|
||||
}
|
||||
__ add(sp, sp, Operand::PointerOffsetFromSmiKey(r1));
|
||||
__ add(sp, sp, Operand(kPointerSize)); // adjust for receiver
|
||||
}
|
||||
|
@ -373,6 +373,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
|
||||
}
|
||||
|
||||
|
||||
void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) {
|
||||
ASSERT(FLAG_enable_ool_constant_pool);
|
||||
SetFrameSlot(offset, value);
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
|
||||
} } // namespace v8::internal
|
||||
|
@ -992,24 +992,19 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
// For the bottommost output frame the constant pool pointer can be gotten
|
||||
// from the input frame. For subsequent output frames, it can be gotten from
|
||||
// the function's code.
|
||||
Register constant_pool_reg =
|
||||
JavaScriptFrame::constant_pool_pointer_register();
|
||||
// from the input frame. For subsequent output frames, it can be read from
|
||||
// the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
input_offset -= kPointerSize;
|
||||
if (is_bottommost) {
|
||||
value = input_->GetFrameSlot(input_offset);
|
||||
} else {
|
||||
value = reinterpret_cast<intptr_t>(
|
||||
function->shared()->code()->constant_pool());
|
||||
value = output_[frame_index - 1]->GetConstantPool();
|
||||
}
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
output_frame->SetConstantPool(value);
|
||||
if (is_topmost) output_frame->SetRegister(constant_pool_reg.code(), value);
|
||||
output_frame->SetCallerConstantPool(output_offset, value);
|
||||
if (trace_scope_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR "; constant_pool\n",
|
||||
V8PRIxPTR "; caller's constant_pool\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
}
|
||||
@ -1067,6 +1062,18 @@ void Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
|
||||
intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
|
||||
output_frame->SetPc(pc_value);
|
||||
|
||||
// Update constant pool.
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
intptr_t constant_pool_value =
|
||||
reinterpret_cast<intptr_t>(non_optimized_code->constant_pool());
|
||||
output_frame->SetConstantPool(constant_pool_value);
|
||||
if (is_topmost) {
|
||||
Register constant_pool_reg =
|
||||
JavaScriptFrame::constant_pool_pointer_register();
|
||||
output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
|
||||
}
|
||||
}
|
||||
|
||||
FullCodeGenerator::State state =
|
||||
FullCodeGenerator::StateField::decode(pc_and_state);
|
||||
output_frame->SetState(Smi::FromInt(state));
|
||||
@ -1150,15 +1157,14 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
// A marker value is used in place of the constant pool.
|
||||
// Read the caller's constant pool from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
intptr_t constant_pool = reinterpret_cast<intptr_t>(
|
||||
Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
|
||||
output_frame->SetFrameSlot(output_offset, constant_pool);
|
||||
value = output_[frame_index - 1]->GetConstantPool();
|
||||
output_frame->SetCallerConstantPool(output_offset, value);
|
||||
if (trace_scope_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; constant_pool (adaptor sentinel)\n",
|
||||
top_address + output_offset, output_offset, constant_pool);
|
||||
V8PRIxPTR "; caller's constant_pool\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1205,6 +1211,11 @@ void Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
|
||||
adaptor_trampoline->instruction_start() +
|
||||
isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
|
||||
output_frame->SetPc(pc_value);
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
intptr_t constant_pool_value =
|
||||
reinterpret_cast<intptr_t>(adaptor_trampoline->constant_pool());
|
||||
output_frame->SetConstantPool(constant_pool_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1280,13 +1291,13 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
// The constant pool pointer can be gotten from the previous frame.
|
||||
// Read the caller's constant pool from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetConstantPool();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
output_frame->SetCallerConstantPool(output_offset, value);
|
||||
if (trace_scope_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; constant pool\n",
|
||||
V8PRIxPTR " ; caller's constant pool\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
}
|
||||
@ -1367,6 +1378,11 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
|
||||
construct_stub->instruction_start() +
|
||||
isolate_->heap()->construct_stub_deopt_pc_offset()->value());
|
||||
output_frame->SetPc(pc);
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
intptr_t constant_pool_value =
|
||||
reinterpret_cast<intptr_t>(construct_stub->constant_pool());
|
||||
output_frame->SetConstantPool(constant_pool_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1438,13 +1454,13 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
// The constant pool pointer can be gotten from the previous frame.
|
||||
// Read the caller's constant pool from the previous frame.
|
||||
output_offset -= kPointerSize;
|
||||
value = output_[frame_index - 1]->GetConstantPool();
|
||||
output_frame->SetFrameSlot(output_offset, value);
|
||||
output_frame->SetCallerConstantPool(output_offset, value);
|
||||
if (trace_scope_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; constant pool\n",
|
||||
V8PRIxPTR " ; caller's constant pool\n",
|
||||
top_address + output_offset, output_offset, value);
|
||||
}
|
||||
}
|
||||
@ -1506,6 +1522,11 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslationIterator* iterator,
|
||||
intptr_t pc = reinterpret_cast<intptr_t>(
|
||||
accessor_stub->instruction_start() + offset->value());
|
||||
output_frame->SetPc(pc);
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
intptr_t constant_pool_value =
|
||||
reinterpret_cast<intptr_t>(accessor_stub->constant_pool());
|
||||
output_frame->SetConstantPool(constant_pool_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1609,17 +1630,14 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
||||
}
|
||||
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
// The constant pool pointer can be gotten from the input frame.
|
||||
Register constant_pool_pointer_register =
|
||||
StubFailureTrampolineFrame::constant_pool_pointer_register();
|
||||
// Read the caller's constant pool from the input frame.
|
||||
input_frame_offset -= kPointerSize;
|
||||
value = input_->GetFrameSlot(input_frame_offset);
|
||||
output_frame->SetRegister(constant_pool_pointer_register.code(), value);
|
||||
output_frame_offset -= kPointerSize;
|
||||
output_frame->SetFrameSlot(output_frame_offset, value);
|
||||
output_frame->SetCallerConstantPool(output_frame_offset, value);
|
||||
if (trace_scope_) {
|
||||
PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
|
||||
V8PRIxPTR " ; constant_pool_pointer\n",
|
||||
V8PRIxPTR " ; caller's constant_pool\n",
|
||||
top_address + output_frame_offset, output_frame_offset, value);
|
||||
}
|
||||
}
|
||||
@ -1753,6 +1771,14 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslationIterator* iterator,
|
||||
ASSERT(trampoline != NULL);
|
||||
output_frame->SetPc(reinterpret_cast<intptr_t>(
|
||||
trampoline->instruction_start()));
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
Register constant_pool_reg =
|
||||
StubFailureTrampolineFrame::constant_pool_pointer_register();
|
||||
intptr_t constant_pool_value =
|
||||
reinterpret_cast<intptr_t>(trampoline->constant_pool());
|
||||
output_frame->SetConstantPool(constant_pool_value);
|
||||
output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
|
||||
}
|
||||
output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
|
||||
Code* notify_failure = NotifyStubFailureBuiltin();
|
||||
output_frame->SetContinuation(
|
||||
|
@ -508,6 +508,8 @@ class FrameDescription {
|
||||
|
||||
void SetCallerFp(unsigned offset, intptr_t value);
|
||||
|
||||
void SetCallerConstantPool(unsigned offset, intptr_t value);
|
||||
|
||||
intptr_t GetRegister(unsigned n) const {
|
||||
#if DEBUG
|
||||
// This convoluted ASSERT is needed to work around a gcc problem that
|
||||
|
@ -201,6 +201,11 @@ inline Address StandardFrame::ComputePCAddress(Address fp) {
|
||||
}
|
||||
|
||||
|
||||
inline Address StandardFrame::ComputeConstantPoolAddress(Address fp) {
|
||||
return fp + StandardFrameConstants::kConstantPoolOffset;
|
||||
}
|
||||
|
||||
|
||||
inline bool StandardFrame::IsArgumentsAdaptorFrame(Address fp) {
|
||||
Object* marker =
|
||||
Memory::Object_at(fp + StandardFrameConstants::kContextOffset);
|
||||
|
@ -531,6 +531,10 @@ void ExitFrame::ComputeCallerState(State* state) const {
|
||||
state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
|
||||
state->pc_address = ResolveReturnAddressLocation(
|
||||
reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
|
||||
if (FLAG_enable_ool_constant_pool) {
|
||||
state->constant_pool_address = reinterpret_cast<Address*>(
|
||||
fp() + ExitFrameConstants::kConstantPoolOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -574,6 +578,8 @@ void ExitFrame::FillState(Address fp, Address sp, State* state) {
|
||||
state->fp = fp;
|
||||
state->pc_address = ResolveReturnAddressLocation(
|
||||
reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
|
||||
state->constant_pool_address =
|
||||
reinterpret_cast<Address*>(fp + ExitFrameConstants::kConstantPoolOffset);
|
||||
}
|
||||
|
||||
|
||||
@ -610,6 +616,8 @@ void StandardFrame::ComputeCallerState(State* state) const {
|
||||
state->fp = caller_fp();
|
||||
state->pc_address = ResolveReturnAddressLocation(
|
||||
reinterpret_cast<Address*>(ComputePCAddress(fp())));
|
||||
state->constant_pool_address =
|
||||
reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
|
||||
}
|
||||
|
||||
|
||||
|
17
src/frames.h
17
src/frames.h
@ -225,10 +225,12 @@ class StackFrame BASE_EMBEDDED {
|
||||
};
|
||||
|
||||
struct State {
|
||||
State() : sp(NULL), fp(NULL), pc_address(NULL) { }
|
||||
State() : sp(NULL), fp(NULL), pc_address(NULL),
|
||||
constant_pool_address(NULL) { }
|
||||
Address sp;
|
||||
Address fp;
|
||||
Address* pc_address;
|
||||
Address* constant_pool_address;
|
||||
};
|
||||
|
||||
// Copy constructor; it breaks the connection to host iterator
|
||||
@ -270,6 +272,11 @@ class StackFrame BASE_EMBEDDED {
|
||||
Address pc() const { return *pc_address(); }
|
||||
void set_pc(Address pc) { *pc_address() = pc; }
|
||||
|
||||
Address constant_pool() const { return *constant_pool_address(); }
|
||||
void set_constant_pool(ConstantPoolArray* constant_pool) {
|
||||
*constant_pool_address() = reinterpret_cast<Address>(constant_pool);
|
||||
}
|
||||
|
||||
virtual void SetCallerFp(Address caller_fp) = 0;
|
||||
|
||||
// Manually changes value of fp in this object.
|
||||
@ -277,6 +284,10 @@ class StackFrame BASE_EMBEDDED {
|
||||
|
||||
Address* pc_address() const { return state_.pc_address; }
|
||||
|
||||
Address* constant_pool_address() const {
|
||||
return state_.constant_pool_address;
|
||||
}
|
||||
|
||||
// Get the id of this stack frame.
|
||||
Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
|
||||
|
||||
@ -496,6 +507,10 @@ class StandardFrame: public StackFrame {
|
||||
// by the provided frame pointer.
|
||||
static inline Address ComputePCAddress(Address fp);
|
||||
|
||||
// Computes the address of the constant pool field in the standard
|
||||
// frame given by the provided frame pointer.
|
||||
static inline Address ComputeConstantPoolAddress(Address fp);
|
||||
|
||||
// Iterate over expression stack including stack handlers, locals,
|
||||
// and parts of the fixed part including context and code fields.
|
||||
void IterateExpressions(ObjectVisitor* v) const;
|
||||
|
@ -463,6 +463,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
|
||||
}
|
||||
|
||||
|
||||
void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) {
|
||||
// No out-of-line constant pool support.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
|
||||
|
||||
|
@ -361,6 +361,12 @@ void FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
|
||||
}
|
||||
|
||||
|
||||
void FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) {
|
||||
// No out-of-line constant pool support.
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
#undef __
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user