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@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@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.