mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:17:55 +00:00
JumpToFrame refactor
- Refactor the JumpToExceptionHandle code so that it is now built from two pieces: JumpToFrame and RunExceptionHandler. - Refactor the Simulator::Longjmp() code so that it is no longer exception-specific. Instead it uses the RunExceptionHandler stub. This makes it so that the JumpToFrame stub and Simulator::JumpToFrame have the same semantics. This will make it easier to land the Rewind changes I am working on. There are some oddities for dbc. BUG= R=johnmccutchan@google.com Review URL: https://codereview.chromium.org/2503653002 .
This commit is contained in:
parent
1d5df9bc8c
commit
5ed13d3298
|
@ -210,12 +210,19 @@ static void JumpToExceptionHandler(Thread* thread,
|
|||
uword frame_pointer,
|
||||
const Object& exception_object,
|
||||
const Object& stacktrace_object) {
|
||||
// The no_gc StackResource is unwound through the tear down of
|
||||
// stack resources below.
|
||||
NoSafepointScope no_safepoint;
|
||||
RawObject* raw_exception = exception_object.raw();
|
||||
RawObject* raw_stacktrace = stacktrace_object.raw();
|
||||
thread->set_active_exception(exception_object);
|
||||
thread->set_active_stacktrace(stacktrace_object);
|
||||
thread->set_resume_pc(program_counter);
|
||||
uword run_exception_pc = StubCode::RunExceptionHandler_entry()->EntryPoint();
|
||||
Exceptions::JumpToFrame(thread, run_exception_pc, stack_pointer,
|
||||
frame_pointer);
|
||||
}
|
||||
|
||||
|
||||
void Exceptions::JumpToFrame(Thread* thread,
|
||||
uword program_counter,
|
||||
uword stack_pointer,
|
||||
uword frame_pointer) {
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
MallocGrowableArray<PendingLazyDeopt>* pending_deopts =
|
||||
thread->isolate()->pending_deopts();
|
||||
|
@ -284,8 +291,8 @@ static void JumpToExceptionHandler(Thread* thread,
|
|||
// exception object in the kExceptionObjectReg register and the stacktrace
|
||||
// object (may be raw null) in the kStackTraceObjectReg register.
|
||||
|
||||
Simulator::Current()->Longjmp(program_counter, stack_pointer, frame_pointer,
|
||||
raw_exception, raw_stacktrace, thread);
|
||||
Simulator::Current()->JumpToFrame(program_counter, stack_pointer,
|
||||
frame_pointer, thread);
|
||||
#else
|
||||
// Prepare for unwinding frames by destroying all the stack resources
|
||||
// in the previous frames.
|
||||
|
@ -294,18 +301,16 @@ static void JumpToExceptionHandler(Thread* thread,
|
|||
// Call a stub to set up the exception object in kExceptionObjectReg,
|
||||
// to set up the stacktrace object in kStackTraceObjectReg, and to
|
||||
// continue execution at the given pc in the given frame.
|
||||
typedef void (*ExcpHandler)(uword, uword, uword, RawObject*, RawObject*,
|
||||
Thread*);
|
||||
typedef void (*ExcpHandler)(uword, uword, uword, Thread*);
|
||||
ExcpHandler func = reinterpret_cast<ExcpHandler>(
|
||||
StubCode::JumpToExceptionHandler_entry()->EntryPoint());
|
||||
StubCode::JumpToFrame_entry()->EntryPoint());
|
||||
|
||||
// Unpoison the stack before we tear it down in the generated stub code.
|
||||
uword current_sp = Thread::GetCurrentStackPointer() - 1024;
|
||||
ASAN_UNPOISON(reinterpret_cast<void*>(current_sp),
|
||||
stack_pointer - current_sp);
|
||||
|
||||
func(program_counter, stack_pointer, frame_pointer, raw_exception,
|
||||
raw_stacktrace, thread);
|
||||
func(program_counter, stack_pointer, frame_pointer, thread);
|
||||
#endif
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
|
@ -80,6 +80,11 @@ class Exceptions : AllStatic {
|
|||
// otherwise returns a RawError.
|
||||
static RawObject* Create(ExceptionType type, const Array& arguments);
|
||||
|
||||
static void JumpToFrame(Thread* thread,
|
||||
uword program_counter,
|
||||
uword stack_pointer,
|
||||
uword frame_pointer);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Exceptions);
|
||||
};
|
||||
|
|
|
@ -1104,11 +1104,10 @@ void Profiler::SampleThread(Thread* thread,
|
|||
return;
|
||||
}
|
||||
|
||||
if (StubCode::HasBeenInitialized() &&
|
||||
StubCode::InJumpToExceptionHandlerStub(state.pc)) {
|
||||
// The JumpToExceptionHandler stub manually adjusts the stack pointer,
|
||||
// frame pointer, and some isolate state before jumping to a catch entry.
|
||||
// It is not safe to walk the stack when executing this stub.
|
||||
if (StubCode::HasBeenInitialized() && StubCode::InJumpToFrameStub(state.pc)) {
|
||||
// The JumpToFrame stub manually adjusts the stack pointer, frame
|
||||
// pointer, and some isolate state. It is not safe to walk the
|
||||
// stack when executing this stub.
|
||||
AtomicOperations::IncrementInt64By(
|
||||
&counters_.bail_out_jump_to_exception_handler, 1);
|
||||
return;
|
||||
|
|
|
@ -3891,12 +3891,7 @@ int64_t Simulator::Call(int32_t entry,
|
|||
}
|
||||
|
||||
|
||||
void Simulator::Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread) {
|
||||
void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
|
||||
// Walk over all setjmp buffers (simulated --> C++ transitions)
|
||||
// and try to find the setjmp associated with the simulated stack pointer.
|
||||
SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
|
||||
|
@ -3919,10 +3914,6 @@ void Simulator::Longjmp(uword pc,
|
|||
thread->set_vm_tag(VMTag::kDartTagId);
|
||||
// Clear top exit frame.
|
||||
thread->set_top_exit_frame_info(0);
|
||||
|
||||
ASSERT(raw_exception != Object::null());
|
||||
set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
|
||||
set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
|
||||
// Restore pool pointer.
|
||||
int32_t code =
|
||||
*reinterpret_cast<int32_t*>(fp + kPcMarkerSlotFromFp * kWordSize);
|
||||
|
|
|
@ -127,12 +127,7 @@ class Simulator {
|
|||
|
||||
static uword FunctionForRedirect(uword redirect);
|
||||
|
||||
void Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread);
|
||||
void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
|
||||
|
||||
private:
|
||||
// Known bad pc value to ensure that the simulator does not execute
|
||||
|
|
|
@ -3602,12 +3602,7 @@ int64_t Simulator::Call(int64_t entry,
|
|||
}
|
||||
|
||||
|
||||
void Simulator::Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread) {
|
||||
void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
|
||||
// Walk over all setjmp buffers (simulated --> C++ transitions)
|
||||
// and try to find the setjmp associated with the simulated stack pointer.
|
||||
SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
|
||||
|
@ -3630,10 +3625,6 @@ void Simulator::Longjmp(uword pc,
|
|||
thread->set_vm_tag(VMTag::kDartTagId);
|
||||
// Clear top exit frame.
|
||||
thread->set_top_exit_frame_info(0);
|
||||
|
||||
ASSERT(raw_exception != Object::null());
|
||||
set_register(NULL, kExceptionObjectReg, bit_cast<int64_t>(raw_exception));
|
||||
set_register(NULL, kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace));
|
||||
// Restore pool pointer.
|
||||
int64_t code =
|
||||
*reinterpret_cast<int64_t*>(fp + kPcMarkerSlotFromFp * kWordSize);
|
||||
|
|
|
@ -124,12 +124,7 @@ class Simulator {
|
|||
|
||||
static uword FunctionForRedirect(uword redirect);
|
||||
|
||||
void Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread);
|
||||
void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
|
||||
|
||||
private:
|
||||
// Known bad pc value to ensure that the simulator does not execute
|
||||
|
|
|
@ -3691,12 +3691,7 @@ RawObject* Simulator::Call(const Code& code,
|
|||
}
|
||||
|
||||
|
||||
void Simulator::Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread) {
|
||||
void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
|
||||
// Walk over all setjmp buffers (simulated --> C++ transitions)
|
||||
// and try to find the setjmp associated with the simulated stack pointer.
|
||||
SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
|
||||
|
@ -3716,12 +3711,22 @@ void Simulator::Longjmp(uword pc,
|
|||
// Clear top exit frame.
|
||||
thread->set_top_exit_frame_info(0);
|
||||
|
||||
ASSERT(raw_exception != Object::null());
|
||||
sp_ = reinterpret_cast<RawObject**>(sp);
|
||||
fp_ = reinterpret_cast<RawObject**>(fp);
|
||||
pc_ = pc;
|
||||
special_[kExceptionSpecialIndex] = raw_exception;
|
||||
special_[kStacktraceSpecialIndex] = raw_stacktrace;
|
||||
|
||||
if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) {
|
||||
// Instead of executing the RunException stub, we implement its
|
||||
// behavior here.
|
||||
RawObject* raw_exception = thread->active_exception();
|
||||
RawObject* raw_stacktrace = thread->active_stacktrace();
|
||||
ASSERT(raw_exception != Object::null());
|
||||
special_[kExceptionSpecialIndex] = raw_exception;
|
||||
special_[kStacktraceSpecialIndex] = raw_stacktrace;
|
||||
pc_ = thread->resume_pc();
|
||||
} else {
|
||||
pc_ = pc;
|
||||
}
|
||||
|
||||
buf->Longjmp();
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
|
|
@ -64,12 +64,7 @@ class Simulator {
|
|||
const Array& arguments,
|
||||
Thread* thread);
|
||||
|
||||
void Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread);
|
||||
void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
|
||||
|
||||
uword get_sp() const { return reinterpret_cast<uword>(sp_); }
|
||||
uword get_fp() const { return reinterpret_cast<uword>(fp_); }
|
||||
|
|
|
@ -2479,12 +2479,7 @@ int64_t Simulator::Call(int32_t entry,
|
|||
}
|
||||
|
||||
|
||||
void Simulator::Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread) {
|
||||
void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) {
|
||||
// Walk over all setjmp buffers (simulated --> C++ transitions)
|
||||
// and try to find the setjmp associated with the simulated stack pointer.
|
||||
SimulatorSetjmpBuffer* buf = last_setjmp_buffer();
|
||||
|
@ -2507,10 +2502,6 @@ void Simulator::Longjmp(uword pc,
|
|||
thread->set_vm_tag(VMTag::kDartTagId);
|
||||
// Clear top exit frame.
|
||||
thread->set_top_exit_frame_info(0);
|
||||
|
||||
ASSERT(raw_exception != Object::null());
|
||||
set_register(kExceptionObjectReg, bit_cast<int32_t>(raw_exception));
|
||||
set_register(kStackTraceObjectReg, bit_cast<int32_t>(raw_stacktrace));
|
||||
// Restore pool pointer.
|
||||
int32_t code =
|
||||
*reinterpret_cast<int32_t*>(fp + kPcMarkerSlotFromFp * kWordSize);
|
||||
|
|
|
@ -139,12 +139,7 @@ class Simulator {
|
|||
|
||||
static uword FunctionForRedirect(uword redirect);
|
||||
|
||||
void Longjmp(uword pc,
|
||||
uword sp,
|
||||
uword fp,
|
||||
RawObject* raw_exception,
|
||||
RawObject* raw_stacktrace,
|
||||
Thread* thread);
|
||||
void JumpToFrame(uword pc, uword sp, uword fp, Thread* thread);
|
||||
|
||||
private:
|
||||
// A pc value used to signal the simulator to stop execution. Generally
|
||||
|
|
|
@ -91,8 +91,8 @@ void StubCode::VisitObjectPointers(ObjectPointerVisitor* visitor) {}
|
|||
|
||||
bool StubCode::HasBeenInitialized() {
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
// Use JumpToExceptionHandler and InvokeDart as canaries.
|
||||
const StubEntry* entry_1 = StubCode::JumpToExceptionHandler_entry();
|
||||
// Use JumpToHandler and InvokeDart as canaries.
|
||||
const StubEntry* entry_1 = StubCode::JumpToFrame_entry();
|
||||
const StubEntry* entry_2 = StubCode::InvokeDartCode_entry();
|
||||
return (entry_1 != NULL) && (entry_2 != NULL);
|
||||
#else
|
||||
|
@ -115,11 +115,11 @@ bool StubCode::InInvocationStub(uword pc) {
|
|||
}
|
||||
|
||||
|
||||
bool StubCode::InJumpToExceptionHandlerStub(uword pc) {
|
||||
bool StubCode::InJumpToFrameStub(uword pc) {
|
||||
#if !defined(TARGET_ARCH_DBC)
|
||||
ASSERT(HasBeenInitialized());
|
||||
uword entry = StubCode::JumpToExceptionHandler_entry()->EntryPoint();
|
||||
uword size = StubCode::JumpToExceptionHandlerSize();
|
||||
uword entry = StubCode::JumpToFrame_entry()->EntryPoint();
|
||||
uword size = StubCode::JumpToFrameSize();
|
||||
return (pc >= entry) && (pc < (entry + size));
|
||||
#else
|
||||
// This stub does not exist on DBC.
|
||||
|
|
|
@ -25,7 +25,8 @@ class Deserializer;
|
|||
#if !defined(TARGET_ARCH_DBC)
|
||||
#define VM_STUB_CODE_LIST(V) \
|
||||
V(GetStackPointer) \
|
||||
V(JumpToExceptionHandler) \
|
||||
V(JumpToFrame) \
|
||||
V(RunExceptionHandler) \
|
||||
V(UpdateStoreBuffer) \
|
||||
V(PrintStopMessage) \
|
||||
V(CallToRuntime) \
|
||||
|
@ -73,6 +74,7 @@ class Deserializer;
|
|||
#define VM_STUB_CODE_LIST(V) \
|
||||
V(LazyCompile) \
|
||||
V(OptimizeFunction) \
|
||||
V(RunExceptionHandler) \
|
||||
V(FixCallersTarget) \
|
||||
V(Deoptimize) \
|
||||
V(DeoptimizeLazyFromReturn) \
|
||||
|
@ -138,8 +140,8 @@ class StubCode : public AllStatic {
|
|||
// transitioning into dart code.
|
||||
static bool InInvocationStub(uword pc);
|
||||
|
||||
// Check if the specified pc is in the jump to exception handler stub.
|
||||
static bool InJumpToExceptionHandlerStub(uword pc);
|
||||
// Check if the specified pc is in the jump to frame stub.
|
||||
static bool InJumpToFrameStub(uword pc);
|
||||
|
||||
// Returns NULL if no stub found.
|
||||
static const char* NameOfStub(uword entry_point);
|
||||
|
|
|
@ -1850,23 +1850,19 @@ void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
// Jump to the exception or error handler.
|
||||
// Jump to a frame on the call stack.
|
||||
// LR: return address.
|
||||
// R0: program_counter.
|
||||
// R1: stack_pointer.
|
||||
// R2: frame_pointer.
|
||||
// R3: error object.
|
||||
// SP + 0: address of stacktrace object.
|
||||
// SP + 4: thread.
|
||||
// R3: thread.
|
||||
// Does not return.
|
||||
void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
||||
void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
|
||||
ASSERT(kExceptionObjectReg == R0);
|
||||
ASSERT(kStackTraceObjectReg == R1);
|
||||
__ mov(IP, Operand(R1)); // Copy Stack pointer into IP.
|
||||
__ mov(LR, Operand(R0)); // Program counter.
|
||||
__ mov(R0, Operand(R3)); // Exception object.
|
||||
__ ldr(R1, Address(SP, 0)); // StackTrace object.
|
||||
__ ldr(THR, Address(SP, 4)); // Thread.
|
||||
__ mov(THR, Operand(R3)); // Thread.
|
||||
__ mov(FP, Operand(R2)); // Frame_pointer.
|
||||
__ mov(SP, Operand(IP)); // Set Stack pointer.
|
||||
// Set the tag.
|
||||
|
@ -1878,6 +1874,27 @@ void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
|||
// Restore the pool pointer.
|
||||
__ RestoreCodePointer();
|
||||
__ LoadPoolPointer();
|
||||
__ bx(LR); // Jump to continuation point.
|
||||
}
|
||||
|
||||
|
||||
// Run an exception handler. Execution comes from JumpToFrame
|
||||
// stub or from the simulator.
|
||||
//
|
||||
// The arguments are stored in the Thread object.
|
||||
// Does not return.
|
||||
void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
|
||||
__ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset());
|
||||
__ LoadImmediate(R2, 0);
|
||||
|
||||
// Exception object.
|
||||
__ LoadFromOffset(kWord, R0, THR, Thread::active_exception_offset());
|
||||
__ StoreToOffset(kWord, R2, THR, Thread::active_exception_offset());
|
||||
|
||||
// Stacktrace object.
|
||||
__ LoadFromOffset(kWord, R1, THR, Thread::active_stacktrace_offset());
|
||||
__ StoreToOffset(kWord, R2, THR, Thread::active_stacktrace_offset());
|
||||
|
||||
__ bx(LR); // Jump to the exception handler code.
|
||||
}
|
||||
|
||||
|
|
|
@ -1902,24 +1902,20 @@ void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
// Jump to the exception or error handler.
|
||||
// Jump to a frame on the call stack.
|
||||
// LR: return address.
|
||||
// R0: program_counter.
|
||||
// R1: stack_pointer.
|
||||
// R2: frame_pointer.
|
||||
// R3: error object.
|
||||
// R4: address of stacktrace object.
|
||||
// R5: thread.
|
||||
// R3: thread.
|
||||
// Does not return.
|
||||
void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
||||
void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
|
||||
ASSERT(kExceptionObjectReg == R0);
|
||||
ASSERT(kStackTraceObjectReg == R1);
|
||||
__ mov(LR, R0); // Program counter.
|
||||
__ mov(SP, R1); // Stack pointer.
|
||||
__ mov(FP, R2); // Frame_pointer.
|
||||
__ mov(R0, R3); // Exception object.
|
||||
__ mov(R1, R4); // StackTrace object.
|
||||
__ mov(THR, R5);
|
||||
__ mov(THR, R3);
|
||||
// Set the tag.
|
||||
__ LoadImmediate(R2, VMTag::kDartTagId);
|
||||
__ StoreToOffset(R2, THR, Thread::vm_tag_offset());
|
||||
|
@ -1928,6 +1924,27 @@ void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
|||
// Restore the pool pointer.
|
||||
__ RestoreCodePointer();
|
||||
__ LoadPoolPointer();
|
||||
__ ret(); // Jump to continuation point.
|
||||
}
|
||||
|
||||
|
||||
// Run an exception handler. Execution comes from JumpToFrame
|
||||
// stub or from the simulator.
|
||||
//
|
||||
// The arguments are stored in the Thread object.
|
||||
// Does not return.
|
||||
void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
|
||||
__ LoadFromOffset(LR, THR, Thread::resume_pc_offset());
|
||||
__ LoadImmediate(R2, 0);
|
||||
|
||||
// Exception object.
|
||||
__ LoadFromOffset(R0, THR, Thread::active_exception_offset());
|
||||
__ StoreToOffset(R2, THR, Thread::active_exception_offset());
|
||||
|
||||
// Stacktrace object.
|
||||
__ LoadFromOffset(R1, THR, Thread::active_stacktrace_offset());
|
||||
__ StoreToOffset(R2, THR, Thread::active_stacktrace_offset());
|
||||
|
||||
__ ret(); // Jump to the exception handler code.
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,12 @@ void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
// Not executed, but used as a sentinel in Simulator::JumpToFrame.
|
||||
void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
|
||||
__ Trap();
|
||||
}
|
||||
|
||||
|
||||
// TODO(vegorov) Don't generate this stub.
|
||||
void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
|
||||
__ Trap();
|
||||
|
|
|
@ -1792,21 +1792,15 @@ void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
// Jump to the exception or error handler.
|
||||
// Jump to a frame on the call stack.
|
||||
// TOS + 0: return address
|
||||
// TOS + 1: program_counter
|
||||
// TOS + 2: stack_pointer
|
||||
// TOS + 3: frame_pointer
|
||||
// TOS + 4: exception object
|
||||
// TOS + 5: stacktrace object
|
||||
// TOS + 6: thread
|
||||
// TOS + 4: thread
|
||||
// No Result.
|
||||
void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
||||
ASSERT(kExceptionObjectReg == EAX);
|
||||
ASSERT(kStackTraceObjectReg == EDX);
|
||||
__ movl(THR, Address(ESP, 6 * kWordSize)); // Load target thread.
|
||||
__ movl(kStackTraceObjectReg, Address(ESP, 5 * kWordSize));
|
||||
__ movl(kExceptionObjectReg, Address(ESP, 4 * kWordSize));
|
||||
void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
|
||||
__ movl(THR, Address(ESP, 4 * kWordSize)); // Load target thread.
|
||||
__ movl(EBP, Address(ESP, 3 * kWordSize)); // Load target frame_pointer.
|
||||
__ movl(EBX, Address(ESP, 1 * kWordSize)); // Load target PC into EBX.
|
||||
__ movl(ESP, Address(ESP, 2 * kWordSize)); // Load target stack_pointer.
|
||||
|
@ -1818,6 +1812,29 @@ void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
// Run an exception handler. Execution comes from JumpToFrame stub.
|
||||
//
|
||||
// The arguments are stored in the Thread object.
|
||||
// No result.
|
||||
void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
|
||||
ASSERT(kExceptionObjectReg == EAX);
|
||||
ASSERT(kStackTraceObjectReg == EDX);
|
||||
__ movl(EBX, Address(THR, Thread::resume_pc_offset()));
|
||||
|
||||
// Load the exception from the current thread.
|
||||
Address exception_addr(THR, Thread::active_exception_offset());
|
||||
__ movl(kExceptionObjectReg, exception_addr);
|
||||
__ movl(exception_addr, Immediate(0));
|
||||
|
||||
// Load the stacktrace from the current thread.
|
||||
Address stacktrace_addr(THR, Thread::active_stacktrace_offset());
|
||||
__ movl(kStackTraceObjectReg, stacktrace_addr);
|
||||
__ movl(stacktrace_addr, Immediate(0));
|
||||
|
||||
__ jmp(EBX); // Jump to continuation point.
|
||||
}
|
||||
|
||||
|
||||
// Calls to the runtime to optimize the given function.
|
||||
// EBX: function to be reoptimized.
|
||||
// EDX: argument descriptor (preserved).
|
||||
|
|
|
@ -1985,19 +1985,13 @@ void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
|
|||
// A0: program_counter.
|
||||
// A1: stack_pointer.
|
||||
// A2: frame_pointer.
|
||||
// A3: error object.
|
||||
// SP + 4*kWordSize: address of stacktrace object.
|
||||
// SP + 5*kWordSize: address of thread.
|
||||
// A3: thread.
|
||||
// Does not return.
|
||||
void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
||||
void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
|
||||
ASSERT(kExceptionObjectReg == V0);
|
||||
ASSERT(kStackTraceObjectReg == V1);
|
||||
__ mov(V0, A3); // Exception object.
|
||||
// MIPS ABI reserves stack space for all arguments. The StackTrace object is
|
||||
// the last of five arguments, so it is first pushed on the stack.
|
||||
__ lw(V1, Address(SP, 4 * kWordSize)); // StackTrace object.
|
||||
__ mov(FP, A2); // Frame_pointer.
|
||||
__ lw(THR, Address(SP, 5 * kWordSize)); // Thread.
|
||||
__ mov(FP, A2); // Frame_pointer.
|
||||
__ mov(THR, A3); // Thread.
|
||||
// Set tag.
|
||||
__ LoadImmediate(A2, VMTag::kDartTagId);
|
||||
__ sw(A2, Assembler::VMTagAddress());
|
||||
|
@ -2006,11 +2000,34 @@ void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
|||
// Restore pool pointer.
|
||||
__ RestoreCodePointer();
|
||||
__ LoadPoolPointer();
|
||||
__ jr(A0); // Jump to the exception handler code.
|
||||
__ jr(A0); // Jump to the program counter.
|
||||
__ delay_slot()->mov(SP, A1); // Stack pointer.
|
||||
}
|
||||
|
||||
|
||||
// Run an exception handler. Execution comes from JumpToFrame
|
||||
// stub or from the simulator.
|
||||
//
|
||||
// The arguments are stored in the Thread object.
|
||||
// Does not return.
|
||||
void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
|
||||
__ lw(A0, Address(THR, Thread::resume_pc_offset()));
|
||||
__ LoadImmediate(A2, 0);
|
||||
|
||||
// Load the exception from the current thread.
|
||||
Address exception_addr(THR, Thread::active_exception_offset());
|
||||
__ lw(V0, exception_addr);
|
||||
__ sw(A2, exception_addr);
|
||||
|
||||
// Load the stacktrace from the current thread.
|
||||
Address stacktrace_addr(THR, Thread::active_stacktrace_offset());
|
||||
__ lw(V1, stacktrace_addr);
|
||||
|
||||
__ jr(A0); // Jump to continuation point.
|
||||
__ delay_slot()->sw(A2, stacktrace_addr);
|
||||
}
|
||||
|
||||
|
||||
// Calls to the runtime to optimize the given function.
|
||||
// T0: function to be reoptimized.
|
||||
// S4: argument descriptor (preserved).
|
||||
|
|
|
@ -1845,33 +1845,17 @@ void StubCode::GenerateGetStackPointerStub(Assembler* assembler) {
|
|||
}
|
||||
|
||||
|
||||
// Jump to the exception or error handler.
|
||||
// Jump to a frame on the call stack.
|
||||
// TOS + 0: return address
|
||||
// Arg1: program counter
|
||||
// Arg2: stack pointer
|
||||
// Arg3: frame_pointer
|
||||
// Arg4: exception object
|
||||
// Arg5: stacktrace object
|
||||
// Arg6: thread
|
||||
// Arg4: thread
|
||||
// No Result.
|
||||
void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
||||
ASSERT(kExceptionObjectReg == RAX);
|
||||
ASSERT(kStackTraceObjectReg == RDX);
|
||||
ASSERT(CallingConventions::kArg4Reg != kStackTraceObjectReg);
|
||||
ASSERT(CallingConventions::kArg1Reg != kStackTraceObjectReg);
|
||||
|
||||
#if defined(_WIN64)
|
||||
Register stacktrace_reg = RBX;
|
||||
__ movq(stacktrace_reg, Address(RSP, 5 * kWordSize));
|
||||
__ movq(THR, Address(RSP, 6 * kWordSize));
|
||||
#else
|
||||
Register stacktrace_reg = CallingConventions::kArg5Reg;
|
||||
__ movq(THR, CallingConventions::kArg6Reg);
|
||||
#endif
|
||||
void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
|
||||
__ movq(THR, CallingConventions::kArg4Reg);
|
||||
__ movq(RBP, CallingConventions::kArg3Reg);
|
||||
__ movq(RSP, CallingConventions::kArg2Reg);
|
||||
__ movq(kStackTraceObjectReg, stacktrace_reg);
|
||||
__ movq(kExceptionObjectReg, CallingConventions::kArg4Reg);
|
||||
// Set the tag.
|
||||
__ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartTagId));
|
||||
// Clear top exit frame.
|
||||
|
@ -1879,7 +1863,31 @@ void StubCode::GenerateJumpToExceptionHandlerStub(Assembler* assembler) {
|
|||
// Restore the pool pointer.
|
||||
__ RestoreCodePointer();
|
||||
__ LoadPoolPointer(PP);
|
||||
__ jmp(CallingConventions::kArg1Reg); // Jump to the exception handler code.
|
||||
__ jmp(CallingConventions::kArg1Reg); // Jump to program counter.
|
||||
}
|
||||
|
||||
|
||||
// Run an exception handler. Execution comes from JumpToFrame stub.
|
||||
//
|
||||
// The arguments are stored in the Thread object.
|
||||
// No result.
|
||||
void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
|
||||
ASSERT(kExceptionObjectReg == RAX);
|
||||
ASSERT(kStackTraceObjectReg == RDX);
|
||||
__ movq(CallingConventions::kArg1Reg,
|
||||
Address(THR, Thread::resume_pc_offset()));
|
||||
|
||||
// Load the exception from the current thread.
|
||||
Address exception_addr(THR, Thread::active_exception_offset());
|
||||
__ movq(kExceptionObjectReg, exception_addr);
|
||||
__ movq(exception_addr, Immediate(0));
|
||||
|
||||
// Load the stacktrace from the current thread.
|
||||
Address stacktrace_addr(THR, Thread::active_stacktrace_offset());
|
||||
__ movq(kStackTraceObjectReg, stacktrace_addr);
|
||||
__ movq(stacktrace_addr, Immediate(0));
|
||||
|
||||
__ jmp(CallingConventions::kArg1Reg); // Jump to continuation point.
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -93,6 +93,9 @@ Thread::Thread(Isolate* isolate)
|
|||
type_range_cache_(NULL),
|
||||
deopt_id_(0),
|
||||
pending_functions_(GrowableObjectArray::null()),
|
||||
active_exception_(Object::null()),
|
||||
active_stacktrace_(Object::null()),
|
||||
resume_pc_(0),
|
||||
sticky_error_(Error::null()),
|
||||
compiler_stats_(NULL),
|
||||
REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
|
||||
|
@ -215,6 +218,17 @@ void Thread::clear_pending_functions() {
|
|||
}
|
||||
|
||||
|
||||
void Thread::set_active_exception(const Object& value) {
|
||||
ASSERT(!value.IsNull());
|
||||
active_exception_ = value.raw();
|
||||
}
|
||||
|
||||
|
||||
void Thread::set_active_stacktrace(const Object& value) {
|
||||
active_stacktrace_ = value.raw();
|
||||
}
|
||||
|
||||
|
||||
RawError* Thread::sticky_error() const {
|
||||
return sticky_error_;
|
||||
}
|
||||
|
@ -606,6 +620,8 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor,
|
|||
reusable_handles_.VisitObjectPointers(visitor);
|
||||
|
||||
visitor->VisitPointer(reinterpret_cast<RawObject**>(&pending_functions_));
|
||||
visitor->VisitPointer(reinterpret_cast<RawObject**>(&active_exception_));
|
||||
visitor->VisitPointer(reinterpret_cast<RawObject**>(&active_stacktrace_));
|
||||
visitor->VisitPointer(reinterpret_cast<RawObject**>(&sticky_error_));
|
||||
|
||||
// Visit the api local scope as it has all the api local handles.
|
||||
|
|
|
@ -471,6 +471,22 @@ class Thread : public BaseThread {
|
|||
RawGrowableObjectArray* pending_functions();
|
||||
void clear_pending_functions();
|
||||
|
||||
RawObject* active_exception() const { return active_exception_; }
|
||||
void set_active_exception(const Object& value);
|
||||
static intptr_t active_exception_offset() {
|
||||
return OFFSET_OF(Thread, active_exception_);
|
||||
}
|
||||
|
||||
RawObject* active_stacktrace() const { return active_stacktrace_; }
|
||||
void set_active_stacktrace(const Object& value);
|
||||
static intptr_t active_stacktrace_offset() {
|
||||
return OFFSET_OF(Thread, active_stacktrace_);
|
||||
}
|
||||
|
||||
uword resume_pc() const { return resume_pc_; }
|
||||
void set_resume_pc(uword value) { resume_pc_ = value; }
|
||||
static uword resume_pc_offset() { return OFFSET_OF(Thread, resume_pc_); }
|
||||
|
||||
RawError* sticky_error() const;
|
||||
void set_sticky_error(const Error& value);
|
||||
void clear_sticky_error();
|
||||
|
@ -684,6 +700,11 @@ class Thread : public BaseThread {
|
|||
intptr_t deopt_id_; // Compilation specific counter.
|
||||
RawGrowableObjectArray* pending_functions_;
|
||||
|
||||
// JumpToExceptionHandler state:
|
||||
RawObject* active_exception_;
|
||||
RawObject* active_stacktrace_;
|
||||
uword resume_pc_;
|
||||
|
||||
RawError* sticky_error_;
|
||||
|
||||
CompilerStats* compiler_stats_;
|
||||
|
|
Loading…
Reference in a new issue