Status: New
Owner: ----

New issue 1505 by [email protected]: general protection fault due to misaligned addresses with sse in v8::internal::DateParser::Parse
http://code.google.com/p/v8/issues/detail?id=1505

We built the latest node v0.4 branch on illumos which is using v8 version 3.1.8.16 and gcc 4.5.2. node and v8 were built 32-bit.

We were running code that was parsing a lot of dates and observed a segmentation fault. When trying to reproduce it, we could occasionally; but not reliably, do so with the following code:

var d = 'Tue, 21 Jun 2011 18:55:';
new Date(d);

I took a brief look into why we were failing with mdb. First here's the stack at the time of the dump:

$C
fd8df128 _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x473(206e754a, 31313032, 3a383120, 323a3535, 4d472037, fe88e054
)
2c657554 0x20313220()
::dem _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE == v8::internal::DateParser::Parse<const char>

There are likely more Javascript stack frames, but mdb can't show them.

GCC optimized the function v8::internal::DateParser::Parse<const char> to use SSE operations. If we look at some of the relevant disassembled output in mdb:

_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x473::dis
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x44e:addl 0x38(%esp),%eax
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x452:cmpl
   %ecx,0x34(%esp)
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x456:movl 0x48(%esp),%ebx _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x45a:movl 0x4c(%esp),%edx
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x45e:
je +0xf <_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x46f> _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x460:movl $0x0,(%edi,%eax,4) _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x467:addl $0x1,%eax _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x46a:cmpl $0x2,%eax
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x46d:
jle -0xf <_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x460>
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x46f:movl
   %edx,0x4(%esp)
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x473:movdqa
 %xmm0,0x10(%esp)
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x479:movl
   %edi,(%esp)
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x47c:
call +0x21164f <_ZN2v88internal10DateParser12KeywordTable6LookupEPKji> _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x481:movdqa 0x10(%esp),%xmm0
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x487:
leal 0x850bee0(%eax,%eax,4),%edx <_ZN2v88internal10DateParser12KeywordTable5arrayE> _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x48e:movsbl 0x3(%edx),%eax _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x492:cmpl $0x3,%eax
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x495:
je +0xd5 <_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x570> _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x49b:cmpl $0x1,%eax
_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x49e:
je +0xec <_ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x590> _ZN2v88internal10DateParser5ParseIKcEEbNS0_6VectorIT_EEPNS0_10FixedArrayE+0x4a4:cmpl $0x2,%eax

We can see that at +0x473 we're doing a movdqa %xmm0,0x10(%esp).

The Intel Assembly manual says that it would raise a GP on the following conditions:

When the source or destination operand is a memory operand, the operand must be aligned on a 16-byte boundary or a general-protection exception (#GP) will be generated. To move integer data to and from unaligned memory locations, use the VMOVDQU instruction.

If we look at esp we see that it has the following value:

<esp=P
                0x80470c4

The instruction wanted 0x10(%esp) or 0x80470d4. My guess as to what's happening is that gcc is assuming that esp will be aligned and sometimes when v8 is making the jump from Javascript to C++ execution it ends up with an esp that is properly aligned and sometimes it isn't.

As a work around one can add -mno-sse to the SConstruct cflags. This problem doesn't manifest itself if the v8::internal::DateParser::Parse function does not get optimized to use the SSE registers.

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to