>
>
>
>
>
> Thanks!
>
>
>
>
> On Tue, Jan 24, 2012 at 11:01 PM, Mariano Martinez Peck <
marianopeck@gmail.com> wrote:
>
>
> 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.
>
> What what about temporally (to be removed in the future) just when we are using older VMs?
>
> If temporary, then fine. But its all work :)
>
>
> Well...writing papers can be boring ;)
> 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
> 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.
> Then I put a halt in #open: fileName forWrite: writeMode from StandardFileStream and then I do it:
> FileDirectory default forceNewFileNamed: 'xxxxx'.
> Once in the debugger, I went to:
>
> StandardFileStream retryWithGC:[self primOpen: f writable: writeMode]
> until:[:id| id notNil]
> forFileNamed: fileName.
>
> 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).
>
> is this ok?
>
> Thanks Eliot!
>
>
>
>
>
> Why do we need them in ProtoObject?
>
> 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.
>
> Because I'm not sure that adding primitive to VM is always a good solution.
>
> Agreed. But it is in keeping with the primitive for invoking numbered primitives, tryPrimitive:withArgs:.
>
>
> HTH
> Eliot
>
>
> Stef
>
> > On Mon, Jan 23, 2012 at 8:52 AM, Mariano Martinez Peck <
marianopeck@gmail.com> wrote:
> > 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.
> > So...I wonder, do you think there could be another way so that to avoid having all those methods in ProtoObject ?
> >
> > Yes there is. I implemented primitive 218 in Cog, primitiveDoNamedPrimitiveWithArgs, which is accessed via
> >
> >
> > tryNamedPrimitiveIn: aCompiledMethod for: aReceiver withArgs: arguments
> > | selector theMethod spec receiverClass |
> > <primitive: 218 error: ec>
> > ec ifNotNil:
> > ["If ec is an integer other than -1 there was a problem with primitive 218,
> > not with the external primitive itself. -1 indicates a generic failure (where
> > ec should be nil) but ec = nil means primitive 218 is not implemented. So
> > interpret -1 to mean the external primitive failed with a nil error code."
> > ec isInteger ifTrue:
> > [ec = -1
> > ifTrue: [ec := nil]
> > ifFalse: [self primitiveFailed]].
> > ^{PrimitiveFailToken. ec}].
> > "Assume a nil error code implies the primitive is not implemented and fall back on the old code."
> > "Hack. Attempt to execute the named primitive from the given compiled method"
> > arguments size > 8 ifTrue:
> > [^{PrimitiveFailToken. nil}].
> > selector := #(
> > tryNamedPrimitive
> > tryNamedPrimitive:
> > tryNamedPrimitive:with:
> > tryNamedPrimitive:with:with:
> > tryNamedPrimitive:with:with:with:
> > tryNamedPrimitive:with:with:with:with:
> > tryNamedPrimitive:with:with:with:with:with:
> > tryNamedPrimitive:with:with:with:with:with:with:
> > tryNamedPrimitive:with:with:with:with:with:with:with:) at: arguments size+1.
> > receiverClass := self objectClass: aReceiver.
> > theMethod := receiverClass lookupSelector: selector.
> > theMethod == nil ifTrue:
> > [^{PrimitiveFailToken. nil}].
> > spec := theMethod literalAt: 1.
> > spec replaceFrom: 1 to: spec size with: (aCompiledMethod literalAt: 1) startingAt: 1.
> > Smalltalk unbindExternalPrimitives.
> > ^self object: aReceiver perform: selector withArguments: arguments inClass: receiverClass
> >
> > (cf tryPrimitive: withArgs:) and used in
> >
> >
> > doPrimitive: primitiveIndex method: meth receiver: receiver args: arguments
> > "Simulate a primitive method whose index is primitiveIndex. The simulated receiver
> > and arguments are given as arguments to this message. Any primitive which provokes
> > execution needs to be intercepted and simulated to avoid execution running away."
> >
> > | value |
> > "If successful, push result and return resuming context, else ^ { PrimitiveFailToken. errorCode }"
> > (primitiveIndex = 19) ifTrue:
> > [ToolSet
> > debugContext: self
> > label:'Code simulation error'
> > contents: nil].
> >
> > "ContextPart>>blockCopy:; simulated to get startpc right"
> > (primitiveIndex = 80 and: [(self objectClass: receiver) includesBehavior: ContextPart])
> > ifTrue: [^self push: ((BlockContext newForMethod: receiver method)
> > home: receiver home
> > startpc: pc + 2
> > nargs: (arguments at: 1))].
> > (primitiveIndex = 81 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>value[:value:...]"
> > ifTrue: [^receiver pushArgs: arguments from: self].
> > (primitiveIndex = 82 and: [(self objectClass: receiver) == BlockContext]) "BlockContext>>valueWithArguments:"
> > ifTrue: [^receiver pushArgs: arguments first from: self].
> > primitiveIndex = 83 "afr 9/11/1998 19:50" "Object>>perform:[with:...]"
> > ifTrue: [^self send: arguments first
> > to: receiver
> > with: arguments allButFirst
> > super: false].
> > primitiveIndex = 84 "afr 9/11/1998 19:50 & eem 8/18/2009 17:04" "Object>>perform:withArguments:"
> > ifTrue: [^self send: arguments first
> > to: receiver
> > with: (arguments at: 2)
> > startClass: nil].
> > primitiveIndex = 100 "eem 8/18/2009 16:57" "Object>>perform:withArguments:inSuperclass:"
> > ifTrue: [^self send: arguments first
> > to: receiver
> > with: (arguments at: 2)
> > startClass: (arguments at: 3)].
> >
> > "Mutex>>primitiveEnterCriticalSection
> > Mutex>>primitiveTestAndSetOwnershipOfCriticalSection"
> > (primitiveIndex = 186 or: [primitiveIndex = 187]) ifTrue:
> > [| active effective |
> > active := Processor activeProcess.
> > effective := active effectiveProcess.
> > "active == effective"
> > value := primitiveIndex = 186
> > ifTrue: [receiver primitiveEnterCriticalSectionOnBehalfOf: effective]
> > ifFalse: [receiver primitiveTestAndSetOwnershipOfCriticalSectionOnBehalfOf: effective].
> > ^(value isArray
> > and: [value size = 2
> > and: [value first == PrimitiveFailToken]])
> > ifTrue: [value]
> > ifFalse: [self push: value]].
> >
> > primitiveIndex = 188 ifTrue: "eem 5/27/2008 11:10 Object>>withArgs:executeMethod:"
> > [^MethodContext
> > sender: self
> > receiver: receiver
> > method: (arguments at: 2)
> > arguments: (arguments at: 1)].
> >
> > "Closure primitives"
> > (primitiveIndex = 200 and: [self == receiver]) ifTrue:
> > "ContextPart>>closureCopy:copiedValues:; simulated to get startpc right"
> > [^self push: (BlockClosure
> > outerContext: receiver
> > startpc: pc + 2
> > numArgs: arguments first
> > copiedValues: arguments last)].
> > ((primitiveIndex between: 201 and: 205) "BlockClosure>>value[:value:...]"
> > or: [primitiveIndex between: 221 and: 222]) ifTrue: "BlockClosure>>valueNoContextSwitch[:]"
> > [^receiver simulateValueWithArguments: arguments caller: self].
> > primitiveIndex = 206 ifTrue: "BlockClosure>>valueWithArguments:"
> > [^receiver simulateValueWithArguments: arguments first caller: self].
> >
> > primitiveIndex = 118 ifTrue: "tryPrimitive:withArgs:; avoid recursing in the VM"
> > [(arguments size = 2
> > and: [arguments first isInteger
> > and: [arguments last class == Array]]) ifFalse:
> > [^ContextPart primitiveFailTokenFor: nil].
> > ^self doPrimitive: arguments first method: meth receiver: receiver args: arguments last].
> >
> > value := primitiveIndex = 120 "FFI method"
> > ifTrue: [(meth literalAt: 1) tryInvokeWithArguments: arguments]
> > ifFalse:
> > [primitiveIndex = 117 "named primitives"
> > ifTrue: [self tryNamedPrimitiveIn: meth for: receiver withArgs: arguments]
> > ifFalse:
> > [receiver tryPrimitive: primitiveIndex withArgs: arguments]].
> > ^(value isArray
> > and: [value size = 2
> > and: [value first == PrimitiveFailToken]])
> > ifTrue: [value]
> > ifFalse: [self push: value]
> >
> > (find attached). But these need implementing in the standard VM before they can be used in Pharo, Squeak, etc.
> >
> >
> > Thanks
> >
> > --
> > Mariano
> >
http://marianopeck.wordpress.com
> >
> >
> >
> >
> > --
> > best,
> > Eliot
> >
>
>
>
>
>
> --
> best,
> Eliot
>
>
>
>
>
> --
> Mariano
>
http://marianopeck.wordpress.com
>
>
>
>
>
> --
> best,
> Eliot
>
>
>
>
>
> --
> Mariano
>
http://marianopeck.wordpress.com
>
>
>
>
> --
> Mariano
>
http://marianopeck.wordpress.com
>
>
>
>
>
> --
> best,
> Eliot
>
>
>
>
>
> --
> Mariano
>
http://marianopeck.wordpress.com
>
>
>
>
>
> --
> best,
> Eliot
>
>
>
>
>
> --
> Mariano
>
http://marianopeck.wordpress.com
>
>
>
>
>
> --
> best,
> Eliot
>
>
>
>
>