&& 和 || 的字节码模式
想想像&& 或|| 这样的短路运算符实际上做了什么。你有一些条件分支。让我们考虑&&。您正在有效评估的是:
if (left)
if (right) <do something>
endIf
没有单一的字节码指令可以描述这种行为。您需要一些标签和条件分支指令:
.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
|| 操作符的行为有点不同;在这种情况下,逻辑如下所示:
if (left)
goto .ifTrue
if (!right)
goto .endIf
.ifTrue
<do something>
.endIf
注意当右操作数的计算结果为true 时,如何反转对右操作数的检查以避免额外的分支。这种行为可以像这样在字节码中实现:
<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
何时推送操作数
请注意,您最初的问题表明您已经在堆栈中拥有左右操作数;那会很糟糕。对于&& 或false(零)对于||,您应该只在左操作数评估为true(非零)之后评估右操作数。如果正确的操作数引起副作用,过早地对其进行评估将违反这些运算符的定义行为。