Hello
I would like to know how the VM defines on:do: on: exception do: handlerAction "Evaluate the receiver in the scope of an exception handler." | handlerActive | <primitive: 199> "just a marker, fail and execute the following" handlerActive _ true. ^ self value I'm on a rather non existent internet connexion and I do not have the vm code and I would like to know where how the exception and handlerAction block are stored. I was imagining that may be the vm stores them in the previous context. Stef |
> on: exception do: handlerAction
> "Evaluate the receiver in the scope of an exception handler." > > | handlerActive | > <primitive: 199> "just a marker, fail and execute the following" > handlerActive _ true. > ^ self value 199 is a primitive that marks the context (it just sets a bit in the context object) and always fails. The fallback code is then evaluated that causes the receiving block to evaluate. That's all. In case of an exception the VM can quickly find marked contexts. Cheers, Lukas -- Lukas Renggli http://www.lukas-renggli.ch |
On Mon, Jul 21, 2008 at 12:46:15PM +0200, Lukas Renggli wrote:
> > on: exception do: handlerAction > > "Evaluate the receiver in the scope of an exception handler." > > > > | handlerActive | > > <primitive: 199> "just a marker, fail and execute the following" > > handlerActive _ true. > > ^ self value > > 199 is a primitive that marks the context (it just sets a bit in the > context object) and always fails. The fallback code is then evaluated > that causes the receiving block to evaluate. That's all. > > In case of an exception the VM can quickly find marked contexts. And the implementation of primitive 199 in class Interpreter is just this: primitiveMarkHandlerMethod "Primitive. Mark the method for exception handling. The primitive must fail after marking the context so that the regular code is run." self inline: false. ^self primitiveFail Or in C: /* Primitive. Mark the method for exception handling. The primitive must fail after marking the context so that the regular code is run. */ sqInt primitiveMarkHandlerMethod(void) { /* begin primitiveFail */ foo->successFlag = 0; return null; } |
In reply to this post by stephane ducasse
On Sun, Jul 20, 2008 at 11:59 AM, stephane ducasse <[hidden email]> wrote: Hello As the other posters have pointed out primitive 199 is simply a primitive that aways fails. So exception and handlerAction are stored in the activation of on:do: in its first and second argument, e.g. see
| exception handler | [exception := thisContext sender at: 1. handler := thisContext sender at: 2. 1 / 0] on: Error do: [:ex| ].
{ exception. handler } The primitive doesn't set any bits in the context. It merely fails, ad the method is activated exactly as if on:do: did not have a primitive. The VM finds activations of on:do: by examining the header of each context's compiled method (no bits are set in the context). Methods with primitives have the primitive number stored in a field in the method header. The VM's primitive is merely an optimization of the Smalltalk code you see:
findNextHandlerContextStarting "Return the next handler marked context, returning nil if there is none. Search starts with self and proceeds up to nil."
| ctx | <primitive: 197> ctx := self.
[ctx isHandlerContext ifTrue:[^ctx]. (ctx := ctx sender) == nil ] whileFalse.
^nil isHandlerContext "is this context for method that is marked?" ^method primitive = 199
and similarly for finding unwind contexts (marked with primitive 198). BTW, this is a really nice implementation by Andreas and Dan. In VW there are bits in the method header because primitives are not stored in the method header but in the bytecode. But this means we need a little bit more machinery. Using the primitive field is very simple and just as effective
|
On 21-Jul-08, at 7:13 AM, Eliot Miranda wrote: > > The primitive doesn't set any bits in the context. It merely fails, > ad the method is activated exactly as if on:do: did not have a > primitive. > > The VM finds activations of on:do: by examining the header of each > context's compiled method (no bits are set in the context). Methods > with primitives have the primitive number stored in a field in the > method header. [snip] > BTW, this is a really nice implementation by Andreas and Dan. In VW > there are bits in the method header because primitives are not > stored in the method header but in the bytecode. But this means we > need a little bit more machinery. Using the primitive field is very > simple and just as effective Actually I'm pretty sure that was me. Certainly I did all the exception handling stuff in the VM and old email implies we came up with using a prim number as a flag in order to make it simple to both interpret and support the old J3 attempt with minimal changes. This was all done back in august 200 or so. There was of course considerable back and forth about various details, lasting for several months IIRC. tim -- tim Rowledge; [hidden email]; http://www.rowledge.org/tim Useful random insult:- One chicken short of a henhouse. |
>>>>> "tim" == tim Rowledge <[hidden email]> writes:
tim> [...] This was all done back in august 200 or tim> so. [...] Wow, I realize Smalltalk has been around for a while, but... was it lost during the Dark Ages? :) -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 <[hidden email]> <URL:http://www.stonehenge.com/merlyn/> Smalltalk/Perl/Unix consulting, Technical writing, Comedy, etc. etc. See http://methodsandmessages.vox.com/ for Smalltalk and Seaside discussion |
In reply to this post by Eliot Miranda-2
Eliot Miranda wrote:
> BTW, this is a really nice implementation by Andreas and Dan. As much as I like to take credit, in this case it wasn't me. I don't quite remember but I think Tim came up with it (was this one of the adopted Interval changes?) Cheers, - Andreas |
On Mon, Jul 21, 2008 at 8:58 AM, Andreas Raab <[hidden email]> wrote:
I'm sorry. I misunderstood a conversation we had recently. Apologies Tim And its great to hear you sounding so chipper at 1808 years old.
|
On 21-Jul-08, at 9:51 AM, Eliot Miranda wrote: > > > On Mon, Jul 21, 2008 at 8:58 AM, Andreas Raab <[hidden email]> > wrote: > Eliot Miranda wrote: > BTW, this is a really nice implementation by Andreas and Dan. > > As much as I like to take credit, in this case it wasn't me. I don't > quite remember but I think Tim came up with it (was this one of the > adopted Interval changes?) > > I'm sorry. I misunderstood a conversation we had recently. > Apologies Tim And its great to hear you sounding so chipper at 1808 > years old. > said, "Emp - we need to put a flag in some primitive". Of course he misunderstood and took a legion or two off to impale some barbarians. Note the method involved - Interpreter>isUnwindMarked: aContext "Is this a MethodContext whose meth has a primitive number of 198?" | header meth pIndex | "NB: the use of a primitive number for marking the method is pretty grungy, but it is simple to use for a test sytem, not too expensive and we don't actually have the two spare method header bits we need. We can probably obtain them when the method format is changed NB 2: actually, the jitter will probably implement the prim to actually mark the volatile frame by changing the return function pointer." self inline: true. header := self baseHeader: aContext. (self isMethodContextHeader: header) ifFalse: [^false]. meth := self fetchPointer: MethodIndex ofObject: aContext. pIndex := self primitiveIndexOf: meth. ^pIndex == 198 ... and particularly the two NBs. I think it's a pretty poor implementation all in all but it was the best compromise we could develop at the time and given the belief we would have a working JIT Real Soon Now to replace the interpreter. A mere eight years later we still don't have a cleaned up image format, jitter, closures, host windows etc etc in actual use[1]. Sigh. tim [1] Yes, I know all of them have been developed in some form - I've worked on all of them - but are they in actual use? -- tim Rowledge; [hidden email]; http://www.rowledge.org/tim Strange OpCodes: WDS: Warp Drive, Scotty! |
ROTFL! |
On 21-Jul-08, at 10:47 AM, Eliot Miranda wrote: > Well, as I was saying to Lucius Septimus Severus back then , "Emp", > I said, "Emp - we need to put a flag in some primitive". Of course > he misunderstood and took a legion or two off to impale some > barbarians. > > ROTFL! > Actually it was SUAPWIA[*] ;-) tim [*]Stuck Up A Pole Wriggling In Agony -- tim Rowledge; [hidden email]; http://www.rowledge.org/tim Strange OpCodes: DPN: Double Precision No-op |
In reply to this post by Eliot Miranda-2
>
Thanks for all these explanation. I like Smalltalk because I can learn a lot. I'm writing some columns and chapters on exception-handling in Smalltalk for the next volume of Squeak by Example (volume two) and I will make them public and call for feedback when they are more than a draft. > I'm on a rather non existent internet connexion and I do not have the > vm code and I would like to know where how the exception and > handlerAction block > are stored. > > As the other posters have pointed out primitive 199 is simply a > primitive that aways fails. So exception and handlerAction are > stored in the activation of on:do: in its first and second argument, > e.g. see > | exception handler | > [exception := thisContext sender at: 1. > handler := thisContext sender at: 2. > 1 / 0] > on: Error > do: [:ex| ]. > { exception. handler } Excellent! > The primitive doesn't set any bits in the context. It merely fails, > ad the method is activated exactly as if on:do: did not have a > primitive. > > The VM finds activations of on:do: by examining the header of each > context's compiled method (no bits are set in the context). Methods > with primitives have the primitive number stored in a field in the > method header. Ok I see so when there is an error the VM look in the activation stack for 199Matching activation and then check if the raised error is a kind of "thisContext sender at: 1" and in such as case evaluate "thisContext sender at: 2" > The VM's primitive is merely an optimization of the Smalltalk code > you see: > > findNextHandlerContextStarting > "Return the next handler marked context, returning nil if there > is none. Search starts with self and proceeds up to nil." > > | ctx | > <primitive: 197> > ctx := self. > [ctx isHandlerContext ifTrue:[^ctx]. > (ctx := ctx sender) == nil ] whileFalse. > ^nil > > isHandlerContext > "is this context for method that is marked?" > ^method primitive = 199 > > and similarly for finding unwind contexts (marked with primitive 198). this looks simple when reading the code. > BTW, this is a really nice implementation by Andreas and Dan. In VW > there are bits in the method header because primitives are not > stored in the method header but in the bytecode. But this means we > need a little bit more machinery. Using the primitive field is very > simple and just as effective Thanks.! |
>> BTW, this is a really nice implementation by Andreas and Dan. In VW >> there are bits in the method header because primitives are not stored >> in the method header but in the bytecode. But this means we need a >> little bit more machinery. Using the primitive field is very simple >> and just as effective > > Thanks.! Just to chime in, GNU Smalltalk also uses a similar trick but with pragmas. Methods with pragmas are marked with a special flag value, and the #scanForAttribute:ifFound: method on ContextPart looks for that flag value before looking for a pragma in the method. It is probably less efficient than Squeak, but applies to all pragmas (at some point I had an idea about using pragmas to support security policies). The handling of unwind methods instead is completely different, 99% of it residing in the implementation of the VM's return-from-method bytecode. Paolo |
Free forum by Nabble | Edit this page |