Remove materialized objects on stack unwind.
BUG=v8:3985 LOG=n R=mstarzinger@chromium.org Review URL: https://codereview.chromium.org/1122083002 Cr-Commit-Position: refs/heads/master@{#28206}
This commit is contained in:
parent
d0ed8940fc
commit
b5b47e1f88
@ -1049,7 +1049,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set r0 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
|
||||
isolate());
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, r0);
|
||||
|
@ -1203,7 +1203,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set x0 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
|
||||
isolate());
|
||||
DCHECK(csp.Is(masm->StackPointer()));
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
|
@ -2017,7 +2017,8 @@ void Deoptimizer::MaterializeHeapObjects(JavaScriptFrameIterator* it) {
|
||||
}
|
||||
|
||||
if (prev_materialized_count_ > 0) {
|
||||
materialized_store->Remove(stack_fp_);
|
||||
bool removed = materialized_store->Remove(stack_fp_);
|
||||
CHECK(removed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3679,17 +3680,21 @@ void MaterializedObjectStore::Set(Address fp,
|
||||
}
|
||||
|
||||
|
||||
void MaterializedObjectStore::Remove(Address fp) {
|
||||
bool MaterializedObjectStore::Remove(Address fp) {
|
||||
int index = StackIdToIndex(fp);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
CHECK_GE(index, 0);
|
||||
|
||||
frame_fps_.Remove(index);
|
||||
Handle<FixedArray> array = GetStackEntries();
|
||||
FixedArray* array = isolate()->heap()->materialized_objects();
|
||||
CHECK_LT(index, array->length());
|
||||
for (int i = index; i < frame_fps_.length(); i++) {
|
||||
array->set(i, array->get(i + 1));
|
||||
}
|
||||
array->set(frame_fps_.length(), isolate()->heap()->undefined_value());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -966,7 +966,7 @@ class MaterializedObjectStore {
|
||||
|
||||
Handle<FixedArray> Get(Address fp);
|
||||
void Set(Address fp, Handle<FixedArray> materialized_objects);
|
||||
void Remove(Address fp);
|
||||
bool Remove(Address fp);
|
||||
|
||||
private:
|
||||
Isolate* isolate() { return isolate_; }
|
||||
|
@ -2538,7 +2538,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set eax to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
|
||||
isolate());
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, eax);
|
||||
|
@ -1025,7 +1025,7 @@ Object* Isolate::ReThrow(Object* exception) {
|
||||
}
|
||||
|
||||
|
||||
Object* Isolate::FindHandler() {
|
||||
Object* Isolate::UnwindAndFindHandler() {
|
||||
Object* exception = pending_exception();
|
||||
|
||||
Code* code = nullptr;
|
||||
@ -1062,19 +1062,19 @@ Object* Isolate::FindHandler() {
|
||||
OptimizedFrame* js_frame = static_cast<OptimizedFrame*>(frame);
|
||||
int stack_slots = 0; // Will contain stack slot count of frame.
|
||||
offset = js_frame->LookupExceptionHandlerInTable(&stack_slots);
|
||||
if (offset < 0) continue;
|
||||
if (offset >= 0) {
|
||||
// Compute the stack pointer from the frame pointer. This ensures that
|
||||
// argument slots on the stack are dropped as returning would.
|
||||
Address return_sp = frame->fp() -
|
||||
StandardFrameConstants::kFixedFrameSizeFromFp -
|
||||
stack_slots * kPointerSize;
|
||||
|
||||
// Compute the stack pointer from the frame pointer. This ensures that
|
||||
// argument slots on the stack are dropped as returning would.
|
||||
Address return_sp = frame->fp() -
|
||||
StandardFrameConstants::kFixedFrameSizeFromFp -
|
||||
stack_slots * kPointerSize;
|
||||
|
||||
// Gather information from the frame.
|
||||
code = frame->LookupCode();
|
||||
handler_sp = return_sp;
|
||||
handler_fp = frame->fp();
|
||||
break;
|
||||
// Gather information from the frame.
|
||||
code = frame->LookupCode();
|
||||
handler_sp = return_sp;
|
||||
handler_fp = frame->fp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For JavaScript frames we perform a range lookup in the handler table.
|
||||
@ -1082,23 +1082,25 @@ Object* Isolate::FindHandler() {
|
||||
JavaScriptFrame* js_frame = static_cast<JavaScriptFrame*>(frame);
|
||||
int stack_slots = 0; // Will contain operand stack depth of handler.
|
||||
offset = js_frame->LookupExceptionHandlerInTable(&stack_slots);
|
||||
if (offset < 0) continue;
|
||||
if (offset >= 0) {
|
||||
// Compute the stack pointer from the frame pointer. This ensures that
|
||||
// operand stack slots are dropped for nested statements. Also restore
|
||||
// correct context for the handler which is pushed within the try-block.
|
||||
Address return_sp = frame->fp() -
|
||||
StandardFrameConstants::kFixedFrameSizeFromFp -
|
||||
stack_slots * kPointerSize;
|
||||
STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
|
||||
context = Context::cast(Memory::Object_at(return_sp - kPointerSize));
|
||||
|
||||
// Compute the stack pointer from the frame pointer. This ensures that
|
||||
// operand stack slots are dropped for nested statements. Also restore
|
||||
// correct context for the handler which is pushed within the try-block.
|
||||
Address return_sp = frame->fp() -
|
||||
StandardFrameConstants::kFixedFrameSizeFromFp -
|
||||
stack_slots * kPointerSize;
|
||||
STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
|
||||
context = Context::cast(Memory::Object_at(return_sp - kPointerSize));
|
||||
|
||||
// Gather information from the frame.
|
||||
code = frame->LookupCode();
|
||||
handler_sp = return_sp;
|
||||
handler_fp = frame->fp();
|
||||
break;
|
||||
// Gather information from the frame.
|
||||
code = frame->LookupCode();
|
||||
handler_sp = return_sp;
|
||||
handler_fp = frame->fp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RemoveMaterializedObjectsOnUnwind(frame);
|
||||
}
|
||||
|
||||
// Handler must exist.
|
||||
@ -1154,6 +1156,17 @@ Isolate::CatchType Isolate::PredictExceptionCatcher() {
|
||||
}
|
||||
|
||||
|
||||
void Isolate::RemoveMaterializedObjectsOnUnwind(StackFrame* frame) {
|
||||
if (frame->is_optimized()) {
|
||||
bool removed = materialized_object_store_->Remove(frame->fp());
|
||||
USE(removed);
|
||||
// If there were any materialized objects, the code should be
|
||||
// marked for deopt.
|
||||
DCHECK(!removed || frame->LookupCode()->marked_for_deoptimization());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Object* Isolate::ThrowIllegalOperation() {
|
||||
if (FLAG_stack_trace_on_illegal) PrintStack(stdout);
|
||||
return Throw(heap()->illegal_access_string());
|
||||
|
@ -764,7 +764,7 @@ class Isolate {
|
||||
|
||||
// Find the correct handler for the current pending exception. This also
|
||||
// clears and returns the current pending exception.
|
||||
Object* FindHandler();
|
||||
Object* UnwindAndFindHandler();
|
||||
|
||||
// Tries to predict whether an exception will be caught. Note that this can
|
||||
// only produce an estimate, because it is undecidable whether a finally
|
||||
@ -1254,6 +1254,10 @@ class Isolate {
|
||||
// then return true.
|
||||
bool PropagatePendingExceptionToExternalTryCatch();
|
||||
|
||||
// Remove per-frame stored materialized objects when we are unwinding
|
||||
// the frame.
|
||||
void RemoveMaterializedObjectsOnUnwind(StackFrame* frame);
|
||||
|
||||
// Traverse prototype chain to find out whether the object is derived from
|
||||
// the Error object.
|
||||
bool IsErrorObject(Handle<Object> obj);
|
||||
|
@ -1151,7 +1151,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set v0 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
|
||||
isolate());
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, a0);
|
||||
|
@ -1146,7 +1146,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set v0 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
|
||||
isolate());
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, a0);
|
||||
|
@ -1131,7 +1131,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set r3 to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindFindExceptionHandler,
|
||||
isolate());
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, 0, r3);
|
||||
|
@ -37,10 +37,10 @@ RUNTIME_FUNCTION(Runtime_ReThrow) {
|
||||
}
|
||||
|
||||
|
||||
RUNTIME_FUNCTION(Runtime_FindExceptionHandler) {
|
||||
RUNTIME_FUNCTION(Runtime_UnwindAndFindExceptionHandler) {
|
||||
SealHandleScope shs(isolate);
|
||||
DCHECK(args.length() == 0);
|
||||
return isolate->FindHandler();
|
||||
return isolate->UnwindAndFindHandler();
|
||||
}
|
||||
|
||||
|
||||
|
@ -271,7 +271,7 @@ namespace internal {
|
||||
F(CheckIsBootstrapping, 0, 1) \
|
||||
F(Throw, 1, 1) \
|
||||
F(ReThrow, 1, 1) \
|
||||
F(FindExceptionHandler, 0, 1) \
|
||||
F(UnwindAndFindExceptionHandler, 0, 1) \
|
||||
F(PromoteScheduledException, 0, 1) \
|
||||
F(ThrowReferenceError, 1, 1) \
|
||||
F(ThrowIteratorResultNotAnObject, 1, 1) \
|
||||
|
@ -2457,7 +2457,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set rax to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
|
||||
isolate());
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ movp(arg_reg_1, Immediate(0)); // argc.
|
||||
|
@ -2230,7 +2230,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
// Ask the runtime for help to determine the handler. This will set eax to
|
||||
// contain the current pending exception, don't clobber it.
|
||||
ExternalReference find_handler(Runtime::kFindExceptionHandler, isolate());
|
||||
ExternalReference find_handler(Runtime::kUnwindAndFindExceptionHandler,
|
||||
isolate());
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::MANUAL);
|
||||
__ PrepareCallCFunction(3, eax);
|
||||
|
@ -223,10 +223,6 @@
|
||||
# nosse2. Also for arm novfp3.
|
||||
'regress/regress-2989': [FAIL, NO_VARIANTS, ['system == linux and arch == x87 or arch == arm and simulator == True', PASS]],
|
||||
|
||||
# BUG(v8:3985). Wrong materialization of arguments object after throwing
|
||||
# an exception.
|
||||
'regress/regress-3985': [PASS, FAIL],
|
||||
|
||||
# Skip endain dependent test for mips due to different typed views of the same
|
||||
# array buffer.
|
||||
'nans': [PASS, ],
|
||||
|
Loading…
Reference in New Issue
Block a user