Lua 在发出字节码时如何利用 <const>?

问题描述 投票:0回答:1

我正在摆弄 Lua 并使用 https://www.luac.nl/ 来看看它如何转换为字节码。我想看看像

if boolean_always_true then ... end
这样用
<const>
定义布尔值的模式是否会得到优化。与始终为 false 布尔值相同。

local always_true <const> = true
local always_false <const> = false

function foo()
  if always_true then
      print("Hello World!")
  end
end

function bar()
  if always_false then
      print("Hello World!")
  end
end

最终成为

function foo() --line 4 through 8
1   GETTABUP    0 0 0   ; _ENV "print"
2   LOADK   1 1 ; "Hello World!"
3   CALL    0 2 1   ; 1 in 0 out
4   RETURN0

function bar() --line 10 through 14
1   LOADFALSE   0   
2   TEST    0 0 
3   JMP 3   to pc 7
4   GETTABUP    0 0 0   ; _ENV "print"
5   LOADK   1 1 ; "Hello World!"
6   CALL    0 2 1   ; 1 in 0 out
7   RETURN0 

为什么

always_true
情况得到优化,
if
消失,而
always_false
情况却没有?

我尝试了不同的代码配置,并使用 https://www.luac.nl/ 查看生成的字节码。我原以为

bar
只是
RETURN0

optimization lua compiler-optimization bytecode
1个回答
0
投票

这与无关,你可以使用旧版本的Lua(<= 5.1.4) to test the code below:

function bar()
  if false then
      print("Hello World!")
  end
end

您将看到优化的结果:

JMP        3    ;jump to return
GETGLOBAL  0 -1
LOADK      1 -2
CALL       0 2 1    
RETURN     0 1

很好,对吧?但这里隐藏着一个问题。众所周知,Lua 中的逻辑运算符(

and
or
)非常独特。其实它们和
if-else
等一些语句的逻辑是一样的,直接跳起来会导致这样的bug:

--[[
 <= 5.1.4: nil
 >= 5.1.5: false
]]
print(((nil and nil) or false) and true)

由于最后一个

(nil and nil) or false
的左边表达式(
and
)明显为假,所以lua跳过了对该表达式的值的求值,导致最终结果存在一些细微的偏差。所以lua的解决方案总是评估虚假表达式。

你可能会问有没有更好的解决方案,我想肯定有,但是你也要知道lua的开发者很少。

© www.soinside.com 2019 - 2024. All rights reserved.