octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Please build the JIT branch


From: Michael Goffioul
Subject: Re: Please build the JIT branch
Date: Fri, 13 Jul 2012 12:37:08 +0100

On Fri, Jul 13, 2012 at 10:44 AM, Michael Goffioul <address@hidden> wrote:
On Fri, Jul 13, 2012 at 9:12 AM, Michael Goffioul <address@hidden> wrote:
I also tried the complex test:

a = b = 1+1i;
for ii=1:5
  a = a + b;
endfor

unfortunately it generates a segmentation fault (works fine without JIT). If the goal is to enforce calling convention, then I suggest you use the appropriate modifiers instead of extern "C". If you want I can give it a quick try here.

No luck, still crashing (I replaced all 'extern "C"' in pt-jit.cc with __cdecl equivalent). Debuggin shows it's crashing in octave_jit_cast_complex_any, when trying to access obv. It looks like obv is not a valid pointer, indicating a potential stack corruption.

I'm not sure this is related, but did you know that even with __cdecl, there's an ABI difference between MSVC and GCC when returning aggregate objects larger than 8 bytes (typically returning a double complex object). The object to return is provided through a hidden pointer pushed on the stack, but MSVC assumes the caller pops the hidden argument, while GCC assumes the callee pops it (note: this has been fixed in gcc-4.7.0, which is now compatible with MSVC). Another source of problems is stack-alignment, although I don't whether it's relevant in this case (MSVC aligns the stack on 4 bytes, GCC aligns it on 16 bytes).

I have no idea how the JIT is working, but if binary code is compiled on the fly for functions returning a large aggregate object, maybe the wrong ABI is being used, leading to stack corruption.


I did some more debugging to analyze what's going on and there's something wrong in the assembly code that is calling octave_jit_cast_complex_any. I've attached a screenshot of the disassembled code: function starts at 02CB00E0 and ends at 02CB010E, you can recognize the standard prologue and epilogue of x86.

If you inspect how the stack is constructed before calling octave_jit_cast_complex_any, you can see that:
- 24 bytes are allocated on the stack (02CB00E9, that's 3 double's, let's call them d1, d2 and d3)
- EAX is copied at the top of the stack, at this point EAX is the "octave_base_value* obv" argument, so it's basically the first argument of the function; it occupies the location d1 on the stack
- after octave_jit_cast_complex_any call, results are pulled from the stack at location d2 and d3

This does not correspond to the ABI MSVC is using. Instead of pushing a hidden pointer on the top of the stack (as it should do), it allocates the memory for the returned complex value on the stack and *after* the regular function arguments. Of course, when octave_jit_cast_complex_any tries to access obv, it points to invalid memory and crashes.

What kind of ABI is this?

Michael.

Attachment: jit_dbg1.png
Description: PNG image


reply via email to

[Prev in Thread] Current Thread [Next in Thread]