On Wed, Sep 29, 2010 at 6:38 PM, Igor Stasenko <siguctua(a)gmail.com> wrote:
> On 30 September 2010 03:39, Eliot Miranda <eliot.miranda(a)gmail.com> wrote:
> >> Can Cog inline message sends? I thought it can't ATM.
> > Right. But the thought is that because Cog does inline machine-code for
> > certain primitives (actually it generates machine-code versions of core
> > primitives) that with a little work NB would be able to generate the
> > code for primitives that Cog's code generator doesn't handle.
> > Igor will correct me if I'm wrong but I think the idea is thus.
> You are right here.
> > NB-generated code needs to be stored somewhere in a CompiledMethod where
> > Cog can find it,
> This is trivial. Its stored right after last bytecode in compiled method :)
No, it's not trivial. Cog doesn't know how to distinguish an NB trailer
form any old trailer. personally I'd prefer to see the NB code in a special
location in the literal frame (e.g. the first literal) using an instance of
a class that can't be a literal. Either that, or a bit in the
CompiledMethod header should indicate that the trailer contains the code.
(Oh, but I see below you're thinking of a specific primitive number; that's
good). Also, if the NB code /is/ in the trailer, how does Cog know where it
ends, sicne presumably the trailer includes other stuff after the trailer
> > along with some link-edit metadata to allow Cog to fix-up
> > data references in the code etc.
> No need. The generated code is position agnostic, and its using
> interpreterProxy api for
> speaking with VM. No position/object memory dependent data is stored there.
> You can copy it anywhere you want and it will still work correctly.
> Native code during its interaction with VM fully relies on
> interpreterProxy interface (as any other primitive).
So the NB code uses absolute addressing to get hold of the interpreterProxy,
right? Depending on what the primitive is doing using interpreterProxy may
be OK or may have poor performance. A little bit of metadata woudl allow NB
direct access to certain variables and allow it to short-circuit the slow
double-indirect calls through interpreterProxy.
A native code is a function of kind:
> sqInt nativeFunction();
> if its not fails, it should return a valid oop.
> So, after call you simply check if prim not failed:
> result := self fnPtr. "fnPtr is native code"
> self failed ifFalse: [
> interpreterProxy pop: argCount + 1 thenPush: result.
> ] ifTrue: [ lastError := interpreterProxy
> but of course, for inlined code we can change that , in order to
> generate even more optimal code :)
> > If Cog finds a method containing NB code
> > it copies this code into the start of the method (where primitive code is
> > compiled) and does some simple link-editing on the code. Now the Cog
> > starts with NB code which operates ;like a primitive, jumping to the
> > of the Cog method proper if it fails.
> A sketch idea is following:
> - reserve a special primitive number for 'a compiled method with
> native code, which can be inlined'.
Yes. That's nice.
> Then you can easily detect in Cog inliner, if method can be inlined
> after some extra checks:
> Method could have such primitive, but may not have a native code,
> since its not yet generated. Then you simply 'fail prim'
> - i.e. simply go and run method interpreted.
> This is what i am actually checking/doing each time before making a native
> Once everything right (it finds a correct native code within a
> method), its then free to either make a call to it or inline it.
> And as i understood, from image side, we have to guarantee that such
> special inlined code
> won't overflow the stack , so Cog won't need to switch stack pointer
> to C stack before running it.
Right. But Cog stack pages have a generous headroom so you can count on 256
bytes of headroom. But we'd have to specify this. Hopefully 256 bytes is
enough for something that runs on the Smalltalk stack since one could argue
that if it uses lots of stack its probably going to run for a whole and so
the overhead of switching to/from teh C stack is affordable. i.e. run only
small performance-critical things on the Smalltalk stack.
> Or, if you extend interpreterProxy with something like
> pleaseMakeSureIAmUsingCStack() and
> then NB could generate a code which will call these things
> before/after external calls,
> and so, Cog are free to inline even code which may contain external calls.
How about a primitive that says "run this code on the C stack" and one that
says "run this on the native stack"?
> > If we're talking about NB FFI calls then there's additional compilations.
> > stack switch is required from Cog's stack pages to the real C stack, and
> > back on return, etc. But I'm encouraged that Igor has already got NB
> > on Cog.
> It wasn't hard.
> I have to match interpreterProxy interface with Cog's one. (Btw i am
> really miss the getStackPointer(),
> which currently not implemented in Cog VM, i would be happy to have
> this function available without Alien plugin :)
I think thats very easy to add :)
> Second, i changed two methods which were responsible for marchalling
> Float instances, since Cog
> storing them in native format, while Squeak in big endian.
> >> Btw, can you send a message from NB code?
> > As I understand it, no.
> Of course it can't, because native code runs as a primitive.
> Primitive can't do sends, because then obviously, it has to enter
> interpreter loop ( via call to interpret()),
> and once send complete, somehow, it should again continue to run native
> So, its implementation will be much more like a callback mechanism,
> which already there.
> With NB you can create a native function with callback, then you
> making an FFI callout to that function
> and when it calls back, you can do 'message send from NB code' or
> whatever you want.
> So, roughly speaking it could be seen as a way to do a message sends
> from native code :)
> > best
> > Eliot
> >> Levente
> >>> --
> >>> Best regards,
> >>> Igor Stasenko AKA sig.
> Best regards,
> Igor Stasenko AKA sig.