Merge branch 'master' into merge

This commit is contained in:
Arseny Kapoulkine 2022-08-18 14:06:14 -07:00
commit d614f43ebe
6 changed files with 31 additions and 11 deletions

View File

@ -13,9 +13,7 @@ on:
jobs: jobs:
callgrind: callgrind:
name: callgrind
strategy: strategy:
fail-fast: false
matrix: matrix:
os: [ubuntu-22.04] os: [ubuntu-22.04]
benchResultsRepo: benchResultsRepo:
@ -44,9 +42,9 @@ jobs:
run: | run: |
python bench/bench.py --callgrind --vm "./luau-gcc -O2" | tee -a bench-gcc-output.txt python bench/bench.py --callgrind --vm "./luau-gcc -O2" | tee -a bench-gcc-output.txt
- name: Run benchmark (bench-clang) - name: Run benchmark (bench)
run: | run: |
python bench/bench.py --callgrind --vm "./luau -O2" | tee -a bench-clang-output.txt python bench/bench.py --callgrind --vm "./luau -O2" | tee -a bench-output.txt
- name: Run benchmark (analyze) - name: Run benchmark (analyze)
run: | run: |
@ -78,13 +76,13 @@ jobs:
token: ${{ secrets.BENCH_GITHUB_TOKEN }} token: ${{ secrets.BENCH_GITHUB_TOKEN }}
path: "./gh-pages" path: "./gh-pages"
- name: Store results (bench-clang) - name: Store results (bench)
uses: Roblox/rhysd-github-action-benchmark@v-luau uses: Roblox/rhysd-github-action-benchmark@v-luau
with: with:
name: callgrind clang name: callgrind clang
tool: "benchmarkluau" tool: "benchmarkluau"
output-file-path: ./bench-clang-output.txt output-file-path: ./bench-output.txt
external-data-json-path: ./gh-pages/bench-clang.json external-data-json-path: ./gh-pages/bench.json
- name: Store results (bench-gcc) - name: Store results (bench-gcc)
uses: Roblox/rhysd-github-action-benchmark@v-luau uses: Roblox/rhysd-github-action-benchmark@v-luau

View File

@ -1209,7 +1209,10 @@ void* lua_newuserdatadtor(lua_State* L, size_t sz, void (*dtor)(void*))
{ {
luaC_checkGC(L); luaC_checkGC(L);
luaC_checkthreadsleep(L); luaC_checkthreadsleep(L);
Udata* u = luaU_newudata(L, sz + sizeof(dtor), UTAG_IDTOR); size_t as = sz + sizeof(dtor);
if (as < sizeof(dtor))
as = SIZE_MAX; // Will cause a memory error in luaU_newudata.
Udata* u = luaU_newudata(L, as, UTAG_IDTOR);
memcpy(&u->data + sz, &dtor, sizeof(dtor)); memcpy(&u->data + sz, &dtor, sizeof(dtor));
setuvalue(L, L->top, u); setuvalue(L, L->top, u);
api_incr_top(L); api_incr_top(L);

View File

@ -70,6 +70,7 @@ Sandboxing challenges are [covered in the dedicated section](sandbox).
| `bit32` library | ✔️ | | | `bit32` library | ✔️ | |
| `string.gsub` is stricter about using `%` on special characters only | ✔️ | | | `string.gsub` is stricter about using `%` on special characters only | ✔️ | |
| light C functions | 😞 | this changes semantics of fenv on C functions and has complex implications wrt runtime performance | | light C functions | 😞 | this changes semantics of fenv on C functions and has complex implications wrt runtime performance |
| NaN keys are supported for tables with `__newindex` | ✔️ | |
Two things that are important to call out here are various new metamethods for tables and yielding in metamethods. In both cases, there are performance implications to supporting this - our implementation is *very* highly tuned for performance, so any changes that affect the core fundamentals of how Lua works have a price. To support yielding in metamethods we'd need to make the core of the VM more involved, since almost every single "interesting" opcode would need to learn how to be resumable - which also complicates future JIT/AOT story. Metamethods in general are important for extensibility, but very challenging to deal with in implementation, so we err on the side of not supporting any new metamethods unless a strong need arises. Two things that are important to call out here are various new metamethods for tables and yielding in metamethods. In both cases, there are performance implications to supporting this - our implementation is *very* highly tuned for performance, so any changes that affect the core fundamentals of how Lua works have a price. To support yielding in metamethods we'd need to make the core of the VM more involved, since almost every single "interesting" opcode would need to learn how to be resumable - which also complicates future JIT/AOT story. Metamethods in general are important for extensibility, but very challenging to deal with in implementation, so we err on the side of not supporting any new metamethods unless a strong need arises.

View File

@ -326,7 +326,6 @@ Luau uses comments that start from `!` to control certain aspects of analysis, f
--!nostrict --!nostrict
-- Unknown comment directive 'nostrict'; did you mean 'nonstrict'?" -- Unknown comment directive 'nostrict'; did you mean 'nonstrict'?"
``` ```
```
## IntegerParsing (27) ## IntegerParsing (27)

View File

@ -51,8 +51,10 @@ end
To support self-iterating objects, we modify the iteration protocol as follows: instead of simply expanding the result of expression `iter` into three variables (`gen`, `state` and `index`), we check if the first result has an `__iter` metamethod (which can be the case if it's a table, userdata or another composite object (e.g. a record in the future). If it does, the metamethod is called with `gen` as the first argument, and the returned three values replace `gen`/`state`/`index`. This happens *before* the loop: To support self-iterating objects, we modify the iteration protocol as follows: instead of simply expanding the result of expression `iter` into three variables (`gen`, `state` and `index`), we check if the first result has an `__iter` metamethod (which can be the case if it's a table, userdata or another composite object (e.g. a record in the future). If it does, the metamethod is called with `gen` as the first argument, and the returned three values replace `gen`/`state`/`index`. This happens *before* the loop:
```lua ```lua
if getmetatable(gen) and getmetatable(gen).__iter then local genmt = rawgetmetatable(gen) -- pseudo code for getmetatable that bypasses __metatable
gen, state, index = getmetatable(gen).__iter(gen) local iterf = genmt and rawget(genmt, "__iter")
if iterf then
gen, state, index = iterf(gen)
end end
``` ```

View File

@ -716,6 +716,23 @@ TEST_CASE("Reference")
CHECK(dtorhits == 2); CHECK(dtorhits == 2);
} }
TEST_CASE("NewUserdataOverflow")
{
StateRef globalState(luaL_newstate(), lua_close);
lua_State* L = globalState.get();
lua_pushcfunction(L, [](lua_State* L1) {
// The following userdata request might cause an overflow.
lua_newuserdatadtor(L1, SIZE_MAX, [](void* d){});
// The overflow might segfault in the following call.
lua_getmetatable(L1, -1);
return 0;
}, "PCall");
CHECK(lua_pcall(L, 0, 0, 0) == LUA_ERRRUN);
CHECK(strcmp(lua_tostring(L, -1), "memory allocation error: block too big") == 0);
}
TEST_CASE("ApiTables") TEST_CASE("ApiTables")
{ {
StateRef globalState(luaL_newstate(), lua_close); StateRef globalState(luaL_newstate(), lua_close);