<br><br><div class="gmail_quote">On Wed, Jan 25, 2012 at 1:32 PM, stephane ducasse <span dir="ltr">&lt;<a href="mailto:stephane.ducasse@gmail.com">stephane.ducasse@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
for the record mariano, VW implementation of method wrapper had a template of method one for each number of possible args<br>
and they reserved space in the compiled method to be able to binding the class name (from memory) so installing one was copy of the right template + homeClass + selector (not sure anymore) so it was quite fast and simple to read.<br>
</blockquote><div><br></div><div>and the same thing is in my port to 4.2, MethodWrappers4.2 on squeaksource.  See MwMethodWrapper&#39;s class instance variable protoMethods.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
Stef<br>
<div class="im"><br>
On Jan 25, 2012, at 7:36 PM, Mariano Martinez Peck wrote:<br>
<br>
&gt;<br>
&gt;<br>
&gt; Ok. I will try to give it a try to this approach as well.<br>
&gt; But what happened with the version I attached in the previous email that uses a template method and just change the arguments number?<br>
&gt;<br>
&gt; That would be fine.  I didn&#39;t look.<br>
&gt;<br>
&gt;<br>
</div>&gt; Since I am quite newbie here and the change can be quite important, I would really appreciate if someone can take a look to the .cs so that I feel confident to commit it :)<br>
<div class="im">&gt;<br>
&gt;<br>
&gt; but I get lost to get this working...the previous solution seems easier.<br>
&gt;<br>
&gt; Do you want to build Trabants or BMWs?<br>
&gt;<br>
&gt; I didn&#39;t understand. Which solution which be each car?<br>
&gt;<br>
&gt; Compiling from source each time = trabant.  Synthesizing directly = vw.   Using a template method = bmw.<br>
&gt;<br>
&gt; (vw = VisualWorks ;) )<br>
&gt;<br>
&gt;<br>
</div>&gt; :):):):)<br>
&gt;<br>
&gt; Nice because it means that we found a fast solution yet quite understandable :)<br>
<div class="im">&gt;<br>
&gt;<br>
&gt;<br>
&gt; Documentation helps.<br>
&gt;<br>
&gt;<br>
&gt; I didn&#39;t understand either. If you refer to the fact I didn&#39;t put comments in the .cs I attached, I explicitly said in my previous email &quot;If you agree, I can put a nice comment and commit.&quot;. It already took me the whole morning (yes, I am completly noob here) to do the version of changing the argument count, so I was waiting the confirmation in the solution before documenting it and make it better.<br>

&gt;<br>
&gt; I mean in general if one builds good quality code that is &quot;clever&quot; then that code needs to be documented.  Sometimes simple doesn&#39;t cut it (look at the complexity involved in making a VM fast).  So if simple doesn&#39;t cut it one must document.<br>

&gt;<br>
</div>&gt; Agree. Once someone gives me the OK for my .cs, I will add comments and commit.<br>
&gt;<br>
&gt; Thanks Eliot.<br>
<div><div></div><div class="h5">&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Thanks!<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; On Tue, Jan 24, 2012 at 11:01 PM, Mariano Martinez Peck &lt;<a href="mailto:marianopeck@gmail.com">marianopeck@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt;<br>
&gt; Analogously, one needs a way of invoking named primitives in the debugger, and using tryNamedPrimitive[:with:with:...] et al has exactly the same weaknesses as tryPrimitiveN above.  So introducing a primitive to run named primitives is in keeping with tryPrimitive:withArgs:.  Using the VisualWorks approach is feasible but violates Occam&#39;s razor.<br>

&gt;<br>
&gt; What what about temporally (to be removed in the future) just when we are using older VMs?<br>
&gt;<br>
&gt; If temporary, then fine.  But its all work :)<br>
&gt;<br>
&gt;<br>
&gt; Well...writing papers can be boring ;)<br>
&gt; Please, could you take a look to the attached .cs?  I tried to do what I had in mind. Since this part of the system is new for me, I have not sure it is correct, nor how to test it. So far what I did for testing it is to take the  #tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments<br>

&gt; and (temporally) remove the &lt;primitive: 218 error: ec&gt; and define &#39;ec&#39; as a temporal variable. Since it will be nil, the following code will be executed.<br>
&gt; Then I put a halt in #open: fileName forWrite: writeMode   from StandardFileStream and then I do it:<br>
&gt; FileDirectory default forceNewFileNamed: &#39;xxxxx&#39;.<br>
&gt; Once in the debugger, I went to:<br>
&gt;<br>
&gt; StandardFileStream retryWithGC:[self primOpen: f writable: writeMode]<br>
&gt;                     until:[:id| id notNil]<br>
&gt;                     forFileNamed: fileName.<br>
&gt;<br>
&gt; did a &quot;through&quot; in the close, and be sure I could do &quot;into&quot; and &quot;step&quot; for #self primOpen: f writable: writeMode  (which is a named primitive).<br>
&gt;<br>
&gt; is this ok?<br>
&gt;<br>
&gt; Thanks Eliot!<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Why do we need them in ProtoObject?<br>
&gt;<br>
&gt; Once tryNamedPrimitiveIn:for:withArgs: is implemented in all relevant virtual machines we don&#39;t need them.  You&#39;ll notice that there is no trace of the tryPrimitiveN methods anymore, even though they&#39;re in Smalltalk-80.<br>

&gt;<br>
&gt; Because I&#39;m not sure that adding primitive to VM is always a good solution.<br>
&gt;<br>
&gt; Agreed.  But it is in keeping with the primitive for invoking numbered primitives,  tryPrimitive:withArgs:.<br>
&gt;<br>
&gt;<br>
&gt; HTH<br>
&gt; Eliot<br>
&gt;<br>
&gt;<br>
&gt; Stef<br>
&gt;<br>
&gt; &gt; On Mon, Jan 23, 2012 at 8:52 AM, Mariano Martinez Peck &lt;<a href="mailto:marianopeck@gmail.com">marianopeck@gmail.com</a>&gt; wrote:<br>
&gt; &gt; Hi guys. I usually like to take a look to ProtoObject and see what is really needed for the minimal object. But having 30% of the methods being  #tryNamedPrimitive:with: *  is not fun.<br>
&gt; &gt; So...I wonder, do you think there could be another way so that to avoid having all those methods in ProtoObject ?<br>
&gt; &gt;<br>
&gt; &gt; Yes there is.  I implemented primitive 218 in Cog, primitiveDoNamedPrimitiveWithArgs, which is accessed via<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;               tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments<br>
&gt; &gt;                       | selector theMethod spec receiverClass |<br>
&gt; &gt;                       &lt;primitive: 218 error: ec&gt;<br>
&gt; &gt;                       ec ifNotNil:<br>
&gt; &gt;                               [&quot;If ec is an integer other than -1 there was a problem with primitive 218,<br>
&gt; &gt;                                 not with the external primitive itself.  -1 indicates a generic failure (where<br>
&gt; &gt;                                 ec should be nil) but ec = nil means primitive 218 is not implemented.  So<br>
&gt; &gt;                                 interpret -1 to mean the external primitive failed with a nil error code.&quot;<br>
&gt; &gt;                                ec isInteger ifTrue:<br>
&gt; &gt;                                       [ec = -1<br>
&gt; &gt;                                               ifTrue: [ec := nil]<br>
&gt; &gt;                                               ifFalse: [self primitiveFailed]].<br>
&gt; &gt;                               ^{PrimitiveFailToken. ec}].<br>
&gt; &gt;                       &quot;Assume a nil error code implies the primitive is not implemented and fall back on the old code.&quot;<br>
&gt; &gt;                       &quot;Hack. Attempt to execute the named primitive from the given compiled method&quot;<br>
&gt; &gt;                       arguments size &gt; 8 ifTrue:<br>
&gt; &gt;                               [^{PrimitiveFailToken. nil}].<br>
&gt; &gt;                       selector := #(<br>
&gt; &gt;                               tryNamedPrimitive<br>
&gt; &gt;                               tryNamedPrimitive:<br>
&gt; &gt;                               tryNamedPrimitive:with:<br>
&gt; &gt;                               tryNamedPrimitive:with:with:<br>
&gt; &gt;                               tryNamedPrimitive:with:with:with:<br>
&gt; &gt;                               tryNamedPrimitive:with:with:with:with:<br>
&gt; &gt;                               tryNamedPrimitive:with:with:with:with:with:<br>
&gt; &gt;                               tryNamedPrimitive:with:with:with:with:with:with:<br>
&gt; &gt;                               tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1.<br>
&gt; &gt;                       receiverClass := self objectClass: aReceiver.<br>
&gt; &gt;                       theMethod := receiverClass lookupSelector: selector.<br>
&gt; &gt;                       theMethod == nil ifTrue:<br>
&gt; &gt;                               [^{PrimitiveFailToken. nil}].<br>
&gt; &gt;                       spec := theMethod literalAt: 1.<br>
&gt; &gt;                       spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1.<br>
&gt; &gt;                       Smalltalk unbindExternalPrimitives.<br>
&gt; &gt;                       ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass<br>
&gt; &gt;<br>
&gt; &gt; (cf tryPrimitive: withArgs:) and used in<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;               doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments<br>
&gt; &gt;                       &quot;Simulate a primitive method whose index is primitiveIndex.  The simulated receiver<br>
&gt; &gt;                        and arguments are given as arguments to this message. Any primitive which provokes<br>
&gt; &gt;                        execution needs to be intercepted and simulated to avoid execution running away.&quot;<br>
&gt; &gt;<br>
&gt; &gt;                       | value |<br>
&gt; &gt;                       &quot;If successful, push result and return resuming context, else ^ { PrimitiveFailToken. errorCode }&quot;<br>
&gt; &gt;                       (primitiveIndex = 19) ifTrue:<br>
&gt; &gt;                               [ToolSet<br>
&gt; &gt;                                       debugContext: self<br>
&gt; &gt;                                       label:&#39;Code simulation error&#39;<br>
&gt; &gt;                                       contents: nil].<br>
&gt; &gt;<br>
&gt; &gt;                       &quot;ContextPart&gt;&gt;blockCopy:; simulated to get startpc right&quot;<br>
&gt; &gt;                       (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart])<br>
&gt; &gt;                               ifTrue: [^self push: ((BlockContext newForMethod: receiver method)<br>
&gt; &gt;                                                               home: receiver home<br>
&gt; &gt;                                                               startpc: pc + 2<br>
&gt; &gt;                                                               nargs: (arguments at: 1))].<br>
&gt; &gt;                       (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) &quot;BlockContext&gt;&gt;value[:value:...]&quot;<br>
&gt; &gt;                               ifTrue: [^receiver pushArgs: arguments from: self].<br>
&gt; &gt;                       (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) &quot;BlockContext&gt;&gt;valueWithArguments:&quot;<br>
&gt; &gt;                               ifTrue: [^receiver pushArgs: arguments first from: self].<br>
&gt; &gt;                       primitiveIndex = 83 &quot;afr 9/11/1998 19:50&quot; &quot;Object&gt;&gt;perform:[with:...]&quot;<br>
&gt; &gt;                               ifTrue: [^self send: arguments first<br>
&gt; &gt;                                                       to: receiver<br>
&gt; &gt;                                                       with: arguments allButFirst<br>
&gt; &gt;                                                       super: false].<br>
&gt; &gt;                       primitiveIndex = 84 &quot;afr 9/11/1998 19:50 &amp; eem 8/18/2009 17:04&quot; &quot;Object&gt;&gt;perform:withArguments:&quot;<br>
&gt; &gt;                               ifTrue: [^self send: arguments first<br>
&gt; &gt;                                                       to: receiver<br>
&gt; &gt;                                                       with: (arguments at: 2)<br>
&gt; &gt;                                                       startClass: nil].<br>
&gt; &gt;                       primitiveIndex = 100 &quot;eem 8/18/2009 16:57&quot; &quot;Object&gt;&gt;perform:withArguments:inSuperclass:&quot;<br>
&gt; &gt;                               ifTrue: [^self send: arguments first<br>
&gt; &gt;                                                       to: receiver<br>
&gt; &gt;                                                       with: (arguments at: 2)<br>
&gt; &gt;                                                       startClass: (arguments at: 3)].<br>
&gt; &gt;<br>
&gt; &gt;                       &quot;Mutex&gt;&gt;primitiveEnterCriticalSection<br>
&gt; &gt;                        Mutex&gt;&gt;primitiveTestAndSetOwnershipOfCriticalSection&quot;<br>
&gt; &gt;                       (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue:<br>
&gt; &gt;                               [| active effective |<br>
&gt; &gt;                                active := Processor activeProcess.<br>
&gt; &gt;                                effective := active effectiveProcess.<br>
&gt; &gt;                                &quot;active == effective&quot;<br>
&gt; &gt;                                value := primitiveIndex = 186<br>
&gt; &gt;                                                       ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective]<br>
&gt; &gt;                                                       ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective].<br>
&gt; &gt;                                ^(value isArray<br>
&gt; &gt;                                   and: [value size = 2<br>
&gt; &gt;                                   and: [value first == PrimitiveFailToken]])<br>
&gt; &gt;                                       ifTrue: [value]<br>
&gt; &gt;                                       ifFalse: [self push: value]].<br>
&gt; &gt;<br>
&gt; &gt;                       primitiveIndex = 188 ifTrue: &quot;eem 5/27/2008 11:10 Object&gt;&gt;withArgs:executeMethod:&quot;<br>
&gt; &gt;                               [^MethodContext<br>
&gt; &gt;                                       sender: self<br>
&gt; &gt;                                       receiver: receiver<br>
&gt; &gt;                                       method: (arguments at: 2)<br>
&gt; &gt;                                       arguments: (arguments at: 1)].<br>
&gt; &gt;<br>
&gt; &gt;                       &quot;Closure primitives&quot;<br>
&gt; &gt;                       (primitiveIndex = 200 and: [self == receiver]) ifTrue:<br>
&gt; &gt;                               &quot;ContextPart&gt;&gt;closureCopy:copiedValues:; simulated to get startpc right&quot;<br>
&gt; &gt;                               [^self push: (BlockClosure<br>
&gt; &gt;                                                               outerContext: receiver<br>
&gt; &gt;                                                               startpc: pc + 2<br>
&gt; &gt;                                                               numArgs: arguments first<br>
&gt; &gt;                                                               copiedValues: arguments last)].<br>
&gt; &gt;                       ((primitiveIndex between: 201 and: 205)                  &quot;BlockClosure&gt;&gt;value[:value:...]&quot;<br>
&gt; &gt;                       or: [primitiveIndex between: 221 and: 222]) ifTrue: &quot;BlockClosure&gt;&gt;valueNoContextSwitch[:]&quot;<br>
&gt; &gt;                               [^receiver simulateValueWithArguments: arguments caller: self].<br>
&gt; &gt;                       primitiveIndex = 206 ifTrue:                                            &quot;BlockClosure&gt;&gt;valueWithArguments:&quot;<br>
&gt; &gt;                               [^receiver simulateValueWithArguments: arguments first caller: self].<br>
&gt; &gt;<br>
&gt; &gt;                       primitiveIndex = 118 ifTrue: &quot;tryPrimitive:withArgs:; avoid recursing in the VM&quot;<br>
&gt; &gt;                               [(arguments size = 2<br>
&gt; &gt;                                and: [arguments first isInteger<br>
&gt; &gt;                                and: [arguments last class == Array]]) ifFalse:<br>
&gt; &gt;                                       [^ContextPart primitiveFailTokenFor: nil].<br>
&gt; &gt;                                ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last].<br>
&gt; &gt;<br>
&gt; &gt;                       value := primitiveIndex = 120 &quot;FFI method&quot;<br>
&gt; &gt;                                               ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments]<br>
&gt; &gt;                                               ifFalse:<br>
&gt; &gt;                                                       [primitiveIndex = 117 &quot;named primitives&quot;<br>
&gt; &gt;                                                               ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments]<br>
&gt; &gt;                                                               ifFalse:<br>
&gt; &gt;                                                                       [receiver tryPrimitive: primitiveIndex withArgs: arguments]].<br>
&gt; &gt;                       ^(value isArray<br>
&gt; &gt;                           and: [value size = 2<br>
&gt; &gt;                           and: [value first == PrimitiveFailToken]])<br>
&gt; &gt;                               ifTrue: [value]<br>
&gt; &gt;                               ifFalse: [self push: value]<br>
&gt; &gt;<br>
&gt; &gt; (find attached).  But these need implementing in the standard VM before they can be used in Pharo, Squeak, etc.<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; Thanks<br>
&gt; &gt;<br>
&gt; &gt; --<br>
&gt; &gt; Mariano<br>
&gt; &gt; <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; --<br>
&gt; &gt; best,<br>
&gt; &gt; Eliot<br>
&gt; &gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; best,<br>
&gt; Eliot<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Mariano<br>
&gt; <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; best,<br>
&gt; Eliot<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Mariano<br>
&gt; <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Mariano<br>
&gt; <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; best,<br>
&gt; Eliot<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Mariano<br>
&gt; <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; best,<br>
&gt; Eliot<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Mariano<br>
&gt; <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; best,<br>
&gt; Eliot<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
</div></div>&gt; --<br>
&gt; Mariano<br>
&gt; <a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br>
&gt;<br>
<br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>