Thank you very much Eliot and Juan for this nice discussion. I have just commit this new functionality and it seems to work fine. I ended up using Eliot's #abstractBytecodes since the one from Juan didn't work out of the box in Pharo.
On Fri, Dec 2, 2011 at 10:38 PM, Eliot Miranda <[email protected]>wrote: > Hi Juan, > > On Fri, Dec 2, 2011 at 11:59 AM, Juan Vuletich <[email protected]> wrote: > >> Mariano Martinez Peck wrote: >> >>> >>> >>> On Fri, Dec 2, 2011 at 9:46 PM, Eliot Miranda >>> <[email protected]<mailto: >>> eliot.miranda@gmail.**com <[email protected]>>> wrote: >>> >>> >>> >>> On Fri, Dec 2, 2011 at 12:40 PM, Mariano Martinez Peck >>> <[email protected] <mailto:[email protected]>**> wrote: >>> >>> >>> >>> On Fri, Dec 2, 2011 at 8:30 PM, Juan Vuletich >>> <[email protected] <mailto:[email protected]>> wrote: >>> >>> Eliot Miranda wrote: >>> >>> >>> >>> On Fri, Dec 2, 2011 at 10:55 AM, Mariano Martinez Peck >>> <[email protected] <mailto:[email protected]> >>> <mailto:[email protected] >>> >>> <mailto:[email protected]>**>> wrote: >>> >>> Thanks both. I am right to assume that if the block >>> refers to temp >>> vars, parameters, or whatever in another scope, >>> then such solution >>> won't work. I mean, if I have this example for example: >>> >>> | bytes result blah | >>> blah := 42. >>> bytes := FLSerializer serializeToByteArray: >>> (SortedCollection >>> sortBlock: [:a :b | (a + blah) > b ]). >>> >>> Then the 'blah' is in a different context. So the >>> mentioned >>> solution works for "clean" closures, which are >>> "self contained". >>> In the other cases (such as this example), we >>> should serialize the >>> whole stack. Is this correct? >>> >>> >>> No. The closure implementation arranges that any and >>> all temporary variables accessed by the closure are >>> directly accessible from the closure without accessing >>> the outer contexts. >>> ... >>> >>> >>> WRT clean closures, check what I did in Cuis to serialize >>> SortedCollections. See implementors and senders of #isClean. >>> >>> >>> Nice. Thanks Juan. I was checking your code, and that's >>> exactly why I asked Eliot. In your method you say: >>> >>> isClean >>> "A clean closure is one that doesn't really need the home >>> context because: >>> - It doesn't send messages to self or super >>> - It doesn't access any instance variable >>> - It doesn't access any outer temp >>> - It doesn't do ^ return" >>> ..... >>> >>> So... my question is, WHAT do I need to serialize if I want to >>> be able to serialize also "non clean". >>> >>> >>> IMO, dy default, everything reachable from the closure, including >>> the outerContext chain and their senders. But that's only a >>> default. What makes sense in any given context is up to the >>> application, e.g. see Seaside. One size won't fit all. You >>> should handle the common cases (e.g. clean blocks and everything >>> else) and leave it up to the user to figure out what they need to >>> do in complex situations, making sure you provide them with the >>> hooks they'll need, such as the ability to substitute objects when >>> serializing etc, and perhaps some useful examples. >>> >>> >>> +1 Then we will do the following: we will check whether the closure is >>> clean. If it is, then we serialize just the closure plus its outerContext >>> but only with receiver and method. If it is not clean, then we serialize >>> the whole stack. That's all by default. If then someone needs something >>> different, then to use the hooks :) >>> So the final question is whether what Juan is using in Cuis is up to >>> date. If it is, then I have all I need :) >>> Thank you guys. >>> >> >> I can say that it does indeed work. But I'd be really grateful if Eliot >> took a good look at that code! >> > > There is a much better way, using > InstructionStream>>interpreetNextInstructionFor: which abstracts away from > the bytecode encoding and allows one to simply use messages. e.g. look at > > BlockClosure methods for private > abstractBytecodes > "Answer an OrderedCollection of the abstract bytecodes sent in the > receiver." > | scanner blockCreationMessage end abstractBytecodes | > scanner := InstructionStream new. > "find the creation message to find the extent of the block." > scanner method: self method pc: self method initialPC. > [scanner pc < startpc] whileTrue: > [[scanner interpretNextInstructionFor: nil] > on: MessageNotUnderstood > do: [:ex| blockCreationMessage := ex message]]. > end := blockCreationMessage arguments last + startpc - 1. > "now collect all the bytecode messages in the block." > abstractBytecodes := OrderedCollection new. > scanner method: self method pc: startpc. > [scanner pc < end] whileTrue: > [[scanner interpretNextInstructionFor: nil] > on: MessageNotUnderstood > do: [:ex| abstractBytecodes add: ex message selector]]. > ^abstractBytecodes > > and (SortedCollection sortBlock: [:a :b| a compare: b caseSensitive: > false]) sortBlock abstractBytecodes evaluates to > > an OrderedCollection(#pushTemporaryVariable: #pushTemporaryVariable: > #pushConstant: #send:super:numArgs:) > > So a check for clean blocks would check for a block's abstractBytecodes > not including some particular set of banned messages (which I *think* is > pushReceiver pushReceiverVariable: popIntoReceiverVariable: > storeIntoReceiverVariable: methodReturnConstant: methodReturnReceiver > methodReturnTop). > > e.g. > > isClean > ^(self abstractBytecodes intersection: #(pushReceiver > pushReceiverVariable: popIntoReceiverVariable: storeIntoReceiverVariable: > methodReturnConstant: methodReturnReceiver methodReturnTop)) isEmpty > > >> Cheers, >> Juan Vuletich >> >> >>> >>> >>> I mean, for each item on that list, what do I need apart from >>> the closure instance and the receiver and method from the >>> outerContext ? the whole stack of contexts ? >>> >>> >>> Thanks a lot in advance! >>> >>> >>> >>> -- Mariano >>> http://marianopeck.wordpress.**com<http://marianopeck.wordpress.com> >>> >>> >>> >>> >>> >>> >>> >>> -- best, >>> Eliot >>> >>> >>> >>> >>> >>> >>> >>> -- >>> Mariano >>> http://marianopeck.wordpress.**com <http://marianopeck.wordpress.com> >>> >>> ------------------------------**------------------------------** >>> ------------ >>> >>> >>> >>> ------------------------------**------------------------------** >>> ------------ >>> >>> No virus found in this message. >>> Checked by AVG - www.avg.com <http://www.avg.com> >>> Version: 10.0.1411 / Virus Database: 2102/4052 - Release Date: 12/02/11 >>> >>> >> >> > > > -- > best, > Eliot > > > > > -- Mariano http://marianopeck.wordpress.com
