Decompiler failure

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

Decompiler failure

Tobias Pape
Hey all


the following code fails to be decompiled by the
Decompiler and I have no clue:

retryOnce: aTryBlock
        | retry |
        retry := true.
        [[retry] whileTrue: [|result|
                result := aTryBlock value.
                retry := false.
                ^ result
        ]] on: Error do: [:e |
                retry := (e isKindOf: NetworkError) not
        ].



Apparently, the Decompilers stack is empty but it tries to access
its last element, which results in an indexing error.

Best
        -Tobias



signature.asc (1K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Decompiler failure

Levente Uzonyi-2
On Mon, 3 Nov 2014, Tobias Pape wrote:

> Hey all
>
>
> the following code fails to be decompiled by the
> Decompiler and I have no clue:
>
> retryOnce: aTryBlock
> | retry |
> retry := true.
> [[retry] whileTrue: [|result|
> result := aTryBlock value.
> retry := false.
> ^ result
> ]] on: Error do: [:e |
> retry := (e isKindOf: NetworkError) not
> ].
>
>
>
> Apparently, the Decompilers stack is empty but it tries to access
> its last element, which results in an indexing error.

The problem is that BlockLocalTempCounter tempCountForBlockStartingAt: pc
in: method returns 67 (the value of its stackPointer) instead of 1 (the
number of local temporaries in the first block of the method) in
#doClosureCopyCopiedValues:numArgs:blockSize: when pc is 50.

It seems to me that it's a bug in BlockLocalTempCounter >> #doJoin,
because it sets its own stackPointer to a pc value.
Decompilation works for me with the following implementation:

doJoin
  scanner pc < blockEnd ifTrue: [
  joinOffsets at: scanner pc ifPresent: [ :sp | stackPointer := sp ] ]

The comment of the methods tells something about the #ifAbsent: branch,
but I don't see how that should work.

Also the comment in #tempCountForBlockAt:in: says

  There are short-cuts.  The ones we take here are
  - if there is no sequence of push nils there can be no local temps
  - we follow forward jumps to shorten the amount of scanning

But it seems to me that the second part is not implemented.

Levente

>
> Best
> -Tobias
>

Reply | Threaded
Open this post in threaded view
|

Re: Decompiler failure

ccrosetti
Hi, is this the right list to post questions about squeak android vm tablet?

Thanks, Carlos

----- Original Message -----
From: "Levente Uzonyi" <[hidden email]>
To: "The general-purpose Squeak developers list"
<[hidden email]>
Sent: Monday, November 03, 2014 9:23 PM
Subject: Re: [squeak-dev] Decompiler failure


> On Mon, 3 Nov 2014, Tobias Pape wrote:
>
>> Hey all
>>
>>
>> the following code fails to be decompiled by the
>> Decompiler and I have no clue:
>>
>> retryOnce: aTryBlock
>> | retry |
>> retry := true.
>> [[retry] whileTrue: [|result|
>> result := aTryBlock value.
>> retry := false.
>> ^ result
>> ]] on: Error do: [:e |
>> retry := (e isKindOf: NetworkError) not
>> ].
>>
>>
>>
>> Apparently, the Decompilers stack is empty but it tries to access
>> its last element, which results in an indexing error.
>
> The problem is that BlockLocalTempCounter tempCountForBlockStartingAt: pc
> in: method returns 67 (the value of its stackPointer) instead of 1 (the
> number of local temporaries in the first block of the method) in
> #doClosureCopyCopiedValues:numArgs:blockSize: when pc is 50.
>
> It seems to me that it's a bug in BlockLocalTempCounter >> #doJoin,
> because it sets its own stackPointer to a pc value.
> Decompilation works for me with the following implementation:
>
> doJoin
>  scanner pc < blockEnd ifTrue: [
>  joinOffsets at: scanner pc ifPresent: [ :sp | stackPointer := sp ] ]
>
> The comment of the methods tells something about the #ifAbsent: branch,
> but I don't see how that should work.
>
> Also the comment in #tempCountForBlockAt:in: says
>
>  There are short-cuts.  The ones we take here are
>  - if there is no sequence of push nils there can be no local temps
>  - we follow forward jumps to shorten the amount of scanning
>
> But it seems to me that the second part is not implemented.
>
> Levente
>
>>
>> Best
>> -Tobias
>>
>


Reply | Threaded
Open this post in threaded view
|

Re: Decompiler failure

marcel.taeumel (old)
In reply to this post by Tobias Pape
What's the semantics of this piece of Smalltalk code? o.O

If "aTryBlock value" raises an error, retry will be set to "true" for all non-network errors. But then? There is no resume. Hmm... Cannot figure out why this will be retried only once? Should be retried forever then? Is there some implicity magic hidden somewhere? :)

Best,
Marcel
Reply | Threaded
Open this post in threaded view
|

Re: Decompiler failure

Tobias Pape
Hi.

On 04.11.2014, at 06:19, Marcel Taeumel <[hidden email]> wrote:

> What's the semantics of this piece of Smalltalk code? o.O
>
> If "aTryBlock value" raises an error, retry will be set to "true" for all
> non-network errors. But then? There is no resume. Hmm... Cannot figure out
> why this will be retried only once? Should be retried forever then? Is there
> some implicity magic hidden somewhere? :)

The code is plain incorrect. I was debugging it and hence
hit the decompiler bug, because “toggle halt on entry” effects
the browser to try to decompile it (which is fine).
  My working implementation is now this:

retryOnce: aTryBlock
        | again |
        again := true.
        [^ aTryBlock value.
        ] on: Error do: [:e |
                ((e isKindOf: NetworkError) or: [again not])
                        ifTrue: [e pass]
                        ifFalse: [again := false. e retry]].

Best
        -Tobias



signature.asc (1K) Download Attachment