[Newcompiler] How to decompile #while{True,False}

Mathieu Suen mathk.sue at gmail.com
Tue Sep 4 22:06:55 UTC 2007


Hi

In a very particular case the compiler optimize the #whileTrue in a  
way that the Decompiler can't find the roght code.

This particular case is:

[
self somthings

aTest
	ifTrue:[ok anOtherThings
		ifTrue:[here doSomthings. true]
		ifFalse:[false]]
	ifFalse:[false]
] whileTrue

The typical exemple is from  Project class>>#sweep: :

>> 		[(ind _ ind + 1) > list size
> 			ifFalse: [(parts at: ind) first asLowercase = projectName
> 				ifTrue: [versions add: (parts at: ind).  true]
> 				ifFalse: [false]]
> 			ifTrue: [false]] whileTrue.
>
The corresponding bytecode is:

> 199 <14> pushTemp: 4
> 200 <76> pushConstant: 1
> 201 <B0> send: +
> 202 <81 44> storeIntoTemp: 4
> 204 <12> pushTemp: 2
> 205 <C2> send: size
> 206 <B3> send: >
> 207 <A8 16> jumpTrue: 231
>
> 209 <13> pushTemp: 3
> 210 <14> pushTemp: 4
> 211 <C0> send: at:
> 212 <83 14> send: first
> 214 <83 15> send: asLowercase
> 216 <16> pushTemp: 6
> 217 <B6> send: =
> 218 <AC 0B> jumpFalse: 231
>
> 220 <17> pushTemp: 7
> 221 <13> pushTemp: 3
> 222 <14> pushTemp: 4
> 223 <C0> send: at:
> 224 <83 37> send: add:
> 226 <87> pop
> 227 <71> pushConstant: true
> 228 <99> jumpFalse: 231
>
> 229 <A3 E0> jumpTo: 199


So the first #ifFlase:ifTrue: has been compact to a single jump:
207 <A8 16> jumpTrue: 231

This avoid pushing false and make an unconditional jump to the end of  
the nearly end of the block.
We also have the same optimazation for the inner #iTrue:ifFalse:  
message (i.e. at bytecode: 218 and: 228).

We can rewrite the code to produce the same flow :

> [((ind _ ind + 1) > list size) not
> 			or: [(parts at: ind) first asLowercase = projectName
> 				and: [versions add: (parts at: ind)]]]] whileTrue

This is what the decompiler found out.
But this do not produce the same bytecode:

> 203 <14> pushTemp: 4
> 204 <76> pushConstant: 1
> 205 <B0> send: +
> 206 <81 44> storeIntoTemp: 4
> 208 <12> pushTemp: 2
> 209 <C2> send: size
> 210 <B3> send: >
> 211 <83 18> send: not
> 213 <A8 12> jumpTrue: 233
>
> 215 <13> pushTemp: 3
> 216 <14> pushTemp: 4
> 217 <C0> send: at:
> 218 <83 14> send: first
> 220 <83 15> send: asLowercase
> 222 <16> pushTemp: 6
> 223 <B6> send: =
> 224 <AC 09> jumpFalse: 235
>
> 226 <17> pushTemp: 7
> 227 <13> pushTemp: 3
> 228 <14> pushTemp: 4
> 229 <C0> send: at:
> 230 <83 37> send: add:
> 232 <99> jumpFalse: 235
>
> 233 <A3 E0> jumpTo: 203

The only difference is in the bytecode 211 and 213:
A "send: not" is added and the jump don't have the same destination.

The old compiler dose not make this smart optimization.
So I have several  question.

Do we want the decompiler produce different bytecode (i.e. adding a  
"send: not"…)?
Should we do such optimization? (IMO I don't thinks so.)
where dose the optimization take place? I can't figure out where it  
is. I get lost inside ASTTranslator and IRTranslator.


Thanks

	Mth





More information about the Newcompiler mailing list