<br><br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote"><div>Ok. I will try to give it a try to this approach as well. <br>But what happened with the version I attached in the previous email that uses a template method and just change the arguments number?<br>

</div></div></blockquote><div><br></div><div>That would be fine.  I didn&#39;t look.</div><div> </div></div></blockquote><div><br>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><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<div class="gmail_quote"><div></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><div>but I get lost to get this working...the previous solution seems easier.<br>



</div></div></blockquote><div><br></div><div>Do you want to build Trabants or BMWs?  </div></div></blockquote><div><br>I didn&#39;t understand. Which solution which be each car?<br></div></div></blockquote><div><br></div>

<div>Compiling from source each time = trabant.  Synthesizing directly = vw.   Using a template method = bmw.  </div><div><br></div><div>(vw = VisualWorks ;) )</div></div></blockquote><div><br><br>:):):):)<br><br>Nice because it means that we found a fast solution yet quite understandable :)<br>
 </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote"><div>Documentation helps.</div><div> </div></div></blockquote><div><br>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>

</div></div></blockquote><div><br></div><div>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.</div>
</div></blockquote><div><br>Agree. Once someone gives me the OK for my .cs, I will add comments and commit.<br><br>Thanks Eliot. <br> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote">
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><div>
 <br> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



<div class="gmail_quote"><div><br>Thanks!<br><br><br> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div class="gmail_quote"><div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br><div class="gmail_quote">On Tue, Jan 24, 2012 at 11:01 PM, Mariano Martinez Peck <span dir="ltr">&lt;<a href="mailto:marianopeck@gmail.com" target="_blank">marianopeck@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><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">








<div class="gmail_quote"><div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<div class="gmail_quote">
<div><br></div><div>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.</div>











</div></blockquote><div><br>What what about temporally (to be removed in the future) just when we are using older VMs?<br></div></div></blockquote><div><br></div></div><div>If temporary, then fine.  But its all work :)</div>








</div>
</blockquote><div><br><br>Well...writing papers can be boring ;)<br>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>









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>Then I put a halt in #open: fileName forWrite: writeMode   from StandardFileStream and then I do it:<br>









FileDirectory default forceNewFileNamed: &#39;xxxxx&#39;.<br>Once in the debugger, I went to:<br><br>StandardFileStream retryWithGC:[self primOpen: f writable: writeMode] <br>                    until:[:id| id notNil] <br>









                    forFileNamed: fileName.<br><br>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>









<br>is this ok?<br><br>Thanks Eliot!<br><br>  <br></div><div><div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="gmail_quote">
<div>
 </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">











<div class="gmail_quote">
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Why do we need them in ProtoObject?<br></blockquote><div><br></div><div>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.</div>












<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Because I&#39;m not sure that adding primitive to VM is always a good solution.<br></blockquote><div><br></div><div>Agreed.  But it is in keeping with the primitive for invoking numbered primitives,  tryPrimitive:withArgs:.</div>












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

</font></span></blockquote></div><br><br clear="all"><br>-- <br>Mariano<br><a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Mariano<br><a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Mariano<br><a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>best,<div>Eliot</div><br>
<br></blockquote></div><br><br clear="all"><br>-- <br>Mariano<br><a href="http://marianopeck.wordpress.com" target="_blank">http://marianopeck.wordpress.com</a><br><br>