luago-book
luago-book copied to clipboard
请教一下第10章 关于upvalue的问题
您好,首先十分感谢作者,这本书对帮助我理解虚拟机底层运行机制帮助很大。目前看到第10章,也参考了这个仓库自己实现了一个Rust版本。 在实现好第10章的内容后对upvalue的一些情况做了测试,但是发现有一种情况不能通过,debug后觉得可能是对于upvalue的引用问题。 用例代码如下:
local step = 1
local start = 0
local function assert(v)
if not v then
fail()
end
end
function newCounter()
local count = start
return function()
count = count + step
return count
end
end
c1 = newCounter()
assert(c1() == 1)
assert(c1() == 2)
c2 = newCounter()
assert(c2() == 1) -- 3
assert(c1() == 3) -- 4
assert(c2() == 2) -- 5
似乎是因为newCounter
获取到start
给count
之后,后续对count
的更改都会同时反馈在最外层的start
上。
我想请教一下,lua对于这种情况闭包获取到的upvalue的生命周期是不是还有其他的处理呢?如果有的话是如何实现的呢,在官方c实现的版本里应该去了解哪部分的代码?
如果您方便的话请您帮忙解答一下,非常感谢!
编译器版本: Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio 操作系统: macOS 11.3.1 附编译后的指令:
main <tests/upvalue.lua:0,0> (52 instructions at 0x7f8d3a406590)
0+ params, 5 slots, 1 upvalue, 3 locals, 7 constants, 2 functions
1 [1] LOADK 0 -1 ; 1
2 [2] LOADK 1 -2 ; 0
3 [7] CLOSURE 2 0 ; 0x7f8d3a406700
4 [14] CLOSURE 3 1 ; 0x7f8d3a406b40
5 [8] SETTABUP 0 -3 3 ; _ENV "newCounter"
6 [16] GETTABUP 3 0 -3 ; _ENV "newCounter"
7 [16] CALL 3 1 2
8 [16] SETTABUP 0 -4 3 ; _ENV "c1"
9 [17] MOVE 3 2
10 [17] GETTABUP 4 0 -4 ; _ENV "c1"
11 [17] CALL 4 1 2
12 [17] EQ 1 4 -1 ; - 1
13 [17] JMP 0 1 ; to 15
14 [17] LOADBOOL 4 0 1
15 [17] LOADBOOL 4 1 0
16 [17] CALL 3 2 1
17 [18] MOVE 3 2
18 [18] GETTABUP 4 0 -4 ; _ENV "c1"
19 [18] CALL 4 1 2
20 [18] EQ 1 4 -5 ; - 2
21 [18] JMP 0 1 ; to 23
22 [18] LOADBOOL 4 0 1
23 [18] LOADBOOL 4 1 0
24 [18] CALL 3 2 1
25 [20] GETTABUP 3 0 -3 ; _ENV "newCounter"
26 [20] CALL 3 1 2
27 [20] SETTABUP 0 -6 3 ; _ENV "c2"
28 [21] MOVE 3 2
29 [21] GETTABUP 4 0 -6 ; _ENV "c2"
30 [21] CALL 4 1 2
31 [21] EQ 1 4 -1 ; - 1
32 [21] JMP 0 1 ; to 34
33 [21] LOADBOOL 4 0 1
34 [21] LOADBOOL 4 1 0
35 [21] CALL 3 2 1
36 [22] MOVE 3 2
37 [22] GETTABUP 4 0 -4 ; _ENV "c1"
38 [22] CALL 4 1 2
39 [22] EQ 1 4 -7 ; - 3
40 [22] JMP 0 1 ; to 42
41 [22] LOADBOOL 4 0 1
42 [22] LOADBOOL 4 1 0
43 [22] CALL 3 2 1
44 [23] MOVE 3 2
45 [23] GETTABUP 4 0 -6 ; _ENV "c2"
46 [23] CALL 4 1 2
47 [23] EQ 1 4 -5 ; - 2
48 [23] JMP 0 1 ; to 50
49 [23] LOADBOOL 4 0 1
50 [23] LOADBOOL 4 1 0
51 [23] CALL 3 2 1
52 [23] RETURN 0 1
constants (7) for 0x7f8d3a406590:
1 1
2 0
3 "newCounter"
4 "c1"
5 2
6 "c2"
7 3
locals (3) for 0x7f8d3a406590:
0 step 2 53
1 start 3 53
2 assert 4 53
upvalues (1) for 0x7f8d3a406590:
0 _ENV 1 0
function <tests/upvalue.lua:3,7> (5 instructions at 0x7f8d3a406700)
1 param, 2 slots, 1 upvalue, 1 local, 1 constant, 0 functions
1 [4] TEST 0 1
2 [4] JMP 0 2 ; to 5
3 [5] GETTABUP 1 0 -1 ; _ENV "fail"
4 [5] CALL 1 1 1
5 [7] RETURN 0 1
constants (1) for 0x7f8d3a406700:
1 "fail"
locals (1) for 0x7f8d3a406700:
0 v 1 6
upvalues (1) for 0x7f8d3a406700:
0 _ENV 0 0
function <tests/upvalue.lua:8,14> (4 instructions at 0x7f8d3a406b40)
0 params, 2 slots, 2 upvalues, 1 local, 0 constants, 1 function
1 [9] GETUPVAL 0 0 ; start
2 [13] CLOSURE 1 0 ; 0x7f8d3a406c40
3 [13] RETURN 1 2
4 [14] RETURN 0 1
constants (0) for 0x7f8d3a406b40:
locals (1) for 0x7f8d3a406b40:
0 count 2 5
upvalues (2) for 0x7f8d3a406b40:
0 start 1 1
1 step 1 0
function <tests/upvalue.lua:10,13> (7 instructions at 0x7f8d3a406c40)
0 params, 2 slots, 2 upvalues, 0 locals, 0 constants, 0 functions
1 [11] GETUPVAL 0 0 ; count
2 [11] GETUPVAL 1 1 ; step
3 [11] ADD 0 0 1
4 [11] SETUPVAL 0 0 ; count
5 [12] GETUPVAL 0 0 ; count
6 [12] RETURN 0 2
7 [13] RETURN 0 1
constants (0) for 0x7f8d3a406c40:
locals (0) for 0x7f8d3a406c40:
upvalues (2) for 0x7f8d3a406c40:
0 count 1 0
1 step 0 1
请问一下具体的问题是什么?是说这个测试用书中的代码执行结果和CLua不一致吗?