[Vm-dev] Making a Slower VM

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


OK thank you, I am aware of that trick so not a problem.

(But you should not blame Eliot, I think I started abusing slang that way
in OSProcessPlugin many years ago, so you can blame me just as well)

Thanks a lot,
Dave

>  Hi David,
> I wanted to say that COG depends on (self malloc: n) to be translated
> malloc(n); and not setMalloc(n); for example (you can have many others by
> browsing unimplemented calls), but maybe foo was not a generic ID in your
> case?
>
>
> 2014-02-11 15:05 GMT+01:00 David T. Lewis <lewis at mail.msen.com>:
>
>>
>> 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