diff options
Diffstat (limited to 'src/lj_api.c')
| -rw-r--r-- | src/lj_api.c | 416 |
1 files changed, 258 insertions, 158 deletions
diff --git a/src/lj_api.c b/src/lj_api.c index a99a81af..6369c17d 100644 --- a/src/lj_api.c +++ b/src/lj_api.c | |||
| @@ -24,11 +24,12 @@ | |||
| 24 | #include "lj_trace.h" | 24 | #include "lj_trace.h" |
| 25 | #include "lj_vm.h" | 25 | #include "lj_vm.h" |
| 26 | #include "lj_strscan.h" | 26 | #include "lj_strscan.h" |
| 27 | #include "lj_strfmt.h" | ||
| 27 | 28 | ||
| 28 | /* -- Common helper functions --------------------------------------------- */ | 29 | /* -- Common helper functions --------------------------------------------- */ |
| 29 | 30 | ||
| 30 | #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) | 31 | #define lj_checkapi_slot(idx) \ |
| 31 | #define api_checkvalidindex(L, i) api_check(L, (i) != niltv(L)) | 32 | lj_checkapi((idx) <= (L->top - L->base), "stack slot %d out of range", (idx)) |
| 32 | 33 | ||
| 33 | static TValue *index2adr(lua_State *L, int idx) | 34 | static TValue *index2adr(lua_State *L, int idx) |
| 34 | { | 35 | { |
| @@ -36,7 +37,8 @@ static TValue *index2adr(lua_State *L, int idx) | |||
| 36 | TValue *o = L->base + (idx - 1); | 37 | TValue *o = L->base + (idx - 1); |
| 37 | return o < L->top ? o : niltv(L); | 38 | return o < L->top ? o : niltv(L); |
| 38 | } else if (idx > LUA_REGISTRYINDEX) { | 39 | } else if (idx > LUA_REGISTRYINDEX) { |
| 39 | api_check(L, idx != 0 && -idx <= L->top - L->base); | 40 | lj_checkapi(idx != 0 && -idx <= L->top - L->base, |
| 41 | "bad stack slot %d", idx); | ||
| 40 | return L->top + idx; | 42 | return L->top + idx; |
| 41 | } else if (idx == LUA_GLOBALSINDEX) { | 43 | } else if (idx == LUA_GLOBALSINDEX) { |
| 42 | TValue *o = &G(L)->tmptv; | 44 | TValue *o = &G(L)->tmptv; |
| @@ -46,7 +48,8 @@ static TValue *index2adr(lua_State *L, int idx) | |||
| 46 | return registry(L); | 48 | return registry(L); |
| 47 | } else { | 49 | } else { |
| 48 | GCfunc *fn = curr_func(L); | 50 | GCfunc *fn = curr_func(L); |
| 49 | api_check(L, fn->c.gct == ~LJ_TFUNC && !isluafunc(fn)); | 51 | lj_checkapi(fn->c.gct == ~LJ_TFUNC && !isluafunc(fn), |
| 52 | "calling frame is not a C function"); | ||
| 50 | if (idx == LUA_ENVIRONINDEX) { | 53 | if (idx == LUA_ENVIRONINDEX) { |
| 51 | TValue *o = &G(L)->tmptv; | 54 | TValue *o = &G(L)->tmptv; |
| 52 | settabV(L, o, tabref(fn->c.env)); | 55 | settabV(L, o, tabref(fn->c.env)); |
| @@ -58,13 +61,27 @@ static TValue *index2adr(lua_State *L, int idx) | |||
| 58 | } | 61 | } |
| 59 | } | 62 | } |
| 60 | 63 | ||
| 61 | static TValue *stkindex2adr(lua_State *L, int idx) | 64 | static LJ_AINLINE TValue *index2adr_check(lua_State *L, int idx) |
| 65 | { | ||
| 66 | TValue *o = index2adr(L, idx); | ||
| 67 | lj_checkapi(o != niltv(L), "invalid stack slot %d", idx); | ||
| 68 | return o; | ||
| 69 | } | ||
| 70 | |||
| 71 | static TValue *index2adr_stack(lua_State *L, int idx) | ||
| 62 | { | 72 | { |
| 63 | if (idx > 0) { | 73 | if (idx > 0) { |
| 64 | TValue *o = L->base + (idx - 1); | 74 | TValue *o = L->base + (idx - 1); |
| 75 | if (o < L->top) { | ||
| 76 | return o; | ||
| 77 | } else { | ||
| 78 | lj_checkapi(0, "invalid stack slot %d", idx); | ||
| 79 | return niltv(L); | ||
| 80 | } | ||
| 65 | return o < L->top ? o : niltv(L); | 81 | return o < L->top ? o : niltv(L); |
| 66 | } else { | 82 | } else { |
| 67 | api_check(L, idx != 0 && -idx <= L->top - L->base); | 83 | lj_checkapi(idx != 0 && -idx <= L->top - L->base, |
| 84 | "invalid stack slot %d", idx); | ||
| 68 | return L->top + idx; | 85 | return L->top + idx; |
| 69 | } | 86 | } |
| 70 | } | 87 | } |
| @@ -87,7 +104,12 @@ LUA_API int lua_checkstack(lua_State *L, int size) | |||
| 87 | if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) { | 104 | if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) { |
| 88 | return 0; /* Stack overflow. */ | 105 | return 0; /* Stack overflow. */ |
| 89 | } else if (size > 0) { | 106 | } else if (size > 0) { |
| 90 | lj_state_checkstack(L, (MSize)size); | 107 | int avail = (int)(mref(L->maxstack, TValue) - L->top); |
| 108 | if (size > avail && | ||
| 109 | lj_state_cpgrowstack(L, (MSize)(size - avail)) != LUA_OK) { | ||
| 110 | L->top--; | ||
| 111 | return 0; /* Out of memory. */ | ||
| 112 | } | ||
| 91 | } | 113 | } |
| 92 | return 1; | 114 | return 1; |
| 93 | } | 115 | } |
| @@ -98,17 +120,24 @@ LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg) | |||
| 98 | lj_err_callerv(L, LJ_ERR_STKOVM, msg); | 120 | lj_err_callerv(L, LJ_ERR_STKOVM, msg); |
| 99 | } | 121 | } |
| 100 | 122 | ||
| 101 | LUA_API void lua_xmove(lua_State *from, lua_State *to, int n) | 123 | LUA_API void lua_xmove(lua_State *L, lua_State *to, int n) |
| 102 | { | 124 | { |
| 103 | TValue *f, *t; | 125 | TValue *f, *t; |
| 104 | if (from == to) return; | 126 | if (L == to) return; |
| 105 | api_checknelems(from, n); | 127 | lj_checkapi_slot(n); |
| 106 | api_check(from, G(from) == G(to)); | 128 | lj_checkapi(G(L) == G(to), "move across global states"); |
| 107 | lj_state_checkstack(to, (MSize)n); | 129 | lj_state_checkstack(to, (MSize)n); |
| 108 | f = from->top; | 130 | f = L->top; |
| 109 | t = to->top = to->top + n; | 131 | t = to->top = to->top + n; |
| 110 | while (--n >= 0) copyTV(to, --t, --f); | 132 | while (--n >= 0) copyTV(to, --t, --f); |
| 111 | from->top = f; | 133 | L->top = f; |
| 134 | } | ||
| 135 | |||
| 136 | LUA_API const lua_Number *lua_version(lua_State *L) | ||
| 137 | { | ||
| 138 | static const lua_Number version = LUA_VERSION_NUM; | ||
| 139 | UNUSED(L); | ||
| 140 | return &version; | ||
| 112 | } | 141 | } |
| 113 | 142 | ||
| 114 | /* -- Stack manipulation -------------------------------------------------- */ | 143 | /* -- Stack manipulation -------------------------------------------------- */ |
| @@ -121,7 +150,7 @@ LUA_API int lua_gettop(lua_State *L) | |||
| 121 | LUA_API void lua_settop(lua_State *L, int idx) | 150 | LUA_API void lua_settop(lua_State *L, int idx) |
| 122 | { | 151 | { |
| 123 | if (idx >= 0) { | 152 | if (idx >= 0) { |
| 124 | api_check(L, idx <= tvref(L->maxstack) - L->base); | 153 | lj_checkapi(idx <= tvref(L->maxstack) - L->base, "bad stack slot %d", idx); |
| 125 | if (L->base + idx > L->top) { | 154 | if (L->base + idx > L->top) { |
| 126 | if (L->base + idx >= tvref(L->maxstack)) | 155 | if (L->base + idx >= tvref(L->maxstack)) |
| 127 | lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base)); | 156 | lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base)); |
| @@ -130,51 +159,58 @@ LUA_API void lua_settop(lua_State *L, int idx) | |||
| 130 | L->top = L->base + idx; | 159 | L->top = L->base + idx; |
| 131 | } | 160 | } |
| 132 | } else { | 161 | } else { |
| 133 | api_check(L, -(idx+1) <= (L->top - L->base)); | 162 | lj_checkapi(-(idx+1) <= (L->top - L->base), "bad stack slot %d", idx); |
| 134 | L->top += idx+1; /* Shrinks top (idx < 0). */ | 163 | L->top += idx+1; /* Shrinks top (idx < 0). */ |
| 135 | } | 164 | } |
| 136 | } | 165 | } |
| 137 | 166 | ||
| 138 | LUA_API void lua_remove(lua_State *L, int idx) | 167 | LUA_API void lua_remove(lua_State *L, int idx) |
| 139 | { | 168 | { |
| 140 | TValue *p = stkindex2adr(L, idx); | 169 | TValue *p = index2adr_stack(L, idx); |
| 141 | api_checkvalidindex(L, p); | ||
| 142 | while (++p < L->top) copyTV(L, p-1, p); | 170 | while (++p < L->top) copyTV(L, p-1, p); |
| 143 | L->top--; | 171 | L->top--; |
| 144 | } | 172 | } |
| 145 | 173 | ||
| 146 | LUA_API void lua_insert(lua_State *L, int idx) | 174 | LUA_API void lua_insert(lua_State *L, int idx) |
| 147 | { | 175 | { |
| 148 | TValue *q, *p = stkindex2adr(L, idx); | 176 | TValue *q, *p = index2adr_stack(L, idx); |
| 149 | api_checkvalidindex(L, p); | ||
| 150 | for (q = L->top; q > p; q--) copyTV(L, q, q-1); | 177 | for (q = L->top; q > p; q--) copyTV(L, q, q-1); |
| 151 | copyTV(L, p, L->top); | 178 | copyTV(L, p, L->top); |
| 152 | } | 179 | } |
| 153 | 180 | ||
| 154 | LUA_API void lua_replace(lua_State *L, int idx) | 181 | static void copy_slot(lua_State *L, TValue *f, int idx) |
| 155 | { | 182 | { |
| 156 | api_checknelems(L, 1); | ||
| 157 | if (idx == LUA_GLOBALSINDEX) { | 183 | if (idx == LUA_GLOBALSINDEX) { |
| 158 | api_check(L, tvistab(L->top-1)); | 184 | lj_checkapi(tvistab(f), "stack slot %d is not a table", idx); |
| 159 | /* NOBARRIER: A thread (i.e. L) is never black. */ | 185 | /* NOBARRIER: A thread (i.e. L) is never black. */ |
| 160 | setgcref(L->env, obj2gco(tabV(L->top-1))); | 186 | setgcref(L->env, obj2gco(tabV(f))); |
| 161 | } else if (idx == LUA_ENVIRONINDEX) { | 187 | } else if (idx == LUA_ENVIRONINDEX) { |
| 162 | GCfunc *fn = curr_func(L); | 188 | GCfunc *fn = curr_func(L); |
| 163 | if (fn->c.gct != ~LJ_TFUNC) | 189 | if (fn->c.gct != ~LJ_TFUNC) |
| 164 | lj_err_msg(L, LJ_ERR_NOENV); | 190 | lj_err_msg(L, LJ_ERR_NOENV); |
| 165 | api_check(L, tvistab(L->top-1)); | 191 | lj_checkapi(tvistab(f), "stack slot %d is not a table", idx); |
| 166 | setgcref(fn->c.env, obj2gco(tabV(L->top-1))); | 192 | setgcref(fn->c.env, obj2gco(tabV(f))); |
| 167 | lj_gc_barrier(L, fn, L->top-1); | 193 | lj_gc_barrier(L, fn, f); |
| 168 | } else { | 194 | } else { |
| 169 | TValue *o = index2adr(L, idx); | 195 | TValue *o = index2adr_check(L, idx); |
| 170 | api_checkvalidindex(L, o); | 196 | copyTV(L, o, f); |
| 171 | copyTV(L, o, L->top-1); | ||
| 172 | if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */ | 197 | if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */ |
| 173 | lj_gc_barrier(L, curr_func(L), L->top-1); | 198 | lj_gc_barrier(L, curr_func(L), f); |
| 174 | } | 199 | } |
| 200 | } | ||
| 201 | |||
| 202 | LUA_API void lua_replace(lua_State *L, int idx) | ||
| 203 | { | ||
| 204 | lj_checkapi_slot(1); | ||
| 205 | copy_slot(L, L->top - 1, idx); | ||
| 175 | L->top--; | 206 | L->top--; |
| 176 | } | 207 | } |
| 177 | 208 | ||
| 209 | LUA_API void lua_copy(lua_State *L, int fromidx, int toidx) | ||
| 210 | { | ||
| 211 | copy_slot(L, index2adr(L, fromidx), toidx); | ||
| 212 | } | ||
| 213 | |||
| 178 | LUA_API void lua_pushvalue(lua_State *L, int idx) | 214 | LUA_API void lua_pushvalue(lua_State *L, int idx) |
| 179 | { | 215 | { |
| 180 | copyTV(L, L->top, index2adr(L, idx)); | 216 | copyTV(L, L->top, index2adr(L, idx)); |
| @@ -188,7 +224,7 @@ LUA_API int lua_type(lua_State *L, int idx) | |||
| 188 | cTValue *o = index2adr(L, idx); | 224 | cTValue *o = index2adr(L, idx); |
| 189 | if (tvisnumber(o)) { | 225 | if (tvisnumber(o)) { |
| 190 | return LUA_TNUMBER; | 226 | return LUA_TNUMBER; |
| 191 | #if LJ_64 | 227 | #if LJ_64 && !LJ_GC64 |
| 192 | } else if (tvislightud(o)) { | 228 | } else if (tvislightud(o)) { |
| 193 | return LUA_TLIGHTUSERDATA; | 229 | return LUA_TLIGHTUSERDATA; |
| 194 | #endif | 230 | #endif |
| @@ -201,7 +237,7 @@ LUA_API int lua_type(lua_State *L, int idx) | |||
| 201 | #else | 237 | #else |
| 202 | int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u); | 238 | int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u); |
| 203 | #endif | 239 | #endif |
| 204 | lua_assert(tt != LUA_TNIL || tvisnil(o)); | 240 | lj_assertL(tt != LUA_TNIL || tvisnil(o), "bad tag conversion"); |
| 205 | return tt; | 241 | return tt; |
| 206 | } | 242 | } |
| 207 | } | 243 | } |
| @@ -268,7 +304,7 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2) | |||
| 268 | return 0; | 304 | return 0; |
| 269 | } else if (tvispri(o1)) { | 305 | } else if (tvispri(o1)) { |
| 270 | return o1 != niltv(L) && o2 != niltv(L); | 306 | return o1 != niltv(L) && o2 != niltv(L); |
| 271 | #if LJ_64 | 307 | #if LJ_64 && !LJ_GC64 |
| 272 | } else if (tvislightud(o1)) { | 308 | } else if (tvislightud(o1)) { |
| 273 | return o1->u64 == o2->u64; | 309 | return o1->u64 == o2->u64; |
| 274 | #endif | 310 | #endif |
| @@ -283,8 +319,8 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2) | |||
| 283 | } else { | 319 | } else { |
| 284 | L->top = base+2; | 320 | L->top = base+2; |
| 285 | lj_vm_call(L, base, 1+1); | 321 | lj_vm_call(L, base, 1+1); |
| 286 | L->top -= 2; | 322 | L->top -= 2+LJ_FR2; |
| 287 | return tvistruecond(L->top+1); | 323 | return tvistruecond(L->top+1+LJ_FR2); |
| 288 | } | 324 | } |
| 289 | } | 325 | } |
| 290 | } | 326 | } |
| @@ -306,8 +342,8 @@ LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2) | |||
| 306 | } else { | 342 | } else { |
| 307 | L->top = base+2; | 343 | L->top = base+2; |
| 308 | lj_vm_call(L, base, 1+1); | 344 | lj_vm_call(L, base, 1+1); |
| 309 | L->top -= 2; | 345 | L->top -= 2+LJ_FR2; |
| 310 | return tvistruecond(L->top+1); | 346 | return tvistruecond(L->top+1+LJ_FR2); |
| 311 | } | 347 | } |
| 312 | } | 348 | } |
| 313 | } | 349 | } |
| @@ -324,6 +360,22 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx) | |||
| 324 | return 0; | 360 | return 0; |
| 325 | } | 361 | } |
| 326 | 362 | ||
| 363 | LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *ok) | ||
| 364 | { | ||
| 365 | cTValue *o = index2adr(L, idx); | ||
| 366 | TValue tmp; | ||
| 367 | if (LJ_LIKELY(tvisnumber(o))) { | ||
| 368 | if (ok) *ok = 1; | ||
| 369 | return numberVnum(o); | ||
| 370 | } else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp)) { | ||
| 371 | if (ok) *ok = 1; | ||
| 372 | return numV(&tmp); | ||
| 373 | } else { | ||
| 374 | if (ok) *ok = 0; | ||
| 375 | return 0; | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 327 | LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx) | 379 | LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx) |
| 328 | { | 380 | { |
| 329 | cTValue *o = index2adr(L, idx); | 381 | cTValue *o = index2adr(L, idx); |
| @@ -361,14 +413,35 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx) | |||
| 361 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) | 413 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) |
| 362 | return 0; | 414 | return 0; |
| 363 | if (tvisint(&tmp)) | 415 | if (tvisint(&tmp)) |
| 364 | return (lua_Integer)intV(&tmp); | 416 | return intV(&tmp); |
| 365 | n = numV(&tmp); | 417 | n = numV(&tmp); |
| 366 | } | 418 | } |
| 367 | #if LJ_64 | 419 | return lj_num2int_type(n, lua_Integer); |
| 368 | return (lua_Integer)n; | 420 | } |
| 369 | #else | 421 | |
| 370 | return lj_num2int(n); | 422 | LUA_API lua_Integer lua_tointegerx(lua_State *L, int idx, int *ok) |
| 371 | #endif | 423 | { |
| 424 | cTValue *o = index2adr(L, idx); | ||
| 425 | TValue tmp; | ||
| 426 | lua_Number n; | ||
| 427 | if (LJ_LIKELY(tvisint(o))) { | ||
| 428 | if (ok) *ok = 1; | ||
| 429 | return intV(o); | ||
| 430 | } else if (LJ_LIKELY(tvisnum(o))) { | ||
| 431 | n = numV(o); | ||
| 432 | } else { | ||
| 433 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) { | ||
| 434 | if (ok) *ok = 0; | ||
| 435 | return 0; | ||
| 436 | } | ||
| 437 | if (tvisint(&tmp)) { | ||
| 438 | if (ok) *ok = 1; | ||
| 439 | return intV(&tmp); | ||
| 440 | } | ||
| 441 | n = numV(&tmp); | ||
| 442 | } | ||
| 443 | if (ok) *ok = 1; | ||
| 444 | return lj_num2int_type(n, lua_Integer); | ||
| 372 | } | 445 | } |
| 373 | 446 | ||
| 374 | LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx) | 447 | LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx) |
| @@ -387,11 +460,7 @@ LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx) | |||
| 387 | return (lua_Integer)intV(&tmp); | 460 | return (lua_Integer)intV(&tmp); |
| 388 | n = numV(&tmp); | 461 | n = numV(&tmp); |
| 389 | } | 462 | } |
| 390 | #if LJ_64 | 463 | return lj_num2int_type(n, lua_Integer); |
| 391 | return (lua_Integer)n; | ||
| 392 | #else | ||
| 393 | return lj_num2int(n); | ||
| 394 | #endif | ||
| 395 | } | 464 | } |
| 396 | 465 | ||
| 397 | LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def) | 466 | LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def) |
| @@ -412,11 +481,7 @@ LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def) | |||
| 412 | return (lua_Integer)intV(&tmp); | 481 | return (lua_Integer)intV(&tmp); |
| 413 | n = numV(&tmp); | 482 | n = numV(&tmp); |
| 414 | } | 483 | } |
| 415 | #if LJ_64 | 484 | return lj_num2int_type(n, lua_Integer); |
| 416 | return (lua_Integer)n; | ||
| 417 | #else | ||
| 418 | return lj_num2int(n); | ||
| 419 | #endif | ||
| 420 | } | 485 | } |
| 421 | 486 | ||
| 422 | LUA_API int lua_toboolean(lua_State *L, int idx) | 487 | LUA_API int lua_toboolean(lua_State *L, int idx) |
| @@ -434,7 +499,7 @@ LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len) | |||
| 434 | } else if (tvisnumber(o)) { | 499 | } else if (tvisnumber(o)) { |
| 435 | lj_gc_check(L); | 500 | lj_gc_check(L); |
| 436 | o = index2adr(L, idx); /* GC may move the stack. */ | 501 | o = index2adr(L, idx); /* GC may move the stack. */ |
| 437 | s = lj_str_fromnumber(L, o); | 502 | s = lj_strfmt_number(L, o); |
| 438 | setstrV(L, o, s); | 503 | setstrV(L, o, s); |
| 439 | } else { | 504 | } else { |
| 440 | if (len != NULL) *len = 0; | 505 | if (len != NULL) *len = 0; |
| @@ -453,7 +518,7 @@ LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len) | |||
| 453 | } else if (tvisnumber(o)) { | 518 | } else if (tvisnumber(o)) { |
| 454 | lj_gc_check(L); | 519 | lj_gc_check(L); |
| 455 | o = index2adr(L, idx); /* GC may move the stack. */ | 520 | o = index2adr(L, idx); /* GC may move the stack. */ |
| 456 | s = lj_str_fromnumber(L, o); | 521 | s = lj_strfmt_number(L, o); |
| 457 | setstrV(L, o, s); | 522 | setstrV(L, o, s); |
| 458 | } else { | 523 | } else { |
| 459 | lj_err_argt(L, idx, LUA_TSTRING); | 524 | lj_err_argt(L, idx, LUA_TSTRING); |
| @@ -475,7 +540,7 @@ LUALIB_API const char *luaL_optlstring(lua_State *L, int idx, | |||
| 475 | } else if (tvisnumber(o)) { | 540 | } else if (tvisnumber(o)) { |
| 476 | lj_gc_check(L); | 541 | lj_gc_check(L); |
| 477 | o = index2adr(L, idx); /* GC may move the stack. */ | 542 | o = index2adr(L, idx); /* GC may move the stack. */ |
| 478 | s = lj_str_fromnumber(L, o); | 543 | s = lj_strfmt_number(L, o); |
| 479 | setstrV(L, o, s); | 544 | setstrV(L, o, s); |
| 480 | } else { | 545 | } else { |
| 481 | lj_err_argt(L, idx, LUA_TSTRING); | 546 | lj_err_argt(L, idx, LUA_TSTRING); |
| @@ -507,7 +572,7 @@ LUA_API size_t lua_objlen(lua_State *L, int idx) | |||
| 507 | } else if (tvisudata(o)) { | 572 | } else if (tvisudata(o)) { |
| 508 | return udataV(o)->len; | 573 | return udataV(o)->len; |
| 509 | } else if (tvisnumber(o)) { | 574 | } else if (tvisnumber(o)) { |
| 510 | GCstr *s = lj_str_fromnumber(L, o); | 575 | GCstr *s = lj_strfmt_number(L, o); |
| 511 | setstrV(L, o, s); | 576 | setstrV(L, o, s); |
| 512 | return s->len; | 577 | return s->len; |
| 513 | } else { | 578 | } else { |
| @@ -532,7 +597,7 @@ LUA_API void *lua_touserdata(lua_State *L, int idx) | |||
| 532 | if (tvisudata(o)) | 597 | if (tvisudata(o)) |
| 533 | return uddata(udataV(o)); | 598 | return uddata(udataV(o)); |
| 534 | else if (tvislightud(o)) | 599 | else if (tvislightud(o)) |
| 535 | return lightudV(o); | 600 | return lightudV(G(L), o); |
| 536 | else | 601 | else |
| 537 | return NULL; | 602 | return NULL; |
| 538 | } | 603 | } |
| @@ -545,17 +610,7 @@ LUA_API lua_State *lua_tothread(lua_State *L, int idx) | |||
| 545 | 610 | ||
| 546 | LUA_API const void *lua_topointer(lua_State *L, int idx) | 611 | LUA_API const void *lua_topointer(lua_State *L, int idx) |
| 547 | { | 612 | { |
| 548 | cTValue *o = index2adr(L, idx); | 613 | return lj_obj_ptr(G(L), index2adr(L, idx)); |
| 549 | if (tvisudata(o)) | ||
| 550 | return uddata(udataV(o)); | ||
| 551 | else if (tvislightud(o)) | ||
| 552 | return lightudV(o); | ||
| 553 | else if (tviscdata(o)) | ||
| 554 | return cdataptr(cdataV(o)); | ||
| 555 | else if (tvisgcv(o)) | ||
| 556 | return gcV(o); | ||
| 557 | else | ||
| 558 | return NULL; | ||
| 559 | } | 614 | } |
| 560 | 615 | ||
| 561 | /* -- Stack setters (object creation) ------------------------------------- */ | 616 | /* -- Stack setters (object creation) ------------------------------------- */ |
| @@ -606,7 +661,7 @@ LUA_API const char *lua_pushvfstring(lua_State *L, const char *fmt, | |||
| 606 | va_list argp) | 661 | va_list argp) |
| 607 | { | 662 | { |
| 608 | lj_gc_check(L); | 663 | lj_gc_check(L); |
| 609 | return lj_str_pushvf(L, fmt, argp); | 664 | return lj_strfmt_pushvf(L, fmt, argp); |
| 610 | } | 665 | } |
| 611 | 666 | ||
| 612 | LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...) | 667 | LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...) |
| @@ -615,7 +670,7 @@ LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...) | |||
| 615 | va_list argp; | 670 | va_list argp; |
| 616 | lj_gc_check(L); | 671 | lj_gc_check(L); |
| 617 | va_start(argp, fmt); | 672 | va_start(argp, fmt); |
| 618 | ret = lj_str_pushvf(L, fmt, argp); | 673 | ret = lj_strfmt_pushvf(L, fmt, argp); |
| 619 | va_end(argp); | 674 | va_end(argp); |
| 620 | return ret; | 675 | return ret; |
| 621 | } | 676 | } |
| @@ -624,14 +679,14 @@ LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n) | |||
| 624 | { | 679 | { |
| 625 | GCfunc *fn; | 680 | GCfunc *fn; |
| 626 | lj_gc_check(L); | 681 | lj_gc_check(L); |
| 627 | api_checknelems(L, n); | 682 | lj_checkapi_slot(n); |
| 628 | fn = lj_func_newC(L, (MSize)n, getcurrenv(L)); | 683 | fn = lj_func_newC(L, (MSize)n, getcurrenv(L)); |
| 629 | fn->c.f = f; | 684 | fn->c.f = f; |
| 630 | L->top -= n; | 685 | L->top -= n; |
| 631 | while (n--) | 686 | while (n--) |
| 632 | copyTV(L, &fn->c.upvalue[n], L->top+n); | 687 | copyTV(L, &fn->c.upvalue[n], L->top+n); |
| 633 | setfuncV(L, L->top, fn); | 688 | setfuncV(L, L->top, fn); |
| 634 | lua_assert(iswhite(obj2gco(fn))); | 689 | lj_assertL(iswhite(obj2gco(fn)), "new GC object is not white"); |
| 635 | incr_top(L); | 690 | incr_top(L); |
| 636 | } | 691 | } |
| 637 | 692 | ||
| @@ -643,16 +698,17 @@ LUA_API void lua_pushboolean(lua_State *L, int b) | |||
| 643 | 698 | ||
| 644 | LUA_API void lua_pushlightuserdata(lua_State *L, void *p) | 699 | LUA_API void lua_pushlightuserdata(lua_State *L, void *p) |
| 645 | { | 700 | { |
| 646 | setlightudV(L->top, checklightudptr(L, p)); | 701 | #if LJ_64 |
| 702 | p = lj_lightud_intern(L, p); | ||
| 703 | #endif | ||
| 704 | setrawlightudV(L->top, p); | ||
| 647 | incr_top(L); | 705 | incr_top(L); |
| 648 | } | 706 | } |
| 649 | 707 | ||
| 650 | LUA_API void lua_createtable(lua_State *L, int narray, int nrec) | 708 | LUA_API void lua_createtable(lua_State *L, int narray, int nrec) |
| 651 | { | 709 | { |
| 652 | GCtab *t; | ||
| 653 | lj_gc_check(L); | 710 | lj_gc_check(L); |
| 654 | t = lj_tab_new(L, (uint32_t)(narray > 0 ? narray+1 : 0), hsize2hbits(nrec)); | 711 | settabV(L, L->top, lj_tab_new_ah(L, narray, nrec)); |
| 655 | settabV(L, L->top, t); | ||
| 656 | incr_top(L); | 712 | incr_top(L); |
| 657 | } | 713 | } |
| 658 | 714 | ||
| @@ -703,7 +759,7 @@ LUA_API void *lua_newuserdata(lua_State *L, size_t size) | |||
| 703 | 759 | ||
| 704 | LUA_API void lua_concat(lua_State *L, int n) | 760 | LUA_API void lua_concat(lua_State *L, int n) |
| 705 | { | 761 | { |
| 706 | api_checknelems(L, n); | 762 | lj_checkapi_slot(n); |
| 707 | if (n >= 2) { | 763 | if (n >= 2) { |
| 708 | n--; | 764 | n--; |
| 709 | do { | 765 | do { |
| @@ -712,11 +768,11 @@ LUA_API void lua_concat(lua_State *L, int n) | |||
| 712 | L->top -= n; | 768 | L->top -= n; |
| 713 | break; | 769 | break; |
| 714 | } | 770 | } |
| 715 | n -= (int)(L->top - top); | 771 | n -= (int)(L->top - (top - 2*LJ_FR2)); |
| 716 | L->top = top+2; | 772 | L->top = top+2; |
| 717 | lj_vm_call(L, top, 1+1); | 773 | lj_vm_call(L, top, 1+1); |
| 718 | L->top--; | 774 | L->top -= 1+LJ_FR2; |
| 719 | copyTV(L, L->top-1, L->top); | 775 | copyTV(L, L->top-1, L->top+LJ_FR2); |
| 720 | } while (--n > 0); | 776 | } while (--n > 0); |
| 721 | } else if (n == 0) { /* Push empty string. */ | 777 | } else if (n == 0) { /* Push empty string. */ |
| 722 | setstrV(L, L->top, &G(L)->strempty); | 778 | setstrV(L, L->top, &G(L)->strempty); |
| @@ -729,30 +785,28 @@ LUA_API void lua_concat(lua_State *L, int n) | |||
| 729 | 785 | ||
| 730 | LUA_API void lua_gettable(lua_State *L, int idx) | 786 | LUA_API void lua_gettable(lua_State *L, int idx) |
| 731 | { | 787 | { |
| 732 | cTValue *v, *t = index2adr(L, idx); | 788 | cTValue *t = index2adr_check(L, idx); |
| 733 | api_checkvalidindex(L, t); | 789 | cTValue *v = lj_meta_tget(L, t, L->top-1); |
| 734 | v = lj_meta_tget(L, t, L->top-1); | ||
| 735 | if (v == NULL) { | 790 | if (v == NULL) { |
| 736 | L->top += 2; | 791 | L->top += 2; |
| 737 | lj_vm_call(L, L->top-2, 1+1); | 792 | lj_vm_call(L, L->top-2, 1+1); |
| 738 | L->top -= 2; | 793 | L->top -= 2+LJ_FR2; |
| 739 | v = L->top+1; | 794 | v = L->top+1+LJ_FR2; |
| 740 | } | 795 | } |
| 741 | copyTV(L, L->top-1, v); | 796 | copyTV(L, L->top-1, v); |
| 742 | } | 797 | } |
| 743 | 798 | ||
| 744 | LUA_API void lua_getfield(lua_State *L, int idx, const char *k) | 799 | LUA_API void lua_getfield(lua_State *L, int idx, const char *k) |
| 745 | { | 800 | { |
| 746 | cTValue *v, *t = index2adr(L, idx); | 801 | cTValue *v, *t = index2adr_check(L, idx); |
| 747 | TValue key; | 802 | TValue key; |
| 748 | api_checkvalidindex(L, t); | ||
| 749 | setstrV(L, &key, lj_str_newz(L, k)); | 803 | setstrV(L, &key, lj_str_newz(L, k)); |
| 750 | v = lj_meta_tget(L, t, &key); | 804 | v = lj_meta_tget(L, t, &key); |
| 751 | if (v == NULL) { | 805 | if (v == NULL) { |
| 752 | L->top += 2; | 806 | L->top += 2; |
| 753 | lj_vm_call(L, L->top-2, 1+1); | 807 | lj_vm_call(L, L->top-2, 1+1); |
| 754 | L->top -= 2; | 808 | L->top -= 2+LJ_FR2; |
| 755 | v = L->top+1; | 809 | v = L->top+1+LJ_FR2; |
| 756 | } | 810 | } |
| 757 | copyTV(L, L->top, v); | 811 | copyTV(L, L->top, v); |
| 758 | incr_top(L); | 812 | incr_top(L); |
| @@ -761,14 +815,14 @@ LUA_API void lua_getfield(lua_State *L, int idx, const char *k) | |||
| 761 | LUA_API void lua_rawget(lua_State *L, int idx) | 815 | LUA_API void lua_rawget(lua_State *L, int idx) |
| 762 | { | 816 | { |
| 763 | cTValue *t = index2adr(L, idx); | 817 | cTValue *t = index2adr(L, idx); |
| 764 | api_check(L, tvistab(t)); | 818 | lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); |
| 765 | copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1)); | 819 | copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1)); |
| 766 | } | 820 | } |
| 767 | 821 | ||
| 768 | LUA_API void lua_rawgeti(lua_State *L, int idx, int n) | 822 | LUA_API void lua_rawgeti(lua_State *L, int idx, int n) |
| 769 | { | 823 | { |
| 770 | cTValue *v, *t = index2adr(L, idx); | 824 | cTValue *v, *t = index2adr(L, idx); |
| 771 | api_check(L, tvistab(t)); | 825 | lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); |
| 772 | v = lj_tab_getint(tabV(t), n); | 826 | v = lj_tab_getint(tabV(t), n); |
| 773 | if (v) { | 827 | if (v) { |
| 774 | copyTV(L, L->top, v); | 828 | copyTV(L, L->top, v); |
| @@ -810,8 +864,7 @@ LUALIB_API int luaL_getmetafield(lua_State *L, int idx, const char *field) | |||
| 810 | 864 | ||
| 811 | LUA_API void lua_getfenv(lua_State *L, int idx) | 865 | LUA_API void lua_getfenv(lua_State *L, int idx) |
| 812 | { | 866 | { |
| 813 | cTValue *o = index2adr(L, idx); | 867 | cTValue *o = index2adr_check(L, idx); |
| 814 | api_checkvalidindex(L, o); | ||
| 815 | if (tvisfunc(o)) { | 868 | if (tvisfunc(o)) { |
| 816 | settabV(L, L->top, tabref(funcV(o)->c.env)); | 869 | settabV(L, L->top, tabref(funcV(o)->c.env)); |
| 817 | } else if (tvisudata(o)) { | 870 | } else if (tvisudata(o)) { |
| @@ -828,12 +881,14 @@ LUA_API int lua_next(lua_State *L, int idx) | |||
| 828 | { | 881 | { |
| 829 | cTValue *t = index2adr(L, idx); | 882 | cTValue *t = index2adr(L, idx); |
| 830 | int more; | 883 | int more; |
| 831 | api_check(L, tvistab(t)); | 884 | lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); |
| 832 | more = lj_tab_next(L, tabV(t), L->top-1); | 885 | more = lj_tab_next(tabV(t), L->top-1, L->top-1); |
| 833 | if (more) { | 886 | if (more > 0) { |
| 834 | incr_top(L); /* Return new key and value slot. */ | 887 | incr_top(L); /* Return new key and value slot. */ |
| 835 | } else { /* End of traversal. */ | 888 | } else if (!more) { /* End of traversal. */ |
| 836 | L->top--; /* Remove key slot. */ | 889 | L->top--; /* Remove key slot. */ |
| 890 | } else { | ||
| 891 | lj_err_msg(L, LJ_ERR_NEXTIDX); | ||
| 837 | } | 892 | } |
| 838 | return more; | 893 | return more; |
| 839 | } | 894 | } |
| @@ -854,7 +909,7 @@ LUA_API void *lua_upvalueid(lua_State *L, int idx, int n) | |||
| 854 | { | 909 | { |
| 855 | GCfunc *fn = funcV(index2adr(L, idx)); | 910 | GCfunc *fn = funcV(index2adr(L, idx)); |
| 856 | n--; | 911 | n--; |
| 857 | api_check(L, (uint32_t)n < fn->l.nupvalues); | 912 | lj_checkapi((uint32_t)n < fn->l.nupvalues, "bad upvalue %d", n); |
| 858 | return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) : | 913 | return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) : |
| 859 | (void *)&fn->c.upvalue[n]; | 914 | (void *)&fn->c.upvalue[n]; |
| 860 | } | 915 | } |
| @@ -864,13 +919,15 @@ LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2) | |||
| 864 | GCfunc *fn1 = funcV(index2adr(L, idx1)); | 919 | GCfunc *fn1 = funcV(index2adr(L, idx1)); |
| 865 | GCfunc *fn2 = funcV(index2adr(L, idx2)); | 920 | GCfunc *fn2 = funcV(index2adr(L, idx2)); |
| 866 | n1--; n2--; | 921 | n1--; n2--; |
| 867 | api_check(L, isluafunc(fn1) && (uint32_t)n1 < fn1->l.nupvalues); | 922 | lj_checkapi(isluafunc(fn1), "stack slot %d is not a Lua function", idx1); |
| 868 | api_check(L, isluafunc(fn2) && (uint32_t)n2 < fn2->l.nupvalues); | 923 | lj_checkapi(isluafunc(fn2), "stack slot %d is not a Lua function", idx2); |
| 924 | lj_checkapi((uint32_t)n1 < fn1->l.nupvalues, "bad upvalue %d", n1+1); | ||
| 925 | lj_checkapi((uint32_t)n2 < fn2->l.nupvalues, "bad upvalue %d", n2+1); | ||
| 869 | setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]); | 926 | setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]); |
| 870 | lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1])); | 927 | lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1])); |
| 871 | } | 928 | } |
| 872 | 929 | ||
| 873 | LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname) | 930 | LUALIB_API void *luaL_testudata(lua_State *L, int idx, const char *tname) |
| 874 | { | 931 | { |
| 875 | cTValue *o = index2adr(L, idx); | 932 | cTValue *o = index2adr(L, idx); |
| 876 | if (tvisudata(o)) { | 933 | if (tvisudata(o)) { |
| @@ -879,8 +936,14 @@ LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname) | |||
| 879 | if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable)) | 936 | if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable)) |
| 880 | return uddata(ud); | 937 | return uddata(ud); |
| 881 | } | 938 | } |
| 882 | lj_err_argtype(L, idx, tname); | 939 | return NULL; /* value is not a userdata with a metatable */ |
| 883 | return NULL; /* unreachable */ | 940 | } |
| 941 | |||
| 942 | LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname) | ||
| 943 | { | ||
| 944 | void *p = luaL_testudata(L, idx, tname); | ||
| 945 | if (!p) lj_err_argtype(L, idx, tname); | ||
| 946 | return p; | ||
| 884 | } | 947 | } |
| 885 | 948 | ||
| 886 | /* -- Object setters ------------------------------------------------------ */ | 949 | /* -- Object setters ------------------------------------------------------ */ |
| @@ -888,19 +951,19 @@ LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname) | |||
| 888 | LUA_API void lua_settable(lua_State *L, int idx) | 951 | LUA_API void lua_settable(lua_State *L, int idx) |
| 889 | { | 952 | { |
| 890 | TValue *o; | 953 | TValue *o; |
| 891 | cTValue *t = index2adr(L, idx); | 954 | cTValue *t = index2adr_check(L, idx); |
| 892 | api_checknelems(L, 2); | 955 | lj_checkapi_slot(2); |
| 893 | api_checkvalidindex(L, t); | ||
| 894 | o = lj_meta_tset(L, t, L->top-2); | 956 | o = lj_meta_tset(L, t, L->top-2); |
| 895 | if (o) { | 957 | if (o) { |
| 896 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ | 958 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ |
| 897 | copyTV(L, o, L->top-1); | ||
| 898 | L->top -= 2; | 959 | L->top -= 2; |
| 960 | copyTV(L, o, L->top+1); | ||
| 899 | } else { | 961 | } else { |
| 900 | L->top += 3; | 962 | TValue *base = L->top; |
| 901 | copyTV(L, L->top-1, L->top-6); | 963 | copyTV(L, base+2, base-3-2*LJ_FR2); |
| 902 | lj_vm_call(L, L->top-3, 0+1); | 964 | L->top = base+3; |
| 903 | L->top -= 3; | 965 | lj_vm_call(L, base, 0+1); |
| 966 | L->top -= 3+LJ_FR2; | ||
| 904 | } | 967 | } |
| 905 | } | 968 | } |
| 906 | 969 | ||
| @@ -908,20 +971,19 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k) | |||
| 908 | { | 971 | { |
| 909 | TValue *o; | 972 | TValue *o; |
| 910 | TValue key; | 973 | TValue key; |
| 911 | cTValue *t = index2adr(L, idx); | 974 | cTValue *t = index2adr_check(L, idx); |
| 912 | api_checknelems(L, 1); | 975 | lj_checkapi_slot(1); |
| 913 | api_checkvalidindex(L, t); | ||
| 914 | setstrV(L, &key, lj_str_newz(L, k)); | 976 | setstrV(L, &key, lj_str_newz(L, k)); |
| 915 | o = lj_meta_tset(L, t, &key); | 977 | o = lj_meta_tset(L, t, &key); |
| 916 | if (o) { | 978 | if (o) { |
| 917 | L->top--; | ||
| 918 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ | 979 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ |
| 919 | copyTV(L, o, L->top); | 980 | copyTV(L, o, --L->top); |
| 920 | } else { | 981 | } else { |
| 921 | L->top += 3; | 982 | TValue *base = L->top; |
| 922 | copyTV(L, L->top-1, L->top-6); | 983 | copyTV(L, base+2, base-3-2*LJ_FR2); |
| 923 | lj_vm_call(L, L->top-3, 0+1); | 984 | L->top = base+3; |
| 924 | L->top -= 2; | 985 | lj_vm_call(L, base, 0+1); |
| 986 | L->top -= 2+LJ_FR2; | ||
| 925 | } | 987 | } |
| 926 | } | 988 | } |
| 927 | 989 | ||
| @@ -929,7 +991,7 @@ LUA_API void lua_rawset(lua_State *L, int idx) | |||
| 929 | { | 991 | { |
| 930 | GCtab *t = tabV(index2adr(L, idx)); | 992 | GCtab *t = tabV(index2adr(L, idx)); |
| 931 | TValue *dst, *key; | 993 | TValue *dst, *key; |
| 932 | api_checknelems(L, 2); | 994 | lj_checkapi_slot(2); |
| 933 | key = L->top-2; | 995 | key = L->top-2; |
| 934 | dst = lj_tab_set(L, t, key); | 996 | dst = lj_tab_set(L, t, key); |
| 935 | copyTV(L, dst, key+1); | 997 | copyTV(L, dst, key+1); |
| @@ -941,7 +1003,7 @@ LUA_API void lua_rawseti(lua_State *L, int idx, int n) | |||
| 941 | { | 1003 | { |
| 942 | GCtab *t = tabV(index2adr(L, idx)); | 1004 | GCtab *t = tabV(index2adr(L, idx)); |
| 943 | TValue *dst, *src; | 1005 | TValue *dst, *src; |
| 944 | api_checknelems(L, 1); | 1006 | lj_checkapi_slot(1); |
| 945 | dst = lj_tab_setint(L, t, n); | 1007 | dst = lj_tab_setint(L, t, n); |
| 946 | src = L->top-1; | 1008 | src = L->top-1; |
| 947 | copyTV(L, dst, src); | 1009 | copyTV(L, dst, src); |
| @@ -953,13 +1015,12 @@ LUA_API int lua_setmetatable(lua_State *L, int idx) | |||
| 953 | { | 1015 | { |
| 954 | global_State *g; | 1016 | global_State *g; |
| 955 | GCtab *mt; | 1017 | GCtab *mt; |
| 956 | cTValue *o = index2adr(L, idx); | 1018 | cTValue *o = index2adr_check(L, idx); |
| 957 | api_checknelems(L, 1); | 1019 | lj_checkapi_slot(1); |
| 958 | api_checkvalidindex(L, o); | ||
| 959 | if (tvisnil(L->top-1)) { | 1020 | if (tvisnil(L->top-1)) { |
| 960 | mt = NULL; | 1021 | mt = NULL; |
| 961 | } else { | 1022 | } else { |
| 962 | api_check(L, tvistab(L->top-1)); | 1023 | lj_checkapi(tvistab(L->top-1), "top stack slot is not a table"); |
| 963 | mt = tabV(L->top-1); | 1024 | mt = tabV(L->top-1); |
| 964 | } | 1025 | } |
| 965 | g = G(L); | 1026 | g = G(L); |
| @@ -989,13 +1050,18 @@ LUA_API int lua_setmetatable(lua_State *L, int idx) | |||
| 989 | return 1; | 1050 | return 1; |
| 990 | } | 1051 | } |
| 991 | 1052 | ||
| 1053 | LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname) | ||
| 1054 | { | ||
| 1055 | lua_getfield(L, LUA_REGISTRYINDEX, tname); | ||
| 1056 | lua_setmetatable(L, -2); | ||
| 1057 | } | ||
| 1058 | |||
| 992 | LUA_API int lua_setfenv(lua_State *L, int idx) | 1059 | LUA_API int lua_setfenv(lua_State *L, int idx) |
| 993 | { | 1060 | { |
| 994 | cTValue *o = index2adr(L, idx); | 1061 | cTValue *o = index2adr_check(L, idx); |
| 995 | GCtab *t; | 1062 | GCtab *t; |
| 996 | api_checknelems(L, 1); | 1063 | lj_checkapi_slot(1); |
| 997 | api_checkvalidindex(L, o); | 1064 | lj_checkapi(tvistab(L->top-1), "top stack slot is not a table"); |
| 998 | api_check(L, tvistab(L->top-1)); | ||
| 999 | t = tabV(L->top-1); | 1065 | t = tabV(L->top-1); |
| 1000 | if (tvisfunc(o)) { | 1066 | if (tvisfunc(o)) { |
| 1001 | setgcref(funcV(o)->c.env, obj2gco(t)); | 1067 | setgcref(funcV(o)->c.env, obj2gco(t)); |
| @@ -1018,7 +1084,7 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n) | |||
| 1018 | TValue *val; | 1084 | TValue *val; |
| 1019 | GCobj *o; | 1085 | GCobj *o; |
| 1020 | const char *name; | 1086 | const char *name; |
| 1021 | api_checknelems(L, 1); | 1087 | lj_checkapi_slot(1); |
| 1022 | name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o); | 1088 | name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o); |
| 1023 | if (name) { | 1089 | if (name) { |
| 1024 | L->top--; | 1090 | L->top--; |
| @@ -1030,11 +1096,25 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n) | |||
| 1030 | 1096 | ||
| 1031 | /* -- Calls --------------------------------------------------------------- */ | 1097 | /* -- Calls --------------------------------------------------------------- */ |
| 1032 | 1098 | ||
| 1099 | #if LJ_FR2 | ||
| 1100 | static TValue *api_call_base(lua_State *L, int nargs) | ||
| 1101 | { | ||
| 1102 | TValue *o = L->top, *base = o - nargs; | ||
| 1103 | L->top = o+1; | ||
| 1104 | for (; o > base; o--) copyTV(L, o, o-1); | ||
| 1105 | setnilV(o); | ||
| 1106 | return o+1; | ||
| 1107 | } | ||
| 1108 | #else | ||
| 1109 | #define api_call_base(L, nargs) (L->top - (nargs)) | ||
| 1110 | #endif | ||
| 1111 | |||
| 1033 | LUA_API void lua_call(lua_State *L, int nargs, int nresults) | 1112 | LUA_API void lua_call(lua_State *L, int nargs, int nresults) |
| 1034 | { | 1113 | { |
| 1035 | api_check(L, L->status == 0 || L->status == LUA_ERRERR); | 1114 | lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR, |
| 1036 | api_checknelems(L, nargs+1); | 1115 | "thread called in wrong state %d", L->status); |
| 1037 | lj_vm_call(L, L->top - nargs, nresults+1); | 1116 | lj_checkapi_slot(nargs+1); |
| 1117 | lj_vm_call(L, api_call_base(L, nargs), nresults+1); | ||
| 1038 | } | 1118 | } |
| 1039 | 1119 | ||
| 1040 | LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) | 1120 | LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) |
| @@ -1043,16 +1123,16 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) | |||
| 1043 | uint8_t oldh = hook_save(g); | 1123 | uint8_t oldh = hook_save(g); |
| 1044 | ptrdiff_t ef; | 1124 | ptrdiff_t ef; |
| 1045 | int status; | 1125 | int status; |
| 1046 | api_check(L, L->status == 0 || L->status == LUA_ERRERR); | 1126 | lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR, |
| 1047 | api_checknelems(L, nargs+1); | 1127 | "thread called in wrong state %d", L->status); |
| 1128 | lj_checkapi_slot(nargs+1); | ||
| 1048 | if (errfunc == 0) { | 1129 | if (errfunc == 0) { |
| 1049 | ef = 0; | 1130 | ef = 0; |
| 1050 | } else { | 1131 | } else { |
| 1051 | cTValue *o = stkindex2adr(L, errfunc); | 1132 | cTValue *o = index2adr_stack(L, errfunc); |
| 1052 | api_checkvalidindex(L, o); | ||
| 1053 | ef = savestack(L, o); | 1133 | ef = savestack(L, o); |
| 1054 | } | 1134 | } |
| 1055 | status = lj_vm_pcall(L, L->top - nargs, nresults+1, ef); | 1135 | status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef); |
| 1056 | if (status) hook_restore(g, oldh); | 1136 | if (status) hook_restore(g, oldh); |
| 1057 | return status; | 1137 | return status; |
| 1058 | } | 1138 | } |
| @@ -1060,12 +1140,17 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) | |||
| 1060 | static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) | 1140 | static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) |
| 1061 | { | 1141 | { |
| 1062 | GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L)); | 1142 | GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L)); |
| 1143 | TValue *top = L->top; | ||
| 1063 | fn->c.f = func; | 1144 | fn->c.f = func; |
| 1064 | setfuncV(L, L->top, fn); | 1145 | setfuncV(L, top++, fn); |
| 1065 | setlightudV(L->top+1, checklightudptr(L, ud)); | 1146 | if (LJ_FR2) setnilV(top++); |
| 1147 | #if LJ_64 | ||
| 1148 | ud = lj_lightud_intern(L, ud); | ||
| 1149 | #endif | ||
| 1150 | setrawlightudV(top++, ud); | ||
| 1066 | cframe_nres(L->cframe) = 1+0; /* Zero results. */ | 1151 | cframe_nres(L->cframe) = 1+0; /* Zero results. */ |
| 1067 | L->top += 2; | 1152 | L->top = top; |
| 1068 | return L->top-1; /* Now call the newly allocated C function. */ | 1153 | return top-1; /* Now call the newly allocated C function. */ |
| 1069 | } | 1154 | } |
| 1070 | 1155 | ||
| 1071 | LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) | 1156 | LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) |
| @@ -1073,7 +1158,8 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) | |||
| 1073 | global_State *g = G(L); | 1158 | global_State *g = G(L); |
| 1074 | uint8_t oldh = hook_save(g); | 1159 | uint8_t oldh = hook_save(g); |
| 1075 | int status; | 1160 | int status; |
| 1076 | api_check(L, L->status == 0 || L->status == LUA_ERRERR); | 1161 | lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR, |
| 1162 | "thread called in wrong state %d", L->status); | ||
| 1077 | status = lj_vm_cpcall(L, func, ud, cpcall); | 1163 | status = lj_vm_cpcall(L, func, ud, cpcall); |
| 1078 | if (status) hook_restore(g, oldh); | 1164 | if (status) hook_restore(g, oldh); |
| 1079 | return status; | 1165 | return status; |
| @@ -1082,10 +1168,11 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) | |||
| 1082 | LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) | 1168 | LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) |
| 1083 | { | 1169 | { |
| 1084 | if (luaL_getmetafield(L, idx, field)) { | 1170 | if (luaL_getmetafield(L, idx, field)) { |
| 1085 | TValue *base = L->top--; | 1171 | TValue *top = L->top--; |
| 1086 | copyTV(L, base, index2adr(L, idx)); | 1172 | if (LJ_FR2) setnilV(top++); |
| 1087 | L->top = base+1; | 1173 | copyTV(L, top++, index2adr(L, idx)); |
| 1088 | lj_vm_call(L, base, 1+1); | 1174 | L->top = top; |
| 1175 | lj_vm_call(L, top-1, 1+1); | ||
| 1089 | return 1; | 1176 | return 1; |
| 1090 | } | 1177 | } |
| 1091 | return 0; | 1178 | return 0; |
| @@ -1093,6 +1180,11 @@ LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) | |||
| 1093 | 1180 | ||
| 1094 | /* -- Coroutine yield and resume ------------------------------------------ */ | 1181 | /* -- Coroutine yield and resume ------------------------------------------ */ |
| 1095 | 1182 | ||
| 1183 | LUA_API int lua_isyieldable(lua_State *L) | ||
| 1184 | { | ||
| 1185 | return cframe_canyield(L->cframe); | ||
| 1186 | } | ||
| 1187 | |||
| 1096 | LUA_API int lua_yield(lua_State *L, int nresults) | 1188 | LUA_API int lua_yield(lua_State *L, int nresults) |
| 1097 | { | 1189 | { |
| 1098 | void *cf = L->cframe; | 1190 | void *cf = L->cframe; |
| @@ -1112,13 +1204,16 @@ LUA_API int lua_yield(lua_State *L, int nresults) | |||
| 1112 | } else { /* Yield from hook: add a pseudo-frame. */ | 1204 | } else { /* Yield from hook: add a pseudo-frame. */ |
| 1113 | TValue *top = L->top; | 1205 | TValue *top = L->top; |
| 1114 | hook_leave(g); | 1206 | hook_leave(g); |
| 1115 | top->u64 = cframe_multres(cf); | 1207 | (top++)->u64 = cframe_multres(cf); |
| 1116 | setcont(top+1, lj_cont_hook); | 1208 | setcont(top, lj_cont_hook); |
| 1117 | setframe_pc(top+1, cframe_pc(cf)-1); | 1209 | if (LJ_FR2) top++; |
| 1118 | setframe_gc(top+2, obj2gco(L)); | 1210 | setframe_pc(top, cframe_pc(cf)-1); |
| 1119 | setframe_ftsz(top+2, (int)((char *)(top+3)-(char *)L->base)+FRAME_CONT); | 1211 | top++; |
| 1120 | L->top = L->base = top+3; | 1212 | setframe_gc(top, obj2gco(L), LJ_TTHREAD); |
| 1121 | #if LJ_TARGET_X64 | 1213 | if (LJ_FR2) top++; |
| 1214 | setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT); | ||
| 1215 | L->top = L->base = top+1; | ||
| 1216 | #if ((defined(__GNUC__) || defined(__clang__)) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND) || LJ_TARGET_WINDOWS | ||
| 1122 | lj_err_throw(L, LUA_YIELD); | 1217 | lj_err_throw(L, LUA_YIELD); |
| 1123 | #else | 1218 | #else |
| 1124 | L->cframe = NULL; | 1219 | L->cframe = NULL; |
| @@ -1134,7 +1229,9 @@ LUA_API int lua_yield(lua_State *L, int nresults) | |||
| 1134 | LUA_API int lua_resume(lua_State *L, int nargs) | 1229 | LUA_API int lua_resume(lua_State *L, int nargs) |
| 1135 | { | 1230 | { |
| 1136 | if (L->cframe == NULL && L->status <= LUA_YIELD) | 1231 | if (L->cframe == NULL && L->status <= LUA_YIELD) |
| 1137 | return lj_vm_resume(L, L->top - nargs, 0, 0); | 1232 | return lj_vm_resume(L, |
| 1233 | L->status == LUA_OK ? api_call_base(L, nargs) : L->top - nargs, | ||
| 1234 | 0, 0); | ||
| 1138 | L->top = L->base; | 1235 | L->top = L->base; |
| 1139 | setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP)); | 1236 | setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP)); |
| 1140 | incr_top(L); | 1237 | incr_top(L); |
| @@ -1164,7 +1261,7 @@ LUA_API int lua_gc(lua_State *L, int what, int data) | |||
| 1164 | res = (int)(g->gc.total & 0x3ff); | 1261 | res = (int)(g->gc.total & 0x3ff); |
| 1165 | break; | 1262 | break; |
| 1166 | case LUA_GCSTEP: { | 1263 | case LUA_GCSTEP: { |
| 1167 | MSize a = (MSize)data << 10; | 1264 | GCSize a = (GCSize)data << 10; |
| 1168 | g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0; | 1265 | g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0; |
| 1169 | while (g->gc.total >= g->gc.threshold) | 1266 | while (g->gc.total >= g->gc.threshold) |
| 1170 | if (lj_gc_step(L) > 0) { | 1267 | if (lj_gc_step(L) > 0) { |
| @@ -1181,6 +1278,9 @@ LUA_API int lua_gc(lua_State *L, int what, int data) | |||
| 1181 | res = (int)(g->gc.stepmul); | 1278 | res = (int)(g->gc.stepmul); |
| 1182 | g->gc.stepmul = (MSize)data; | 1279 | g->gc.stepmul = (MSize)data; |
| 1183 | break; | 1280 | break; |
| 1281 | case LUA_GCISRUNNING: | ||
| 1282 | res = (g->gc.threshold != LJ_MAX_MEM); | ||
| 1283 | break; | ||
| 1184 | default: | 1284 | default: |
| 1185 | res = -1; /* Invalid option. */ | 1285 | res = -1; /* Invalid option. */ |
| 1186 | } | 1286 | } |
