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:
jarin 2015-05-04 09:43:56 -07:00 committed by Commit bot
parent d0ed8940fc
commit b5b47e1f88
15 changed files with 74 additions and 48 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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_; }

View File

@ -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);

View File

@ -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());

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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();
}

View File

@ -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) \

View File

@ -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.

View File

@ -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);

View File

@ -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, ],