Hi Eliot,

Please find attached the two methods.

The class is NativeImageSegment, as found in the current image:

ImageSegment subclass: #NativeImageSegment
instanceVariableNames: ''
classVariableNames: 'BiggestFileNumber'
poolDictionaries: ''
category: 'System-Object Storage'


Thank you,
Florin

On Mon, Jan 9, 2023 at 12:43 AM Eliot Miranda <eliot.miranda@gmail.com> wrote:
 
Hi Florin, can you email me a file out if the undecompilable and decompilable methods plus a class definition and I’ll try and fix it.

_,,,^..^,,,_ (phone)

On Jan 8, 2023, at 7:07 PM, Florin Mateoc <florin.mateoc@gmail.com> wrote:


I meant "I stared at the bytecodes" (not started), and I also realized that I did not explain what I meant by the literal #Marker causing the bug.
If I replace the expression

  (wld := arrayOfRoots
    detect: [:obj1 | obj1 isMorph]
    ifNone: [#Marker]
  ) == #Marker

with

  (wld := arrayOfRoots
    detect: [:obj1 | obj1 isMorph]
    ifNone: []
  ) == nil

or even with

  (wld := arrayOfRoots
    detect: [:obj1 | obj1 isMorph]
    ifNone: [#Marker]
  ) == nil

the bug goes away, and the method is decompilable







On Sun, Jan 8, 2023 at 10:00 PM Florin Mateoc <florin.mateoc@gmail.com> wrote:
Hi,

Happy New Year everybody!

I hope you will forgive my transgression, I know this is not about the VM, it is about the bytecode compiler, but I am only subscribed to this list, and the Squeak compiler is somewhere in between.

I have recently stumbled upon a regression introduced by Compiler-eem.483
One of my generated (transformed) methods is apparently valid Smalltalk - it can still be compiled - but it cannot be decompiled anymore. I am not sure if this is a compiler bug, or a latent decompiler bug exposed by the changes in Compiler-eem.483

My method is below, it is a transformed variant of NativeImageSegment>>findRogueRootsPrep

The bug is somehow caused by the literal #Marker. I have started at the bytecodes and they look ok to me, but the decompiler enters an (apparently unrelated) infinite loop. It is also not just about the literal itself or the immediate surrounding code, the method needs to be big/complex enough (over a certain number of literals?) to trigger the bug.


findRogueRootsPrep1
"Part of the tool to track down unwanted pointers into the segment.  Break all owner pointers in submorphs, scripts, and viewers in flaps."
| wld players morphs |
wld := arrayOfRoots detect: [:obj | obj isMorph and: [obj isWorldMorph]] ifNone: [].
wld == nil ifTrue: [
  (wld := arrayOfRoots
    detect: [:obj1 | obj1 isMorph]
    ifNone: [#Marker]
  ) == #Marker ifTrue: [
    ^ self error: 'can''t find a root morph']].
morphs := IdentitySet new: 400.
wld allMorphsAndBookPagesInto: morphs.
players := wld presenter allExtantPlayers. "just the cached list"
players do: [:pp | | scriptEditors |
  scriptEditors := pp class tileScriptNames collect: [:nn | pp scriptEditorFor: nn].
  scriptEditors do: [:se | morphs addAll: se allMorphs]].
wld submorphs do: [:mm | "non showing flaps"
  (mm isKindOf: FlapTab) ifTrue: [
    mm referent allMorphsAndBookPagesInto: morphs]].
morphs do: [:mm1 | "break the back pointers"
  mm1 isInMemory ifTrue: [
    (mm1 respondsTo: #target) ifTrue: [
      mm1 nearestOwnerThat: [:ow | | zzzTemp |
        ow == mm1 target ifTrue: [
          mm1 target: nil.
          zzzTemp := true
        ] ifFalse: [
          zzzTemp := false].
        zzzTemp]].
    (mm1 respondsTo: #arguments) ifTrue: [
      mm1 arguments do: [:arg |
        arg == nil ifFalse: [
          mm1 nearestOwnerThat: [:ow1 | | zzzTemp1 |
            ow1 == arg ifTrue: [
              mm1 arguments at: (mm1 arguments indexOf: arg) put: nil.
              zzzTemp1 := true
            ] ifFalse: [
              zzzTemp1 := false].
            zzzTemp1]]]].
    mm1 eventHandler == nil ifFalse: ["recipients point back up"
      (morphs includesAllOf: mm1 eventHandler allRecipients) ifTrue: [
        mm1 eventHandler: nil]].
    "temporary, until using Model for PartsBin"
    mm1 isMorphicModel ifTrue: [
      mm1 model isMorphicModel ifTrue: [
        mm1 model breakDependents]].
    mm1 isTextMorph ifTrue: [
      mm1 setContainer: nil]]].
(Smalltalk includesKey: #Owners) ifTrue: [
  Smalltalk at: #Owners put: nil].
"in case findOwnerMap: is commented out"
"self findOwnerMap: morphs."
morphs do: [:mm2 | "break the back pointers"
  mm2 isInMemory ifTrue: [
    mm2 privateOwner: nil]]


Florin