Fix bug restoring of JS entry sp so to fix profiler-related valgrind issues.

The profiler did not correctly identify when there was a JS frame
on the stack after an exception was thrown.

I also refactored the code to use PopTryHandler macro-instructions on all platforms

BUG=73722
TEST=No more valgrind errors related to v8::internal::StackFrameIterator.
Review URL: http://codereview.chromium.org/7019010

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7910 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
fschneider@chromium.org 2011-05-17 11:11:12 +00:00
parent 9bddc8e0d8
commit 7d446f7f4c
4 changed files with 52 additions and 41 deletions

View File

@ -3564,11 +3564,20 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
#ifdef ENABLE_LOGGING_AND_PROFILING
// If this is the outermost JS call, set js_entry_sp value.
Label non_outermost_js;
ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate);
__ mov(r5, Operand(ExternalReference(js_entry_sp)));
__ ldr(r6, MemOperand(r5));
__ cmp(r6, Operand(0, RelocInfo::NONE));
__ str(fp, MemOperand(r5), eq);
__ cmp(r6, Operand(0));
__ b(ne, &non_outermost_js);
__ str(fp, MemOperand(r5));
__ mov(ip, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
Label cont;
__ b(&cont);
__ bind(&non_outermost_js);
__ mov(ip, Operand(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
__ bind(&cont);
__ push(ip);
#endif
// Call a faked try-block that does the invoke.
@ -3626,27 +3635,22 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ mov(lr, Operand(pc));
masm->add(pc, ip, Operand(Code::kHeaderSize - kHeapObjectTag));
// Unlink this frame from the handler chain. When reading the
// address of the next handler, there is no need to use the address
// displacement since the current stack pointer (sp) points directly
// to the stack handler.
__ ldr(r3, MemOperand(sp, StackHandlerConstants::kNextOffset));
__ mov(ip, Operand(ExternalReference(Isolate::k_handler_address, isolate)));
__ str(r3, MemOperand(ip));
// No need to restore registers
__ add(sp, sp, Operand(StackHandlerConstants::kSize));
#ifdef ENABLE_LOGGING_AND_PROFILING
// If current FP value is the same as js_entry_sp value, it means that
// the current function is the outermost.
__ mov(r5, Operand(ExternalReference(js_entry_sp)));
__ ldr(r6, MemOperand(r5));
__ cmp(fp, Operand(r6));
__ mov(r6, Operand(0, RelocInfo::NONE), LeaveCC, eq);
__ str(r6, MemOperand(r5), eq);
#endif
// Unlink this frame from the handler chain.
__ PopTryHandler();
__ bind(&exit); // r0 holds result
#ifdef ENABLE_LOGGING_AND_PROFILING
// Check if the current stack frame is marked as the outermost JS frame.
Label non_outermost_js_2;
__ pop(r5);
__ cmp(r5, Operand(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
__ b(ne, &non_outermost_js_2);
__ mov(r6, Operand(0));
__ mov(r5, Operand(ExternalReference(js_entry_sp)));
__ str(r6, MemOperand(r5));
__ bind(&non_outermost_js_2);
#endif
// Restore the top frame descriptors from the stack.
__ pop(r3);
__ mov(ip,

View File

@ -152,6 +152,12 @@ class StackFrame BASE_EMBEDDED {
NO_ID = 0
};
// Used to mark the outermost JS entry frame.
enum JsFrameMarker {
INNER_JSENTRY_FRAME = 0,
OUTERMOST_JSENTRY_FRAME = 1
};
struct State {
State() : sp(NULL), fp(NULL), pc_address(NULL) { }
Address sp;

View File

@ -4197,7 +4197,12 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ cmp(Operand::StaticVariable(js_entry_sp), Immediate(0));
__ j(not_equal, &not_outermost_js);
__ mov(Operand::StaticVariable(js_entry_sp), ebp);
__ push(Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
Label cont;
__ jmp(&cont);
__ bind(&not_outermost_js);
__ push(Immediate(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)));
__ bind(&cont);
#endif
// Call a faked try-block that does the invoke.
@ -4243,23 +4248,19 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ call(Operand(edx));
// Unlink this frame from the handler chain.
__ pop(Operand::StaticVariable(ExternalReference(
Isolate::k_handler_address,
masm->isolate())));
// Pop next_sp.
__ add(Operand(esp), Immediate(StackHandlerConstants::kSize - kPointerSize));
__ PopTryHandler();
__ bind(&exit);
#ifdef ENABLE_LOGGING_AND_PROFILING
// If current EBP value is the same as js_entry_sp value, it means that
// the current function is the outermost.
__ cmp(ebp, Operand::StaticVariable(js_entry_sp));
// Check if the current stack frame is marked as the outermost JS frame.
__ pop(ebx);
__ cmp(Operand(ebx), Immediate(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)));
__ j(not_equal, &not_outermost_js_2);
__ mov(Operand::StaticVariable(js_entry_sp), Immediate(0));
__ bind(&not_outermost_js_2);
#endif
// Restore the top frame descriptor from the stack.
__ bind(&exit);
__ pop(Operand::StaticVariable(ExternalReference(
Isolate::k_c_entry_fp_address,
masm->isolate())));

View File

@ -3270,9 +3270,14 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ Load(rax, js_entry_sp);
__ testq(rax, rax);
__ j(not_zero, &not_outermost_js);
__ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ movq(rax, rbp);
__ Store(js_entry_sp, rax);
Label cont;
__ jmp(&cont);
__ bind(&not_outermost_js);
__ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
__ bind(&cont);
#endif
// Call a faked try-block that does the invoke.
@ -3314,25 +3319,20 @@ void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
__ call(kScratchRegister);
// Unlink this frame from the handler chain.
Operand handler_operand =
masm->ExternalOperand(ExternalReference(Isolate::k_handler_address,
isolate));
__ pop(handler_operand);
// Pop next_sp.
__ addq(rsp, Immediate(StackHandlerConstants::kSize - kPointerSize));
__ PopTryHandler();
__ bind(&exit);
#ifdef ENABLE_LOGGING_AND_PROFILING
// If current RBP value is the same as js_entry_sp value, it means that
// the current function is the outermost.
__ movq(kScratchRegister, js_entry_sp);
__ cmpq(rbp, Operand(kScratchRegister, 0));
// Check if the current stack frame is marked as the outermost JS frame.
__ pop(rbx);
__ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
__ j(not_equal, &not_outermost_js_2);
__ movq(kScratchRegister, js_entry_sp);
__ movq(Operand(kScratchRegister, 0), Immediate(0));
__ bind(&not_outermost_js_2);
#endif
// Restore the top frame descriptor from the stack.
__ bind(&exit);
{
Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
__ pop(c_entry_fp_operand);