Tests.Compiler.DecompilerTests.testDecompilerInClassesMNtoMZ

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Tests.Compiler.DecompilerTests.testDecompilerInClassesMNtoMZ

Frank Shearar-3
This, and the other decompiler test failure, happens because of the
recent chained assignment work:

original snippet:

    ActiveWorld := ActiveHand := ActiveEvent := nil.

decompiled version of sameL

    ActiveEvent := nil.
    ActiveHand := nil.
    ActiveWorld := nil.

How to fix?

frank

Reply | Threaded
Open this post in threaded view
|

Re: Tests.Compiler.DecompilerTests.testDecompilerInClassesMNtoMZ

Levente Uzonyi-2
On Fri, 12 Apr 2013, Frank Shearar wrote:

> This, and the other decompiler test failure, happens because of the
> recent chained assignment work:
>
> original snippet:
>
>    ActiveWorld := ActiveHand := ActiveEvent := nil.
>
> decompiled version of sameL
>
>    ActiveEvent := nil.
>    ActiveHand := nil.
>    ActiveWorld := nil.
>
> How to fix?

The only method with this assignment chain in my image is MorphicProject
>> #saveState . The bytecodes for this line are:

73 <73> pushConstant: nil
74 <81 C5> storeIntoLit: ActiveEvent
76 <81 C6> storeIntoLit: ActiveHand
78 <82 C7> popIntoLit: ActiveWorld

And the decompiler can reproduce the original code.

If I recompile this method (which should have been done due to the
Environments changes, but for some reason it hasn't happened yet), then
there's a bug in the compiler. The bytecodes will be:

78 <25> pushConstant: ##ActiveWorld
79 <73> pushConstant: nil
80 <27> pushConstant: ##ActiveEvent
81 <80 41> pushTemp: 1
83 <CA> send: value:
84 <87> pop
85 <26> pushConstant: ##ActiveHand
86 <80 41> pushTemp: 1
88 <CA> send: value:
89 <87> pop
90 <CA> send: value:
91 <87> pop

Which are obviously wrong.

Creating a new method with just a simple assignment chain:

foo

  GlobalA := GlobalB := $a

generetes:

25 <20> pushConstant: ##GlobalA
26 <22> pushConstant: $a
27 <21> pushConstant: ##GlobalB
28 <80 41> pushTemp: 1
30 <CA> send: value:
31 <87> pop
32 <CA> send: value:
33 <87> pop
34 <78> returnSelf

Which still has the pushTemp: 1. But this method has 0 temporaries, so
it's a compiler bug. I wonder how the decompiler can decompile anything
meaningful from this, and how the VM doesn't crash.


Levente

>
> frank
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Tests.Compiler.DecompilerTests.testDecompilerInClassesMNtoMZ

Nicolas Cellier
Once you recompileAll, they do not fail anymore.
Still the same problem, Compiler recompileAll will leave unbound CompiledMethod here and there.


2013/4/12 Levente Uzonyi <[hidden email]>
On Fri, 12 Apr 2013, Frank Shearar wrote:

This, and the other decompiler test failure, happens because of the
recent chained assignment work:

original snippet:

   ActiveWorld := ActiveHand := ActiveEvent := nil.

decompiled version of sameL

   ActiveEvent := nil.
   ActiveHand := nil.
   ActiveWorld := nil.

How to fix?

The only method with this assignment chain in my image is MorphicProject
#saveState . The bytecodes for this line are:

73 <73> pushConstant: nil
74 <81 C5> storeIntoLit: ActiveEvent
76 <81 C6> storeIntoLit: ActiveHand
78 <82 C7> popIntoLit: ActiveWorld

And the decompiler can reproduce the original code.

If I recompile this method (which should have been done due to the Environments changes, but for some reason it hasn't happened yet), then there's a bug in the compiler. The bytecodes will be:

78 <25> pushConstant: ##ActiveWorld
79 <73> pushConstant: nil
80 <27> pushConstant: ##ActiveEvent
81 <80 41> pushTemp: 1
83 <CA> send: value:
84 <87> pop
85 <26> pushConstant: ##ActiveHand
86 <80 41> pushTemp: 1
88 <CA> send: value:
89 <87> pop
90 <CA> send: value:
91 <87> pop

Which are obviously wrong.

Creating a new method with just a simple assignment chain:

foo

        GlobalA := GlobalB := $a

generetes:

25 <20> pushConstant: ##GlobalA
26 <22> pushConstant: $a
27 <21> pushConstant: ##GlobalB
28 <80 41> pushTemp: 1
30 <CA> send: value:
31 <87> pop
32 <CA> send: value:
33 <87> pop
34 <78> returnSelf

Which still has the pushTemp: 1. But this method has 0 temporaries, so it's a compiler bug. I wonder how the decompiler can decompile anything
meaningful from this, and how the VM doesn't crash.


Levente


frank






Reply | Threaded
Open this post in threaded view
|

Re: Tests.Compiler.DecompilerTests.testDecompilerInClassesMNtoMZ

Levente Uzonyi-2
On Fri, 12 Apr 2013, Nicolas Cellier wrote:

> Once you recompileAll, they do not fail anymore.

Digging into the code a bit I found out that the pushTemp: bytecode is a
hack to duplicate the value which will be assigned.

The generated code could be improved if Binding >> #value: would
always return its argument. In that case the bytecode could follow the
assignment chain directly:

78 <25> pushConstant: ##ActiveWorld
79 <26> pushConstant: ##ActiveHand
80 <27> pushConstant: ##ActiveEvent
81 <73> pushConstant: nil
82 <CA> send: value:
83 <CA> send: value:
84 <CA> send: value:
85 <87> pop

It doesn't seem to be a simple change though.


Levente

> Still the same problem, Compiler recompileAll will leave unbound CompiledMethod here and there.
>
>
> 2013/4/12 Levente Uzonyi <[hidden email]>
>       On Fri, 12 Apr 2013, Frank Shearar wrote:
>
>             This, and the other decompiler test failure, happens because of the
>             recent chained assignment work:
>
>             original snippet:
>
>                ActiveWorld := ActiveHand := ActiveEvent := nil.
>
>             decompiled version of sameL
>
>                ActiveEvent := nil.
>                ActiveHand := nil.
>                ActiveWorld := nil.
>
>             How to fix?
>
>
> The only method with this assignment chain in my image is MorphicProject
>             #saveState . The bytecodes for this line are:
>
>
> 73 <73> pushConstant: nil
> 74 <81 C5> storeIntoLit: ActiveEvent
> 76 <81 C6> storeIntoLit: ActiveHand
> 78 <82 C7> popIntoLit: ActiveWorld
>
> And the decompiler can reproduce the original code.
>
> If I recompile this method (which should have been done due to the Environments changes, but for some reason it hasn't happened yet), then there's a bug in the compiler. The bytecodes will be:
>
> 78 <25> pushConstant: ##ActiveWorld
> 79 <73> pushConstant: nil
> 80 <27> pushConstant: ##ActiveEvent
> 81 <80 41> pushTemp: 1
> 83 <CA> send: value:
> 84 <87> pop
> 85 <26> pushConstant: ##ActiveHand
> 86 <80 41> pushTemp: 1
> 88 <CA> send: value:
> 89 <87> pop
> 90 <CA> send: value:
> 91 <87> pop
>
> Which are obviously wrong.
>
> Creating a new method with just a simple assignment chain:
>
> foo
>
>         GlobalA := GlobalB := $a
>
> generetes:
>
> 25 <20> pushConstant: ##GlobalA
> 26 <22> pushConstant: $a
> 27 <21> pushConstant: ##GlobalB
> 28 <80 41> pushTemp: 1
> 30 <CA> send: value:
> 31 <87> pop
> 32 <CA> send: value:
> 33 <87> pop
> 34 <78> returnSelf
>
> Which still has the pushTemp: 1. But this method has 0 temporaries, so it's a compiler bug. I wonder how the decompiler can decompile anything
> meaningful from this, and how the VM doesn't crash.
>
>
> Levente
>
>
>       frank
>
>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Tests.Compiler.DecompilerTests.testDecompilerInClassesMNtoMZ

Nicolas Cellier
Changing #value: would be simple, but we preferred to not depend on this.
Current bytecode does completely ignore the returned value, which is a bit more robust.
At least, that was Eliot's choice :)


2013/4/12 Levente Uzonyi <[hidden email]>
On Fri, 12 Apr 2013, Nicolas Cellier wrote:

Once you recompileAll, they do not fail anymore.

Digging into the code a bit I found out that the pushTemp: bytecode is a hack to duplicate the value which will be assigned.

The generated code could be improved if Binding >> #value: would always return its argument. In that case the bytecode could follow the assignment chain directly:

78 <25> pushConstant: ##ActiveWorld
79 <26> pushConstant: ##ActiveHand
80 <27> pushConstant: ##ActiveEvent
81 <73> pushConstant: nil
82 <CA> send: value:
83 <CA> send: value:
84 <CA> send: value:
85 <87> pop

It doesn't seem to be a simple change though.


Levente


Still the same problem, Compiler recompileAll will leave unbound CompiledMethod here and there.


2013/4/12 Levente Uzonyi <[hidden email]>
      On Fri, 12 Apr 2013, Frank Shearar wrote:

            This, and the other decompiler test failure, happens because of the
            recent chained assignment work:

            original snippet:

               ActiveWorld := ActiveHand := ActiveEvent := nil.

            decompiled version of sameL

               ActiveEvent := nil.
               ActiveHand := nil.
               ActiveWorld := nil.

            How to fix?


The only method with this assignment chain in my image is MorphicProject
            #saveState . The bytecodes for this line are:


73 <73> pushConstant: nil
74 <81 C5> storeIntoLit: ActiveEvent
76 <81 C6> storeIntoLit: ActiveHand
78 <82 C7> popIntoLit: ActiveWorld

And the decompiler can reproduce the original code.

If I recompile this method (which should have been done due to the Environments changes, but for some reason it hasn't happened yet), then there's a bug in the compiler. The bytecodes will be:

78 <25> pushConstant: ##ActiveWorld
79 <73> pushConstant: nil
80 <27> pushConstant: ##ActiveEvent
81 <80 41> pushTemp: 1
83 <CA> send: value:
84 <87> pop
85 <26> pushConstant: ##ActiveHand
86 <80 41> pushTemp: 1
88 <CA> send: value:
89 <87> pop
90 <CA> send: value:
91 <87> pop

Which are obviously wrong.

Creating a new method with just a simple assignment chain:

foo

        GlobalA := GlobalB := $a

generetes:

25 <20> pushConstant: ##GlobalA
26 <22> pushConstant: $a
27 <21> pushConstant: ##GlobalB
28 <80 41> pushTemp: 1
30 <CA> send: value:
31 <87> pop
32 <CA> send: value:
33 <87> pop
34 <78> returnSelf

Which still has the pushTemp: 1. But this method has 0 temporaries, so it's a compiler bug. I wonder how the decompiler can decompile anything
meaningful from this, and how the VM doesn't crash.


Levente


      frank