[Vm-dev] Re: [Pharo-project] is there a way to avoid all the
#tryNamedPrimitive:with: * in ProtoObject
Andreas Raab
andreas.raab at gmx.de
Wed Jan 25 13:21:08 UTC 2012
Hi Eliot -
On 1/25/2012 2:43, Eliot Miranda wrote:
> On Tue, Jan 24, 2012 at 2:02 PM, Mariano Martinez Peck
> <marianopeck at gmail.com <mailto:marianopeck at gmail.com>> wrote:
>
>
> sorry...here is the attached.
>
>
> OK. What you've done will work.
I actually quite like it. Getting rid of all those methods in class
ProtoObject is definitely a good thing. Is there any downside other than
some possible performance issues? I.e., the code should work everywhere,
right?
> 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.
More important in my view is the misuse of the term "temporal" in the
method names. I find it quite confusing to read about "temporal"
compiled methods :-)
Cheers,
- Andreas
>
>
> On Tue, Jan 24, 2012 at 11:01 PM, Mariano Martinez Peck
> <marianopeck at gmail.com <mailto:marianopeck at 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 at gmail.com
> <mailto:marianopeck at 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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20120125/2169248b/attachment-0001.htm
More information about the Vm-dev
mailing list