Bytecode patterns for &&
and ||
Think about what a short-circuiting operator like &&
or ||
actually does. You've got some conditional branching. Let's consider &&
. What you're effectively evaluating is:
if (left)
if (right) <do something>
endIf
There is no single bytecode instruction that can describe this behavior. You need need some labels and conditional branching instructions:
.start
<left expression>
IFEQ .endIf // if left evaluates to zero (false), skip to end
<right expression>
IFEQ .endIf // if right evaluates to zero (false), skip to end
.ifTrue
<body of 'if' block>
.endIf
The behavior of the ||
operator is a bit different; in this case, the logic looks something like this:
if (left)
goto .ifTrue
if (!right)
goto .endIf
.ifTrue
<do something>
.endIf
Note how the check on the right operand is inverted to avoid an additional branch when the right operand evaluates to true
. This behavior could be implemented in bytecode like so:
<left operand>
IFNE .ifTrue // if left evaluates true, skip right, enter 'if' body
<right operand>
IFEQ .endIf // if right evaluates false, skip 'if' body
.ifTrue
<do something>
.endIf
When to push your operands
Note that your original question suggested you already have the left and right operands on the stack; that would be bad. You should only evaluate the right operand after the left operand has evaluated to true
(nonzero) for &&
or false
(zero) for ||
. If the right operand causes side effects, evaluating it prematurely would violate the defined behavior of these operators.