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