Loading ...
Sorry, an error occurred while loading the content.
 

Block activation verification...

Expand Messages
  • Dru Nelson
    In the Self tutorial/slides, it mentions that the blocks are compiled with some hidden slots. Then when an expression that references a block is evaluated , a
    Message 1 of 7 , Jun 2, 2000
      In the Self tutorial/slides, it mentions that the blocks
      are compiled with some hidden slots.

      Then when an expression that references a block is "evaluated",
      a clone is made with a hidden slot to the context.

      (3 < 4) ifTrue: [ ^nil ].

      How is that done?




      Dru Nelson
      San Mateo, California
    • David Ungar
      Painfully & painstakingly;-) - Dave ... -- David Ungar Sun Microsystems Laboratories (650) 336-2618
      Message 2 of 7 , Jun 2, 2000
        Painfully & painstakingly;-)

        - Dave



        At 1:48 AM -0700 6/2/00, Dru Nelson wrote:
        >In the Self tutorial/slides, it mentions that the blocks
        >are compiled with some hidden slots.
        >
        >Then when an expression that references a block is "evaluated",
        >a clone is made with a hidden slot to the context.
        >
        >(3 < 4) ifTrue: [ ^nil ].
        >
        >How is that done?
        >
        >
        >
        >
        >Dru Nelson
        >San Mateo, California
        >
        >
        >
        >
        >
        >
        >------------------------------------------------------------------------
        >Failed tests, classes skipped, forgotten locker combinations.
        >Remember the good 'ol days
        >http://click.egroups.com/1/4053/0/_/8257/_/959935686/
        >------------------------------------------------------------------------

        --


        David Ungar
        Sun Microsystems Laboratories
        (650) 336-2618
      • Jecel Assumpcao Jr
        ... True. This greatly offends some people who feel they are being cheated by these tricks. This led me to take a look at some outliners for methods (just
        Message 3 of 7 , Jun 2, 2000
          Dru Nelson you wrote:
          > In the Self tutorial/slides, it mentions that the blocks
          > are compiled with some hidden slots.

          True. This greatly offends some people who feel they are being cheated
          by these tricks. This led me to take a look at some outliners for
          methods (just choose "sprout" from the yellow menu while pointing to a
          method) and noticed that Self 4.1.2 doesn't include the "pseudo slots"
          like 4.0 does. In fact, this lastest version seems to have some real
          problems with outliners and methods (it can't show the reflectee slot
          in a method mirror outliner without getting into a loop generating
          errors). Speaking of 4.1.2 UI problems, enumerators now start
          evaluating themselves as soon as you call them up instead of when you
          try to open them. This means you can never uncheck the "well known
          only" box before doing the enumeration.

          > Then when an expression that references a block is "evaluated",
          > a clone is made with a hidden slot to the context.

          Variable scoping in other languages is simulated in Self using object
          inheritance. By making the implicit receiver be the current context and
          having that point to the original receiver via a self* parent slot, you
          can access both "local variables" and "instance variables" (and "class
          variables! And "globals") in a uniform way.

          When you send the 'value' message to a block, if the corresponding
          methods acted in the normal way you would have a "self*" slot pointing
          to the block itself and no way to access stuff in the context in which
          it appeared:

          ( | a <- 3. b <- 4 | a < b ifTrue: [ ^ a*b ]. a+b )

          This has a block object that looks like this:

          ( | parent* = traits block. value = ( ^ a*b ) | )

          Now if this block object is sent a 'value' message and the resulting
          context gets a 'self*' slot pointing to itself, then it will know about
          'parent*' and 'value', but nothing about 'a' and 'b', right?

          So we don't add that 'self*' slot at all, but a 'lexicalParent*' slot
          pointing to the context which executed the "push literal: [ ^ a*b ]"
          bytecode. But how can we find out that information when creating the
          context for the 'value' method? By this time, we no longer remember
          this (and it would be a good idea to know this anyway since otherwise
          we can't execute the "non local return" bytecode, the "^").

          > (3 < 4) ifTrue: [ ^nil ].
          >
          > How is that done?

          Yet another trick - when the bytecode tells us to push a block on the
          stack, we create a clone of it with an extra slot to point to the
          currently executing context and push that instead. Note that you can't
          see this in the debugger - it does every thing it can to make you think
          that the original block was used, not its evil twin ;-)

          Now when we send the 'value' message, it will go to the modified clone
          instead of the block, and this clone does know about the context we are
          interested in and so can fill in the 'lexicalParent*' slot correctly.
          From now on, everything works as claimed.

          Don't worry too much about understanding all this... Self doesn't
          really work this way at all under the hood!!

          So David's answer was probably just what you needed :-)

          -- Jecel
        • Dru Nelson
          Ok :-) Dru Nelson San Mateo, California
          Message 4 of 7 , Jun 3, 2000
            Ok :-)

            Dru Nelson
            San Mateo, California


            On Fri, 2 Jun 2000, David Ungar wrote:

            > Painfully & painstakingly;-)
            >
            > - Dave
          • Dru Nelson
            First, Thanks Jecel! ... Yes, I understood the hidden slots. I don t feel tricked :-) ... Yes, I understood this part too. A very elegant solution. ... Now to
            Message 5 of 7 , Jun 3, 2000
              First, Thanks Jecel!


              > True. This greatly offends some people who feel they are being cheated
              > by these tricks. This led me to take a look at some outliners for

              Yes, I understood the hidden slots. I don't feel tricked :-)

              >
              > Variable scoping in other languages is simulated in Self using object
              > inheritance. By making the implicit receiver be the current context and
              > having that point to the original receiver via a self* parent slot, you
              > can access both "local variables" and "instance variables" (and "class
              > variables! And "globals") in a uniform way.

              Yes, I understood this part too. A very elegant solution.

              > this (and it would be a good idea to know this anyway since otherwise
              > we can't execute the "non local return" bytecode, the "^").
              >

              Now to the heart of the question :-)

              > > (3 < 4) ifTrue: [ ^nil ].
              > >
              > > How is that done?
              >
              > Yet another trick - when the bytecode tells us to push a block on the
              > stack, we create a clone of it with an extra slot to point to the
              > currently executing context and push that instead. Note that you can't
              > see this in the debugger - it does every thing it can to make you think
              > that the original block was used, not its evil twin ;-)
              >
              > Now when we send the 'value' message, it will go to the modified clone
              > instead of the block, and this clone does know about the context we are
              > interested in and so can fill in the 'lexicalParent*' slot correctly.
              > >From now on, everything works as claimed.

              OK, this is the trick I was looking for. I read about this in the slides
              and the Self 4.0 progs' ref. However, I didn't know how the final
              clone was created *efficiently*. In order for this to work in a naive
              way, every push of a reference would have to know if the argument
              was a block (a significant read barrier). Or a block would be a
              special object type specified in the reference so the bytecode could
              do this.

              Is that how it works?


              > Don't worry too much about understanding all this... Self doesn't
              > really work this way at all under the hood!!

              I'm sure the optimizer is a whole other field in itself :-)

              >
              > So David's answer was probably just what you needed :-)
              >

              The last trick is the answer I needed.


              Dru Nelson
              San Mateo, California
            Your message has been successfully submitted and would be delivered to recipients shortly.