<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 20, 2016 at 7:51 PM, Ben Coman <span dir="ltr"><<a href="mailto:btc@openinworld.com" target="_blank">btc@openinworld.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div class=""><div class="h5"><br>
On Fri, May 20, 2016 at 9:25 PM, Clément Bera <<a href="mailto:bera.clement@gmail.com">bera.clement@gmail.com</a>> wrote:<br>
><br>
><br>
><br>
> On Thu, May 19, 2016 at 3:42 PM, Ben Coman <<a href="mailto:btc@openinworld.com">btc@openinworld.com</a>> wrote:<br>
>><br>
>><br>
>> The hierarchy goes<br>
>> VMClass<br>
>> InterpreterPrimitives<br>
>> StackIntepreter<br>
>> StackIntepreterPrimitives<br>
>> CoInterpreter<br>
>> CoInterpreterPrimitives<br>
>><br>
>> from which a tick / tock (XXInterpreter / XXInterpreterPrimitives)<br>
>> pattern is apparent,<br>
>> and I wonder why Interpreter is missing above InterpreterPrimitives<br>
>> sitting off to the side. I guess it is something to do with<br>
>> InterpreterPrimitives composing objectMemory as an instance variable<br>
>> rather than inheriting from ObjectMemory as Interpeter does?<br>
><br>
><br>
> I think this is exactly that.<br>
><br>
>><br>
>> The reason I ask is that I'm trying a new approach to the OwnedLock primitives<br>
>> where if waitAcquire primitive sleeps, when the process wakes up it<br>
>> retries the primitive.<br>
>> So effectively the process sleeps at the top of the waitAquire rather<br>
>> than the bottom,<br>
>> and the process truly cannot proceed past that point until it gains<br>
>> the lock. I have this working if StackInterpreterPrimitives holds the<br>
>> primitive, but if I move the primitive to InterpreterPrimitives,<br>
>> instructionPointer is unknown.<br>
>><br>
><br>
> In general, you implement in InterpreterPrimitives the primitives that would work with the Interpreter, and in StackInterpreterPrimitives the ones specific to the StackInterpreter. If you have a bug in InterpreterPrimitives, it's likely to be specific to the StackInterpreter.<br>
><br>
> In the future the Cog branch may merge with the trunk, hence Interpreter will be back in the hierarchy.<br>
><br>
>><br>
>><br>
>> P.S. For the curious, here is the proof of concept I tried. A single<br>
>> call to the primitive counts up to four by backing up the<br>
>> instructionPointer such that the primitive is executed again, until<br>
>> the exit condition of four is reached.<br>
>><br>
>> (Note the use of Semaphore and ExcessSignalsIndex is not significant,<br>
>> just an expedient template I was familiar with.)<br>
>><br>
>> # VM SIDE...<br>
>><br>
>> StackInterpreterPrimitives >> primitiveRetryExperiment<br>
>> | excessSignals stackTop |<br>
>> stackTop := self stackTop.<br>
>> excessSignals := objectMemory fetchInteger: ExcessSignalsIndex<br>
>> ofObject: stackTop.<br>
>> excessSignals := excessSignals + 1.<br>
>> objectMemory storeInteger: ExcessSignalsIndex<br>
>> ofObject: stackTop<br>
>> withValue: excessSignals.<br>
>> [ excessSignals > 3 ] ifFalse: [ instructionPointer :=<br>
>> instructionPointer - 1 ].<br>
>><br>
>> StackInterpreter class >> initializePrimitiveTable<br>
>> (234 primitiveRetryExperiment)<br>
>><br>
><br>
> ... Why instructionPointer - 1 ?<br>
<br>
</div></div>A random experiment before moving on to -2, -3 and -4. Obviously I<br>
don't know enough yet to have properly judged its impact. Just poking<br>
it with a stick to see what pops out, and following that old adage<br>
that if you need something to be true, "assume it" until you learn<br>
otherwise. And whadayaknow..., it worked for the StackInterpreter.<br>
And I've since learnt its not so easy for the JIT.<br>
<span class=""><br>
> It works if the send is encoded in a single byte as by chance is the case in your example, else your interpretation get misaligned, which is a complete nonsense (unless you're working with a Smalltalk-78 VM ;-) ). Going backward in the instructions is not that trivial, you need a scanner to find the previous pc.<br>
<br>
</span>I thought *maybe* that since the layout of the receiver is "known" (to<br>
be an OwnedLock) the previous pc could be assumed at a known distance<br>
up the stack - but maybe that is bad practice and trouble if the<br>
layout changes for anyone subclassing OwnedLock.<br>
<span class=""><br></span></blockquote><div><br></div><div>I don' really understand that known layout of the receiver thing. </div><div><br></div><div>The problem is with the encoding of sends in the bytecode. They are encoded in different number of bytes to lower the memory footprint.</div><div><br></div><div>For example, in Pharo, in this method:</div><div>foo</div><div> <span style="font-family:monospace,monospace">PrimExp new primRetryExperiment excessSignals</span></div><div><span style="font-family:monospace,monospace"><br></span></div><div><span style="font-family:monospace,monospace">=> </span><font face="monospace, monospace">27 <D1> send: primRetryExperiment</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="arial, helvetica, sans-serif">the send to </font><span style="font-family:monospace,monospace">primRetryExperiment</span><span style="font-family:arial,helvetica,sans-serif"> is encoded in a single byte.</span></div><div><font face="monospace, monospace"><br></font></div><div>But in this method:</div><div><div><font face="monospace, monospace">foo</font></div><div><font face="monospace, monospace"><span style="white-space:pre"> </span>self foo1 foo2 foo3 foo4 foo5 foo6 foo7 foo8 </font></div><div><font face="monospace, monospace"> self foo9 foo10 foo11 foo12 foo13 foo14 foo15 foo16.</font></div><div><font face="monospace, monospace"> PrimExp new primRetryExperiment excessSignals</font></div></div><div><span style="font-family:monospace,monospace"><br></span></div><div><font face="monospace, monospace">=> 109 <83 11> send: primRetryExperiment</font><br></div><div><font face="monospace, monospace"><br></font></div><div><font face="arial, helvetica, sans-serif">The same send is encoded in 2 bytes.</font></div><div><font face="arial, helvetica, sans-serif"><br></font></div><div>So, after the send, in the primitive code, you need the instruction pointer to go back by 1 or 2 bytes to repeat the send. But you don't know by how many bytes. <span style="font-family:arial,helvetica,sans-serif">There is no easy way to guess if it's 1 or 2 (or something else, there are other cases I omitted).</span></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span class="">
> See #skipBackBeforeJump for example, which goes backward 1 instruction in the image side. You need to implement something similar in the interpreter if you want to do that... but you don't.<br>
<br>
</span>I'll take a look just for interest, but point taken.<br>
<span class=""><br>
> Although going back one instruction is very funny, it won't work with the JIT, unless you do something completely evil, crazy and hackish.<br>
<br>
</span>That was the advice I was looking for. I don't want to be hackish ;)<br>
At least not in the final result.<br>
<span class=""><br>
> Most likely you want in fact to implement your primitive with a while loop instead, so you don't need that ip modification hack. Why didn't you do a while loop in the first place ?<br>
<br>
</span>A loop in the Image would work, but I'm attempting to keep it in the<br>
VM. IIUC a loop won't work in the VM because the primitive sleeps and<br>
changes context if the lock is held by someone else.<br></blockquote><div><br></div><div>hum. If I change your example to:</div><div><br></div><font face="monospace, monospace"><span style="color:rgb(80,0,80)">StackInterpreterPrimitives >> primitiveRetryExperiment</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"> | excessSignals stackTop |</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"> stackTop := self stackTop.</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"> excessSignals := objectMemory fetchInteger: ExcessSignalsIndex</span><span style="color:rgb(80,0,80)"> ofObject: stackTop.</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"> [ </span><span style="color:rgb(80,0,80)">excessSignals > 3 ] whileFalse: [</span></font></div><div class="gmail_quote"><font face="monospace, monospace"><span style="color:rgb(80,0,80)"> excessSignals := excessSignals + 1.</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"> objectMemory storeInteger: ExcessSignalsIndex</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"> ofObject: stackTop</span><br style="color:rgb(80,0,80)"><span style="color:rgb(80,0,80)"> withValue: excessSignals</span><span style="color:rgb(80,0,80)"> ].</span> </font></div><div class="gmail_quote"><br></div><div class="gmail_quote">It's exactly equivalent to what you wrote, isn't it ? There is no process switch - context switch - in both cases in the loop, isn't it ? Or maybe I am missing something ?</div><div class="gmail_quote"><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<span class=""><br>
> Primitive calls are not interrupt points anyway, it would be exactly the same behavior, wouldn't it ?<br>
><br>
>><br>
>><br>
>> # IMAGE SIDE...<br>
>><br>
>> Semaphore subclass: #PrimExp<br>
>> instanceVariableNames: ''<br>
>> classVariableNames: ''<br>
>> package: '0PrimitiveRetryExperiment'<br>
>><br>
>> PrimExp >> initialize<br>
>> excessSignals := 1.<br>
>><br>
>> PrimExp >> primRetryExperiment<br>
>> <primitive: 234><br>
>><br>
>> PrimExp >> excessSignals<br>
>> ^ excessSignals<br>
>><br>
>> # TEST CASE...<br>
>><br>
>> PrimExp new primRetryExperiment excessSignals<br>
>> --> 4<br>
>><br>
>> I've only done this with the Stack VM so far. I'll report further<br>
>> when I try it with Cog.<br>
<br>
</span>So I found the approach doesn't work with Cog.<br>
cheers -ben<br>
<div class=""><div class="h5"><br>
><br>
> It's nice to see people trying to hack the VM :-). I'll try to answer your other questions.<br>
</div></div></blockquote></div><br></div></div>