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)
2014-02-10 21:51 GMT+01:00 David T. Lewis lewis@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@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
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@rowledge.org; http://www.rowledge.org/tim Science is imagination equipped with grappling hooks.