> At 12:54 AM -0400 6/3/04, Benjamin K. Stuhl wrote: >>(with one major caveat: if the _vtable_ functions try to use the >>PMC's address as an index into some data structure, things will go >>wrong since the PMC the base vtable functions get no longer has the >>same address as the logical PMC; if external things want to do so, >>that's fine though, since the logical PMC's address hasn't changed). >>After all, AIUI no one but the vtable functions is supposed to be >>poking inside the PMC, and the wrapper PMC (which happens to have >>the same address as the original PMC) will of course pass the new >>wrapped PMC down when it redispatches. > > Well... I'm not sure that the wrapped PMC is what gets passed on, > which is where things get tricky. > > If it does, then access to the internal bits works out just fine. On > the other hand, any vtable redispatch (of which there's a > not-inconsiderable amount) doesn't work out right. For example, for > an Integer PMC with bytecode vtable functions: > > .sub __set_string_native prototyped, method > .param string value > $I0 = value > self = $I0 > .end > > if we pass in the inner PMC to that, and someone's thrown a wrapper > that intercepts the integer set then the intercept wouldn't get > triggered, and I think that's probably a bad thing. > > Unfortunately doing this makes getting to the guts of the PMC tricky. > It also means you can only have one of each layer type layering a > PMC, since all the non-terminal layers will have to search down from > the top until they find the right PMC, which'll involve doing vtable > type comparisons or something like that, which isn't too good either. > > I'm not sure there's a good answer here, and *something* is going to > take a speed hit. (Passing in the base pmc pointer along with the > current pmc pointer has its own costs, since extra parameters aren't > free either) I'm just not sure where we want that hit to be.
Well, there is a way to take care of things reasonably cleanly, for the low, low cost of only one extra pointer per PMC! :-P Add an ->toplevel_pmc pointer to all PMCs, and call all your vfuncs on that, rather than on the PMC itself. Then you _can_ just pass down the wrapped PMC, and things Should Just Work: each level can ignore any levels above it and has its own PMC as a closure, and it can find both the top of the stack to call vfuncs on and its wrapped PMC to delegate down to. Pushing or popping a layer just means that the entire stack's worth of ->toplevel_pmc pointers have to be updated to point at the new top level. Speed or space. If the computer's in a good mood, it'll let you choose one. ^_^ -- BKS