[Vm-dev] Making a Slower VM

David T. Lewis lewis at mail.msen.com
Tue Feb 11 14:05:34 UTC 2014


On Mon, Feb 10, 2014 at 10:12:32PM +0100, Nicolas Cellier wrote:
>  
> Hi David,
> do you realize that Eliot is (ab)using this in COG in order to eliminate
> some direct cCode: '...' inclusion?
> So setFoo: is not an option (or i misunderstood something)
> 

Hi Nicolas,

Actually I am not sure what you are referring to here, so probably I am
missing something. Can you explain why setFoo: would be a problem in Cog?
I cannot check it myself right now but I am interested to know if I am
missing something important.

Thanks,
Dave


> 
> 2014-02-10 21:51 GMT+01:00 David T. Lewis <lewis at mail.msen.com>:
> 
> >
> > I was looking at the trunk VMM yesterday and found that most of the issues
> > were just caused by accessor methods, where #foo and #foo: generate
> > conflicting foo(void) and foo(aParameter). In most cases, a convention of
> > #setFoo: rather than #foo: takes care of the problem. There were a few
> > other miscellaneous issues as well, but nothing that looked serious.
> >
> > The variable 'memory' is a challenge because it is used extensively both
> > directly and through #memory and #memory:. I was considering changing the
> > variable name to something like memoryBase, and leaving the accessors
> > alone though I'm not sure that would be a very good idea.
> >
> > I ran out of time yesterday and did not pursue it beyond this.
> >
> > Dave
> >
> > >
> > >
> > > On 10-02-2014, at 11:53 AM, Eliot Miranda <eliot.miranda at gmail.com>
> > wrote:
> > >>
> > >> I *think* the issue is the internal/external split brought abut by the
> > >> introduction of the localFoo variables, such as localSP and localIP.
> > >
> > > It's really hard to be sure but I suspect that this isn't the (only)
> > > issue. IIRC we used to be able to make non-inlined VMs at one point and
> > > that was well after the internalFoo code was added.
> > >
> > > OK, some quick email searching reveals some work done in '03 by johnMcI,
> > > Craig & me.
> > > Craig found the following code helped -
> > >
> > > !'From Squeak3.6alpha of ''17 March 2003'' [latest update: #5325] on 21
> > > July 2003 at 1:11:25 pm'!
> > >
> > > !Interpreter methodsFor: 'contexts' stamp: 'crl 7/19/2003 15:59'!
> > > primitiveFindNextUnwindContext
> > >       "Primitive. Search up the context stack for the next method context
> > > marked for unwind handling from the receiver up to but not including the
> > > argument. Return nil if none found."
> > >       | thisCntx nilOop aContext isUnwindMarked header meth pIndex |
> > >       aContext _ self popStack.
> > >       thisCntx _ self fetchPointer: SenderIndex ofObject: self popStack.
> > >       nilOop _ nilObj.
> > >
> > >       [(thisCntx = aContext) or: [thisCntx = nilOop]] whileFalse: [
> > >
> > >       header _ self baseHeader: aContext.
> > >
> > >       (self isMethodContextHeader: header)
> > >               ifTrue: [
> > >                       meth _ self fetchPointer: MethodIndex ofObject:
> > aContext.
> > >                       pIndex _ self primitiveIndexOf: meth.
> > >                       isUnwindMarked _ pIndex == 198]
> > >               ifFalse: [isUnwindMarked _ false].
> > >               isUnwindMarked ifTrue:[
> > >                       self push: thisCntx.
> > >                       ^nil].
> > >               thisCntx _ self fetchPointer: SenderIndex ofObject:
> > thisCntx].
> > >
> > >       ^self push: nilOop! !
> > >
> > > !Interpreter methodsFor: 'interpreter shell' stamp: 'crl 7/19/2003
> > 15:33'!
> > > interpret
> > >       "This is the main interpreter loop. It normally loops forever,
> > fetching
> > > and executing bytecodes. When running in the context of a browser plugin
> > > VM, however, it must return control to the browser periodically. This
> > > should done only when the state of the currently running Squeak thread is
> > > safely stored in the object heap. Since this is the case at the moment
> > > that a check for interrupts is performed, that is when we return to the
> > > browser if it is time to do so. Interrupt checks happen quite
> > > frequently."
> > >
> > >       "record entry time when running as a browser plug-in"
> > >       "self browserPluginInitialiseIfNeeded"
> > >       self internalizeIPandSP.
> > >       self fetchNextBytecode.
> > >       [true] whileTrue: [self dispatchOn: currentBytecode in:
> > BytecodeTable].
> > >       localIP _ localIP - 1.  "undo the pre-increment of IP before
> > returning"
> > >       self externalizeIPandSP.
> > > ! !
> > >
> > > !Interpreter methodsFor: 'return bytecodes' stamp: 'crl 7/19/2003 16:05'!
> > > returnValueTo
> > >       "Note: Assumed to be inlined into the dispatch loop."
> > >
> > >       | nilOop thisCntx contextOfCaller localCntx localVal isUnwindMarked
> > > header meth pIndex |
> > >       self inline: true.
> > >       self sharedCodeNamed: 'commonReturn' inCase: 120.
> > >
> > >       nilOop _ nilObj. "keep in a register"
> > >       thisCntx _ activeContext.
> > >       localCntx _ cntx.
> > >       localVal _ val.
> > >
> > >       "make sure we can return to the given context"
> > >       ((localCntx = nilOop) or:
> > >        [(self fetchPointer: InstructionPointerIndex ofObject: localCntx)
> > =
> > > nilOop]) ifTrue: [
> > >               "error: sender's instruction pointer or context is nil;
> > cannot return"
> > >               ^self internalCannotReturn: localVal].
> > >
> > >       "If this return is not to our immediate predecessor (i.e. from a
> > method
> > > to its sender, or from a block to its caller), scan the stack for the
> > > first unwind marked context and inform this context and let it deal with
> > > it. This provides a chance for ensure unwinding to occur."
> > >       thisCntx _ self fetchPointer: SenderIndex ofObject: activeContext.
> > >
> > >       "Just possibly a faster test would be to compare the homeContext
> > and
> > > activeContext - they are of course different for blocks. Thus we might be
> > > able to optimise a touch by having a different returnTo for the
> > > blockreteurn (since we know that must return to caller) and then if
> > > active ~= home we must be doing a non-local return. I think. Maybe."
> > >       [thisCntx = localCntx] whileFalse: [
> > >               thisCntx = nilObj ifTrue:[
> > >                       "error: sender's instruction pointer or context is
> > nil; cannot return"
> > >                       ^self internalCannotReturn: localVal].
> > >               "Climb up stack towards localCntx. Break out to a send of
> > > #aboutToReturn:through: if an unwind marked context is found"
> > >       header _ self baseHeader: thisCntx.
> > >
> > >       (self isMethodContextHeader: header)
> > >               ifTrue: [
> > >                       meth _ self fetchPointer: MethodIndex ofObject:
> > thisCntx.
> > >                       pIndex _ self primitiveIndexOf: meth.
> > >                       isUnwindMarked _ pIndex == 198]
> > >               ifFalse: [isUnwindMarked _ false].
> > >
> > >               isUnwindMarked ifTrue:[
> > >                       "context is marked; break out"
> > >                       ^self internalAboutToReturn: localVal through:
> > thisCntx].
> > >               thisCntx _ self fetchPointer: SenderIndex ofObject:
> > thisCntx.
> > > ].
> > >
> > >       "If we get here there is no unwind to worry about. Simply
> > terminate the
> > > stack up to the localCntx - often just the sender of the method"
> > >       thisCntx _ activeContext.
> > >       [thisCntx = localCntx]
> > >               whileFalse:
> > >               ["climb up stack to localCntx"
> > >               contextOfCaller _ self fetchPointer: SenderIndex ofObject:
> > thisCntx.
> > >
> > >               "zap exited contexts so any future attempted use will be
> > caught"
> > >               self storePointerUnchecked: SenderIndex ofObject: thisCntx
> > withValue:
> > > nilOop.
> > >               self storePointerUnchecked: InstructionPointerIndex
> > ofObject: thisCntx
> > > withValue: nilOop.
> > >               reclaimableContextCount > 0 ifTrue:
> > >                       ["try to recycle this context"
> > >                       reclaimableContextCount _ reclaimableContextCount
> > - 1.
> > >                       self recycleContextIfPossible: thisCntx].
> > >               thisCntx _ contextOfCaller].
> > >
> > >       activeContext _ thisCntx.
> > >       (thisCntx < youngStart) ifTrue: [ self beRootIfOld: thisCntx ].
> > >
> > >       self internalFetchContextRegisters: thisCntx.  "updates local IP
> > and SP"
> > >       self fetchNextBytecode.
> > >       self internalPush: localVal.
> > > ! !
> > >
> > > Shortly after that I released the VMMaker3.6 with a note that it couldn't
> > > produce a completely non-inlined VM because of a problem in fetchByte if
> > > globalstruct was enabled, and some odd problems in B2DPlugin. When
> > > VMMaker3.7 was released a year late (march 04) I apparently thought it
> > > could make the core vm non-inlined. Since this is all a bazillion years
> > > ago I can't remember any context to help extend the history.
> > >
> > > tim
> > > --
> > > tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim
> > > Science is imagination equipped with grappling hooks.
> > >
> >
> >
> >



More information about the Vm-dev mailing list