On Fri, Dec 2, 2011 at 8:04 PM, Eliot Miranda <[email protected]>wrote:
> > > On Fri, Dec 2, 2011 at 10:55 AM, Mariano Martinez Peck < > [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. > Ahhhhhhh :) > You were there for my presentation Mariano :) And you understood the > issue then right ? :) > Well, yes, but I usually understand in the second or third time ;) > Remember the closure compiler *copies* any temporary variables that are > not changed after being closed over into a closure's copiedValues, and > *moves* any temporary variables that could be changed after being closed > over into indirection vectors, and these indirection vectors are copied > into the copied values of the closure. > Excellent. So everything is inside the closure. When you say "copiedValues" I guess you use the variable part of BlockClosure, is that right? > But, as I just said, the receiver and method are not copied (to save time > at closure creation) since these are in the outerContext already. These > are fetched from the outerContext when the closure is activated. > Got it. > > That's the trade-off, slower closure creation and larger closures and > duplication if a closure refers to its method and receiver directly, faster > closure creation, smaller closures, less duplication and very slightly > slower activation if closures refer to their receiver and method > indirectly. The additional trade-off is this issue; the indirect approach > entails more problems for serialization and for implementing compile-time > clean closures (since the compiler needs to create an outerContext for the > method and nil for the non-existent receiver - clean closures can't refer > to self). > > Is this clear or as clear as mud? > Much clear now. One last question. So far, then, I didn't find/think a scenario where serializing the whole stack (from a closure) make sense. So, if I just want to serialize a closure and be able to materialize it, then it is *never* necessary the whole stack, in all scenarios? or I am missing a case where the whole stack is needed? I am talking only about when serializing closures, because if I directly serialize a MethodContext, it may happen that I want the whole stack (like the example I showed in ESUG where I serialized the whole Debugger and then I continue debugging in another image). Thanks! > > >> >> Thanks! >> >> >> On Fri, Dec 2, 2011 at 7:41 PM, Eliot Miranda <[email protected]>wrote: >> >>> >>> >>> On Fri, Dec 2, 2011 at 10:20 AM, Nicolas Cellier < >>> [email protected]> wrote: >>> >>>> 2011/12/2 Martin Dias <[email protected]>: >>>> > Hi folks >>>> > >>>> > In Fuel, we serialize a block closure with its state, including its >>>> > outerContext. This enables to serialize a sorted collection with its >>>> > sortBlock: >>>> > >>>> > | bytes result | >>>> > bytes := FLSerializer serializeToByteArray: (SortedCollection >>>> sortBlock: [:a >>>> > :b | a > b ]). >>>> > result := FLMaterializer materializeFromByteArray: bytes. >>>> > result >>>> > addAll: #(1 2 3); >>>> > yourself. >>>> > ---> a SortedCollection(3 2 1) >>>> > >>>> > Here the problem: the byte array is huge! (800kb) because we are >>>> serializing >>>> > unneeded context for the sort block. >>>> > >>>> > We wonder how to prune it and save time and space. >>>> > >>>> > Thanks in advance >>>> > MartÃn >>>> >>>> In the case of such clean block, there is no need of outer context >>>> during block execution. >>>> However I don't know if implementation makes it possible to ignore the >>>> context... >>>> That's more a question directed to Eliot ;) >>>> >>> >>> Arguably there is a bug in my closure implementation, which is that both >>> the receiver and the method are fetched from the outerContext. That's not >>> a bug which can be fixed without a new VM/image combination and may be >>> something I'll look at long-term, but is something we have to live with at >>> the moment. This means that you *do* have to serialize the outerContext. >>> But the outerContext is used only for the receiver and method. So you >>> don't need to full serialize the outerContext. In particular you don't >>> need to serialize any of the outerContext's stack contents or its sender. >>> This needs special handling, I guess in BlockClosure, to substitute a >>> suitably reduced outerContext, but it shouldn't be hard to do. e.g. >>> >>> BlockClosure methods for: '*Fuel-serialization' >>> outerContextForSerialization >>> ^MethodContext >>> sender: nil >>> receiver outerContext receiver >>> method: outerContext method >>> args: #() >>> >>> >>> BlockClosure methods for: '*Fuel-serialization' >>> outerContextForSerialization >>> ^MethodContext >>> sender: nil >>> receiver self receiver >>> method: self method >>> args: #() >>> >>> >>> >>>> Nicolas >>>> >>>> >>> >>> >>> -- >>> best, >>> Eliot >>> >>> >>> >>> >>> >> >> >> -- >> Mariano >> http://marianopeck.wordpress.com >> >> >> >> >> > > > -- > best, > Eliot > > > > > -- Mariano http://marianopeck.wordpress.com
