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