pharo-project / pharo

Pharo is a dynamic reflective pure object-oriented language supporting live programming inspired by Smalltalk.
http://pharo.org
Other
1.21k stars 355 forks source link

whileTrue: et al unnecessarily consume stack #9409

Open martinmcclure opened 3 years ago

martinmcclure commented 3 years ago

Describe the problem whileTrue: and related messages are optimized by the bytecode compiler when the receiver (and argument, where applicable) are literal blocks. When this condition is not met, a normal message send is compiled and at runtime the corresponding method (such as BlockClosure>>whileTrue:) is evaluated. These methods are implemented in a tail-recursive manner. Since Pharo does not currently have tail-call elimination, this consumes stack space. For example, you can try this doit:

| b |
b := [  true ].
b whileTrue: [  ].

and watch Pharo rapidly consume memory until ctrl-. This expression should consume CPU, but there is no need for it to consume significant memory.

Classes involved BlockClosure

Proposal BlockClosure>>whileTrue is currently implemented as

    self value ifTrue: [ aBlock value. self whileTrue: aBlock ].
    ^ nil

it could avoid consuming stack if implemented as

    [ self value ] whileTrue: [ aBlock value ].
    ^ nil

Similar changes are needed for at least whileFalse, whileFalse:, whileTrue, and whileTrue:.

Version information:

Expected development cost This one's fairly simple. Perhaps a day to write tests, make the changes, run regression tests, and so on. Alas, I don't have a day to spare right now.

Also, it is conceivable that the non-optimized implementations are needed for the bootstrapping process. If so, the fix would involve replacing the initial implementations later in the build process, and in that case this should be done by or with consultation from someone familiar with the bootstrap/build process.

guillep commented 3 years ago

Yes, good catch. Probably making the change and letting the CI run is enough?

Although in a random image I took I see 53 senders and all of them are using the optimised version and never going through this one...