[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