JIT machine code deletion

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

JIT machine code deletion

Chris Lattner

Hi All,

I just implemented an often-requested feature: the ability to delete
machine code out of the JIT's code buffer (the
ExecutionEngine::freeMachineCodeForFunction(F) method).

The implementation uses a very general free-list mechanism for tracking
free ranges in the buffer, and it works perfectly in my simple test cases
designed to cover all of the code paths.  However, I don't have any good
"real world" way to test this thoroughly.

If you have an application for this API, please try it out.  Remember
that, once deleted, the memory for a function can be reused for other
functions.  This means you should only call this method if you *know* that
execution could never reach this function again.  As a sanity check, in
debug builds, I memset the freed buffer with garbage to try to make it
obvious if the buffer is called into.

If you don't *know* that all (e.g.) function pointers to this code are
dead (which means that execution could come back to the function), you
should use the ExecutionEngine::recompileAndRelinkFunction(F) method.

I'm happy to answer any questions about this functionality, as usual.

-Chris

--
http://nondot.org/sabre/
http://llvm.org/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: JIT machine code deletion

Ralph Corderoy

Hi Chris,

> If you don't *know* that all (e.g.) function pointers to this code are
> dead (which means that execution could come back to the function), you
> should use the ExecutionEngine::recompileAndRelinkFunction(F) method.

recompileAndRelinkFunction() overwrites the old machine code with a
branch to the new.  Is it always guaranteed that there's space to write
the new branch instructions?  A quick look suggests the x86 takes five
bytes, PowerPC 16, and the Alpha's implementation is an assert(0) but if
it did call its EmitBranchToAt() then that would be 76.  Could the
original machine code be smaller?

Cheers,


Ralph.


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: JIT machine code deletion

Chris Lattner
On Fri, 12 May 2006, Ralph Corderoy wrote:
>> If you don't *know* that all (e.g.) function pointers to this code are
>> dead (which means that execution could come back to the function), you
>> should use the ExecutionEngine::recompileAndRelinkFunction(F) method.
>
> recompileAndRelinkFunction() overwrites the old machine code with a
> branch to the new.  Is it always guaranteed that there's space to write
> the new branch instructions?

Yes.

> A quick look suggests the x86 takes five
> bytes, PowerPC 16,

PPC should be 4 bytes in the normal case.  It is up to the backend to
implement this API correctly... if it doesn't, that's a bug: please
report it!

-Chris

--
http://nondot.org/sabre/
http://llvm.org/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: JIT machine code deletion

Ralph Corderoy

Hi Chris,

> On Fri, 12 May 2006, Ralph Corderoy wrote:
> > recompileAndRelinkFunction() overwrites the old machine code with a
> > branch to the new.  Is it always guaranteed that there's space to
> > write the new branch instructions?
>
> Yes.

OK.

> > A quick look suggests the x86 takes five bytes, PowerPC 16,
>
> PPC should be 4 bytes in the normal case.  It is up to the backend to
> implement this API correctly... if it doesn't, that's a bug: please
> report it!

No, EmitBranchToAt() always emits 16 bytes.

    AtI[0] = BUILD_LIS(12, Addr >> 16);   // lis r12, hi16(address)
    AtI[1] = BUILD_ORI(12, 12, Addr);     // ori r12, r12, low16(address)
    AtI[2] = BUILD_MTCTR(12);             // mtctr r12
    AtI[3] = BUILD_BCTR(isCall);          // bctr/bctrl

but I understand now how startFunctionStub() is given StubSize and on
PowerPC it's 16 so there's no problem.

Cheers,


Ralph.


_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: JIT machine code deletion

Chris Lattner
On Sun, 14 May 2006, Ralph Corderoy wrote:

>> PPC should be 4 bytes in the normal case.  It is up to the backend to
>> implement this API correctly... if it doesn't, that's a bug: please
>> report it!
>
> No, EmitBranchToAt() always emits 16 bytes.
>
>    AtI[0] = BUILD_LIS(12, Addr >> 16);   // lis r12, hi16(address)
>    AtI[1] = BUILD_ORI(12, 12, Addr);     // ori r12, r12, low16(address)
>    AtI[2] = BUILD_MTCTR(12);             // mtctr r12
>    AtI[3] = BUILD_BCTR(isCall);          // bctr/bctrl
>
> but I understand now how startFunctionStub() is given StubSize and on
> PowerPC it's 16 so there's no problem.

Ah, that's silly.  If the source and target are within range (as they
should almost always be), a simple unconditional branch should be used.
Patches welcome :)

-Chris

--
http://nondot.org/sabre/
http://llvm.org/

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev