[squeak-dev] Compiler

Eliot Miranda eliot.miranda at gmail.com
Fri Jun 22 01:10:51 UTC 2012


On Thu, Jun 21, 2012 at 2:34 PM, Bert Freudenberg <bert at freudenbergs.de>wrote:

>
> On 2012-06-21, at 22:32, Nicolas Cellier wrote:
>
> > 2012/6/21 Bert Freudenberg <bert at freudenbergs.de>:
> >>
> >> On 2012-06-21, at 19:43, Nicolas Cellier wrote:
> >>
> >>> if these are objects rather than literals (that we can expect being
> >>> constant), say for example some instance variable, then can we
> >>> guaranty that the first message won't have any side effect...
> >>>
> >>> (a at: 1) + ( (a at:2) * ( (a at: 1 put: ( ... ) ) + (... ) ) )
> >>>
> >>> Nicolas
> >>
> >> Did you mean to write we can *not* guarantee it?
> >>
> >> I don't think we have to worry about side effects, as long as the
> evaluation order of all expressions remains the same:
> >>
> >>        a := {3. 4}.
> >>        (a at: 1) + ( (a at: 2) * (a at: 1 put: 5) ).
> >>
> >> is equivalent to
> >>
> >>        a := {3. 4}.
> >>        t1 := a at: 1.
> >>        t2 := a at: 2.
> >>        t3 := a at: 1 put: 5.
> >>        t4 := t2 * t3.
> >>        t5 := t1 + t4.
> >>        t5
> >>
> >
> > Agree, but then we're back to our initial problem, above code first
> > push all parameters then perform all the sends, and might overflow the
> > stack limit in-between... We could hack and simulate the stack in such
> > case as I proposed , but I feel it will be really teddious to handle
> > all of current CompiledMethod limitations...
> >
> > Nicolas
>
>
> No, we have worked around the stack limitation. The expanded form uses
> temps, not stack slots. And for more temps you had a solution already :)
>
> The first example needs a stack of size 5, while the second one needs only
> 3.
>
> The maximum stack depth the expanded form needs is the number of arguments
> of the message send with the most arguments, plus 1 for the receiver/result.
>

This is fine.  But a 2 bit field could code the logarithm of the context
size, either 16, 32, 64 & 128 slots, or 16, 64, 256 & 1024 slots.  I think
that would be more than adequate.

So with 31 bits in the header to play with you'd get e.g.
0:     14 numLiterals (16k literals)
14:     6 numArgs (63 args)
20:     6 numTemps-numArgs (63 temps, temps ~= numTemps + numArgs)
26:     2 context size (16, 64, 256 & 1024 slots)
28:     3 bits flags

But there are lots of other tricks one could play moving some fields into
bytecode.  For example, a one byte bytecode that specified 0 temps and a
two byte bytecode that specified how many temps to allocate (up to 255 or
256) would save a further 6 bits, and provide a greater range.  Why have
two bytecodes?  Most methods have no temps, e.g.:

| noTemps hasTemps |
noTemps := hasTemps := 0.
CompiledMethod allInstancesDo:
[:cm|
cm isQuick ifFalse:
[cm numTemps = cm numArgs ifTrue: [noTemps := noTemps + 1] ifFalse:
[hasTemps := hasTemps + 1]]].
{noTemps. hasTemps } #(65839 24230)

But saving 64k by burning a bytecode might be silly.  Depends on how the
bytecode set looks.


>
> - Bert -
>
>
>
>


-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20120621/b1013412/attachment.htm


More information about the Squeak-dev mailing list