Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating JVM bytecode for a unary not expression

Let's say you're writing a Java (or subset-of-Java) compiler and you want to generate bytecode for a unary not expression, !E. You're past type checking so you know E has type boolean, i.e. it will push a 1 or a 0 on to the operand stack.

One way to do it is something like (in Jasmin syntax):

E
ifeq truelabel
iconst_0
goto stoplabel
truelabel:
iconst_1
stoplabel:

i.e. if there's a 0 on the stack push 1, else push 0. Another way to do it, taking advantage of the fact that a boolean is just an int with value 1 or 0, is to say !E = (E + 1) % 2 and generate

E
iconst_1
iadd
iconst_2
irem

Is there an advantage to using one over the other? Or something else entirely?

like image 988
Ismail Badawi Avatar asked Oct 14 '12 21:10

Ismail Badawi


2 Answers

I once tried to write a Java decompiler, so I used to know what code javac generated. As I recall, javac 1.0.x used !E = E ? false : true while javac 1.1 used !E = E ^ 1 (bitwise XOR).

like image 63
Neil Avatar answered Sep 19 '22 12:09

Neil


I wouldn't count on the following definition to hold true on the bytecode level.

true == 1

On the binary level (and its almost language independent), a boolean is usually defined as

false == 0
true != 0

The javac compiler apparently also follows this definition (all checks in javac bytecode I have seen just always checks agains ZERO, never against ONE).

And it makes sense to use this definition for boolean instead only treating 1 as true, C also defines it this way (true is just != 0, not simply 1) and in assembly code this convention is also commonly used. So java also using this definition makes it possible to take/pass java booleans to other code without any special conversions.

I suspect your first code example (with the ifeq) is the only way to correctly implement the not-operator for booleans. The ^1-method (xor with 1) will fail if the boolean value is not strcitly represented as 0/1. Any other int value would cause the expression to work incorrectly.

like image 28
Durandal Avatar answered Sep 20 '22 12:09

Durandal