diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-09-05 15:30:45 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-09-05 15:30:45 -0300 |
| commit | 14e416355f83cf0a1b871eedec2c92b86dbe76d6 (patch) | |
| tree | 620c7fa0b811d5f91d3d2f9b4879b289df6d137c /testes | |
| parent | f33cda8d6eb1cac5b9042429e85f1096175c7ca5 (diff) | |
| download | lua-14e416355f83cf0a1b871eedec2c92b86dbe76d6.tar.gz lua-14e416355f83cf0a1b871eedec2c92b86dbe76d6.tar.bz2 lua-14e416355f83cf0a1b871eedec2c92b86dbe76d6.zip | |
Added suport for Fixed Buffers
A fixed buffer keeps a binary chunk "forever", so that the program
does not need to copy some of its parts when loading it.
Diffstat (limited to 'testes')
| -rw-r--r-- | testes/api.lua | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/testes/api.lua b/testes/api.lua index dece98f5..181c1d53 100644 --- a/testes/api.lua +++ b/testes/api.lua | |||
| @@ -407,7 +407,7 @@ do | |||
| 407 | concat 3]]) == "hi alo mundo") | 407 | concat 3]]) == "hi alo mundo") |
| 408 | 408 | ||
| 409 | -- "argerror" without frames | 409 | -- "argerror" without frames |
| 410 | assert(T.checkpanic("loadstring 4") == | 410 | assert(T.checkpanic("loadstring 4 name bt") == |
| 411 | "bad argument #4 (string expected, got no value)") | 411 | "bad argument #4 (string expected, got no value)") |
| 412 | 412 | ||
| 413 | 413 | ||
| @@ -420,7 +420,7 @@ do | |||
| 420 | if not _soft then | 420 | if not _soft then |
| 421 | local msg = T.checkpanic[[ | 421 | local msg = T.checkpanic[[ |
| 422 | pushstring "function f() f() end" | 422 | pushstring "function f() f() end" |
| 423 | loadstring -1; call 0 0 | 423 | loadstring -1 name t; call 0 0 |
| 424 | getglobal f; call 0 0 | 424 | getglobal f; call 0 0 |
| 425 | ]] | 425 | ]] |
| 426 | assert(string.find(msg, "stack overflow")) | 426 | assert(string.find(msg, "stack overflow")) |
| @@ -430,7 +430,7 @@ do | |||
| 430 | assert(T.checkpanic([[ | 430 | assert(T.checkpanic([[ |
| 431 | pushstring "return {__close = function () Y = 'ho'; end}" | 431 | pushstring "return {__close = function () Y = 'ho'; end}" |
| 432 | newtable | 432 | newtable |
| 433 | loadstring -2 | 433 | loadstring -2 name t |
| 434 | call 0 1 | 434 | call 0 1 |
| 435 | setmetatable -2 | 435 | setmetatable -2 |
| 436 | toclose -1 | 436 | toclose -1 |
| @@ -458,6 +458,8 @@ if not _soft then | |||
| 458 | print'+' | 458 | print'+' |
| 459 | end | 459 | end |
| 460 | 460 | ||
| 461 | |||
| 462 | |||
| 461 | local lim = _soft and 500 or 12000 | 463 | local lim = _soft and 500 or 12000 |
| 462 | local prog = {"checkstack " .. (lim * 2 + 100) .. "msg", "newtable"} | 464 | local prog = {"checkstack " .. (lim * 2 + 100) .. "msg", "newtable"} |
| 463 | for i = 1,lim do | 465 | for i = 1,lim do |
| @@ -481,10 +483,20 @@ for i = 1,lim do assert(t[i] == i*10); t[i] = undef end | |||
| 481 | assert(next(t) == nil) | 483 | assert(next(t) == nil) |
| 482 | prog, g, t = nil | 484 | prog, g, t = nil |
| 483 | 485 | ||
| 486 | do -- shrink stack | ||
| 487 | local m1, m2 = 0, collectgarbage"count" * 1024 | ||
| 488 | while m1 ~= m2 do -- repeat until stable | ||
| 489 | collectgarbage() | ||
| 490 | m1 = m2 | ||
| 491 | m2 = collectgarbage"count" * 1024 | ||
| 492 | end | ||
| 493 | end | ||
| 494 | |||
| 495 | |||
| 484 | -- testing errors | 496 | -- testing errors |
| 485 | 497 | ||
| 486 | a = T.testC([[ | 498 | a = T.testC([[ |
| 487 | loadstring 2; pcall 0 1 0; | 499 | loadstring 2 name t; pcall 0 1 0; |
| 488 | pushvalue 3; insert -2; pcall 1 1 0; | 500 | pushvalue 3; insert -2; pcall 1 1 0; |
| 489 | pcall 0 0 0; | 501 | pcall 0 0 0; |
| 490 | return 1 | 502 | return 1 |
| @@ -498,7 +510,7 @@ local function check3(p, ...) | |||
| 498 | assert(#arg == 3) | 510 | assert(#arg == 3) |
| 499 | assert(string.find(arg[3], p)) | 511 | assert(string.find(arg[3], p)) |
| 500 | end | 512 | end |
| 501 | check3(":1:", T.testC("loadstring 2; return *", "x=")) | 513 | check3(":1:", T.testC("loadstring 2 name t; return *", "x=")) |
| 502 | check3("%.", T.testC("loadfile 2; return *", ".")) | 514 | check3("%.", T.testC("loadfile 2; return *", ".")) |
| 503 | check3("xxxx", T.testC("loadfile 2; return *", "xxxx")) | 515 | check3("xxxx", T.testC("loadfile 2; return *", "xxxx")) |
| 504 | 516 | ||
| @@ -509,6 +521,35 @@ local function checkerrnopro (code, msg) | |||
| 509 | assert(not stt and string.find(err, msg)) | 521 | assert(not stt and string.find(err, msg)) |
| 510 | end | 522 | end |
| 511 | 523 | ||
| 524 | |||
| 525 | do | ||
| 526 | print("testing load of binaries in fixed buffers") | ||
| 527 | local source = {} | ||
| 528 | local N = 1000 | ||
| 529 | -- create a somewhat "large" source | ||
| 530 | for i = 1, N do source[i] = "X = X + 1; " end | ||
| 531 | source = table.concat(source) | ||
| 532 | -- give chunk an explicit name to avoid using source as name | ||
| 533 | source = load(source, "name1") | ||
| 534 | -- dump without debug information | ||
| 535 | source = string.dump(source, true) | ||
| 536 | -- each "X=X+1" generates 4 opcodes with 4 bytes each | ||
| 537 | assert(#source > N * 4 * 4) | ||
| 538 | collectgarbage(); collectgarbage() | ||
| 539 | local m1 = collectgarbage"count" * 1024 | ||
| 540 | -- load dump using fixed buffer | ||
| 541 | local code = T.testC([[ | ||
| 542 | loadstring 2 name B; | ||
| 543 | return 1 | ||
| 544 | ]], source) | ||
| 545 | collectgarbage() | ||
| 546 | local m2 = collectgarbage"count" * 1024 | ||
| 547 | -- load used fewer than 300 bytes | ||
| 548 | assert(m2 > m1 and m2 - m1 < 300) | ||
| 549 | X = 0; code(); assert(X == N); X = nil | ||
| 550 | end | ||
| 551 | |||
| 552 | |||
| 512 | if not _soft then | 553 | if not _soft then |
| 513 | collectgarbage("stop") -- avoid __gc with full stack | 554 | collectgarbage("stop") -- avoid __gc with full stack |
| 514 | checkerrnopro("pushnum 3; call 0 0", "attempt to call") | 555 | checkerrnopro("pushnum 3; call 0 0", "attempt to call") |
