diff options
Diffstat (limited to 'src/lj_api.c')
-rw-r--r-- | src/lj_api.c | 393 |
1 files changed, 252 insertions, 141 deletions
diff --git a/src/lj_api.c b/src/lj_api.c index 04a41792..d869ebf8 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 | } |
@@ -98,17 +115,24 @@ LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg) | |||
98 | lj_err_callerv(L, LJ_ERR_STKOVM, msg); | 115 | lj_err_callerv(L, LJ_ERR_STKOVM, msg); |
99 | } | 116 | } |
100 | 117 | ||
101 | LUA_API void lua_xmove(lua_State *from, lua_State *to, int n) | 118 | LUA_API void lua_xmove(lua_State *L, lua_State *to, int n) |
102 | { | 119 | { |
103 | TValue *f, *t; | 120 | TValue *f, *t; |
104 | if (from == to) return; | 121 | if (L == to) return; |
105 | api_checknelems(from, n); | 122 | lj_checkapi_slot(n); |
106 | api_check(from, G(from) == G(to)); | 123 | lj_checkapi(G(L) == G(to), "move across global states"); |
107 | lj_state_checkstack(to, (MSize)n); | 124 | lj_state_checkstack(to, (MSize)n); |
108 | f = from->top; | 125 | f = L->top; |
109 | t = to->top = to->top + n; | 126 | t = to->top = to->top + n; |
110 | while (--n >= 0) copyTV(to, --t, --f); | 127 | while (--n >= 0) copyTV(to, --t, --f); |
111 | from->top = f; | 128 | L->top = f; |
129 | } | ||
130 | |||
131 | LUA_API const lua_Number *lua_version(lua_State *L) | ||
132 | { | ||
133 | static const lua_Number version = LUA_VERSION_NUM; | ||
134 | UNUSED(L); | ||
135 | return &version; | ||
112 | } | 136 | } |
113 | 137 | ||
114 | /* -- Stack manipulation -------------------------------------------------- */ | 138 | /* -- Stack manipulation -------------------------------------------------- */ |
@@ -121,7 +145,7 @@ LUA_API int lua_gettop(lua_State *L) | |||
121 | LUA_API void lua_settop(lua_State *L, int idx) | 145 | LUA_API void lua_settop(lua_State *L, int idx) |
122 | { | 146 | { |
123 | if (idx >= 0) { | 147 | if (idx >= 0) { |
124 | api_check(L, idx <= tvref(L->maxstack) - L->base); | 148 | lj_checkapi(idx <= tvref(L->maxstack) - L->base, "bad stack slot %d", idx); |
125 | if (L->base + idx > L->top) { | 149 | if (L->base + idx > L->top) { |
126 | if (L->base + idx >= tvref(L->maxstack)) | 150 | if (L->base + idx >= tvref(L->maxstack)) |
127 | lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base)); | 151 | lj_state_growstack(L, (MSize)idx - (MSize)(L->top - L->base)); |
@@ -130,51 +154,58 @@ LUA_API void lua_settop(lua_State *L, int idx) | |||
130 | L->top = L->base + idx; | 154 | L->top = L->base + idx; |
131 | } | 155 | } |
132 | } else { | 156 | } else { |
133 | api_check(L, -(idx+1) <= (L->top - L->base)); | 157 | lj_checkapi(-(idx+1) <= (L->top - L->base), "bad stack slot %d", idx); |
134 | L->top += idx+1; /* Shrinks top (idx < 0). */ | 158 | L->top += idx+1; /* Shrinks top (idx < 0). */ |
135 | } | 159 | } |
136 | } | 160 | } |
137 | 161 | ||
138 | LUA_API void lua_remove(lua_State *L, int idx) | 162 | LUA_API void lua_remove(lua_State *L, int idx) |
139 | { | 163 | { |
140 | TValue *p = stkindex2adr(L, idx); | 164 | TValue *p = index2adr_stack(L, idx); |
141 | api_checkvalidindex(L, p); | ||
142 | while (++p < L->top) copyTV(L, p-1, p); | 165 | while (++p < L->top) copyTV(L, p-1, p); |
143 | L->top--; | 166 | L->top--; |
144 | } | 167 | } |
145 | 168 | ||
146 | LUA_API void lua_insert(lua_State *L, int idx) | 169 | LUA_API void lua_insert(lua_State *L, int idx) |
147 | { | 170 | { |
148 | TValue *q, *p = stkindex2adr(L, idx); | 171 | 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); | 172 | for (q = L->top; q > p; q--) copyTV(L, q, q-1); |
151 | copyTV(L, p, L->top); | 173 | copyTV(L, p, L->top); |
152 | } | 174 | } |
153 | 175 | ||
154 | LUA_API void lua_replace(lua_State *L, int idx) | 176 | static void copy_slot(lua_State *L, TValue *f, int idx) |
155 | { | 177 | { |
156 | api_checknelems(L, 1); | ||
157 | if (idx == LUA_GLOBALSINDEX) { | 178 | if (idx == LUA_GLOBALSINDEX) { |
158 | api_check(L, tvistab(L->top-1)); | 179 | lj_checkapi(tvistab(f), "stack slot %d is not a table", idx); |
159 | /* NOBARRIER: A thread (i.e. L) is never black. */ | 180 | /* NOBARRIER: A thread (i.e. L) is never black. */ |
160 | setgcref(L->env, obj2gco(tabV(L->top-1))); | 181 | setgcref(L->env, obj2gco(tabV(f))); |
161 | } else if (idx == LUA_ENVIRONINDEX) { | 182 | } else if (idx == LUA_ENVIRONINDEX) { |
162 | GCfunc *fn = curr_func(L); | 183 | GCfunc *fn = curr_func(L); |
163 | if (fn->c.gct != ~LJ_TFUNC) | 184 | if (fn->c.gct != ~LJ_TFUNC) |
164 | lj_err_msg(L, LJ_ERR_NOENV); | 185 | lj_err_msg(L, LJ_ERR_NOENV); |
165 | api_check(L, tvistab(L->top-1)); | 186 | lj_checkapi(tvistab(f), "stack slot %d is not a table", idx); |
166 | setgcref(fn->c.env, obj2gco(tabV(L->top-1))); | 187 | setgcref(fn->c.env, obj2gco(tabV(f))); |
167 | lj_gc_barrier(L, fn, L->top-1); | 188 | lj_gc_barrier(L, fn, f); |
168 | } else { | 189 | } else { |
169 | TValue *o = index2adr(L, idx); | 190 | TValue *o = index2adr_check(L, idx); |
170 | api_checkvalidindex(L, o); | 191 | copyTV(L, o, f); |
171 | copyTV(L, o, L->top-1); | ||
172 | if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */ | 192 | if (idx < LUA_GLOBALSINDEX) /* Need a barrier for upvalues. */ |
173 | lj_gc_barrier(L, curr_func(L), L->top-1); | 193 | lj_gc_barrier(L, curr_func(L), f); |
174 | } | 194 | } |
195 | } | ||
196 | |||
197 | LUA_API void lua_replace(lua_State *L, int idx) | ||
198 | { | ||
199 | lj_checkapi_slot(1); | ||
200 | copy_slot(L, L->top - 1, idx); | ||
175 | L->top--; | 201 | L->top--; |
176 | } | 202 | } |
177 | 203 | ||
204 | LUA_API void lua_copy(lua_State *L, int fromidx, int toidx) | ||
205 | { | ||
206 | copy_slot(L, index2adr(L, fromidx), toidx); | ||
207 | } | ||
208 | |||
178 | LUA_API void lua_pushvalue(lua_State *L, int idx) | 209 | LUA_API void lua_pushvalue(lua_State *L, int idx) |
179 | { | 210 | { |
180 | copyTV(L, L->top, index2adr(L, idx)); | 211 | copyTV(L, L->top, index2adr(L, idx)); |
@@ -188,7 +219,7 @@ LUA_API int lua_type(lua_State *L, int idx) | |||
188 | cTValue *o = index2adr(L, idx); | 219 | cTValue *o = index2adr(L, idx); |
189 | if (tvisnumber(o)) { | 220 | if (tvisnumber(o)) { |
190 | return LUA_TNUMBER; | 221 | return LUA_TNUMBER; |
191 | #if LJ_64 | 222 | #if LJ_64 && !LJ_GC64 |
192 | } else if (tvislightud(o)) { | 223 | } else if (tvislightud(o)) { |
193 | return LUA_TLIGHTUSERDATA; | 224 | return LUA_TLIGHTUSERDATA; |
194 | #endif | 225 | #endif |
@@ -201,7 +232,7 @@ LUA_API int lua_type(lua_State *L, int idx) | |||
201 | #else | 232 | #else |
202 | int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u); | 233 | int tt = (int)(((t < 8 ? 0x98042110u : 0x75a06u) >> 4*(t&7)) & 15u); |
203 | #endif | 234 | #endif |
204 | lua_assert(tt != LUA_TNIL || tvisnil(o)); | 235 | lj_assertL(tt != LUA_TNIL || tvisnil(o), "bad tag conversion"); |
205 | return tt; | 236 | return tt; |
206 | } | 237 | } |
207 | } | 238 | } |
@@ -268,7 +299,7 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2) | |||
268 | return 0; | 299 | return 0; |
269 | } else if (tvispri(o1)) { | 300 | } else if (tvispri(o1)) { |
270 | return o1 != niltv(L) && o2 != niltv(L); | 301 | return o1 != niltv(L) && o2 != niltv(L); |
271 | #if LJ_64 | 302 | #if LJ_64 && !LJ_GC64 |
272 | } else if (tvislightud(o1)) { | 303 | } else if (tvislightud(o1)) { |
273 | return o1->u64 == o2->u64; | 304 | return o1->u64 == o2->u64; |
274 | #endif | 305 | #endif |
@@ -283,8 +314,8 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2) | |||
283 | } else { | 314 | } else { |
284 | L->top = base+2; | 315 | L->top = base+2; |
285 | lj_vm_call(L, base, 1+1); | 316 | lj_vm_call(L, base, 1+1); |
286 | L->top -= 2; | 317 | L->top -= 2+LJ_FR2; |
287 | return tvistruecond(L->top+1); | 318 | return tvistruecond(L->top+1+LJ_FR2); |
288 | } | 319 | } |
289 | } | 320 | } |
290 | } | 321 | } |
@@ -306,8 +337,8 @@ LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2) | |||
306 | } else { | 337 | } else { |
307 | L->top = base+2; | 338 | L->top = base+2; |
308 | lj_vm_call(L, base, 1+1); | 339 | lj_vm_call(L, base, 1+1); |
309 | L->top -= 2; | 340 | L->top -= 2+LJ_FR2; |
310 | return tvistruecond(L->top+1); | 341 | return tvistruecond(L->top+1+LJ_FR2); |
311 | } | 342 | } |
312 | } | 343 | } |
313 | } | 344 | } |
@@ -324,6 +355,22 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx) | |||
324 | return 0; | 355 | return 0; |
325 | } | 356 | } |
326 | 357 | ||
358 | LUA_API lua_Number lua_tonumberx(lua_State *L, int idx, int *ok) | ||
359 | { | ||
360 | cTValue *o = index2adr(L, idx); | ||
361 | TValue tmp; | ||
362 | if (LJ_LIKELY(tvisnumber(o))) { | ||
363 | if (ok) *ok = 1; | ||
364 | return numberVnum(o); | ||
365 | } else if (tvisstr(o) && lj_strscan_num(strV(o), &tmp)) { | ||
366 | if (ok) *ok = 1; | ||
367 | return numV(&tmp); | ||
368 | } else { | ||
369 | if (ok) *ok = 0; | ||
370 | return 0; | ||
371 | } | ||
372 | } | ||
373 | |||
327 | LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx) | 374 | LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx) |
328 | { | 375 | { |
329 | cTValue *o = index2adr(L, idx); | 376 | cTValue *o = index2adr(L, idx); |
@@ -361,9 +408,38 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx) | |||
361 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) | 408 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) |
362 | return 0; | 409 | return 0; |
363 | if (tvisint(&tmp)) | 410 | if (tvisint(&tmp)) |
364 | return (lua_Integer)intV(&tmp); | 411 | return intV(&tmp); |
412 | n = numV(&tmp); | ||
413 | } | ||
414 | #if LJ_64 | ||
415 | return (lua_Integer)n; | ||
416 | #else | ||
417 | return lj_num2int(n); | ||
418 | #endif | ||
419 | } | ||
420 | |||
421 | LUA_API lua_Integer lua_tointegerx(lua_State *L, int idx, int *ok) | ||
422 | { | ||
423 | cTValue *o = index2adr(L, idx); | ||
424 | TValue tmp; | ||
425 | lua_Number n; | ||
426 | if (LJ_LIKELY(tvisint(o))) { | ||
427 | if (ok) *ok = 1; | ||
428 | return intV(o); | ||
429 | } else if (LJ_LIKELY(tvisnum(o))) { | ||
430 | n = numV(o); | ||
431 | } else { | ||
432 | if (!(tvisstr(o) && lj_strscan_number(strV(o), &tmp))) { | ||
433 | if (ok) *ok = 0; | ||
434 | return 0; | ||
435 | } | ||
436 | if (tvisint(&tmp)) { | ||
437 | if (ok) *ok = 1; | ||
438 | return intV(&tmp); | ||
439 | } | ||
365 | n = numV(&tmp); | 440 | n = numV(&tmp); |
366 | } | 441 | } |
442 | if (ok) *ok = 1; | ||
367 | #if LJ_64 | 443 | #if LJ_64 |
368 | return (lua_Integer)n; | 444 | return (lua_Integer)n; |
369 | #else | 445 | #else |
@@ -434,7 +510,7 @@ LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len) | |||
434 | } else if (tvisnumber(o)) { | 510 | } else if (tvisnumber(o)) { |
435 | lj_gc_check(L); | 511 | lj_gc_check(L); |
436 | o = index2adr(L, idx); /* GC may move the stack. */ | 512 | o = index2adr(L, idx); /* GC may move the stack. */ |
437 | s = lj_str_fromnumber(L, o); | 513 | s = lj_strfmt_number(L, o); |
438 | setstrV(L, o, s); | 514 | setstrV(L, o, s); |
439 | } else { | 515 | } else { |
440 | if (len != NULL) *len = 0; | 516 | if (len != NULL) *len = 0; |
@@ -453,7 +529,7 @@ LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len) | |||
453 | } else if (tvisnumber(o)) { | 529 | } else if (tvisnumber(o)) { |
454 | lj_gc_check(L); | 530 | lj_gc_check(L); |
455 | o = index2adr(L, idx); /* GC may move the stack. */ | 531 | o = index2adr(L, idx); /* GC may move the stack. */ |
456 | s = lj_str_fromnumber(L, o); | 532 | s = lj_strfmt_number(L, o); |
457 | setstrV(L, o, s); | 533 | setstrV(L, o, s); |
458 | } else { | 534 | } else { |
459 | lj_err_argt(L, idx, LUA_TSTRING); | 535 | lj_err_argt(L, idx, LUA_TSTRING); |
@@ -475,7 +551,7 @@ LUALIB_API const char *luaL_optlstring(lua_State *L, int idx, | |||
475 | } else if (tvisnumber(o)) { | 551 | } else if (tvisnumber(o)) { |
476 | lj_gc_check(L); | 552 | lj_gc_check(L); |
477 | o = index2adr(L, idx); /* GC may move the stack. */ | 553 | o = index2adr(L, idx); /* GC may move the stack. */ |
478 | s = lj_str_fromnumber(L, o); | 554 | s = lj_strfmt_number(L, o); |
479 | setstrV(L, o, s); | 555 | setstrV(L, o, s); |
480 | } else { | 556 | } else { |
481 | lj_err_argt(L, idx, LUA_TSTRING); | 557 | lj_err_argt(L, idx, LUA_TSTRING); |
@@ -507,7 +583,7 @@ LUA_API size_t lua_objlen(lua_State *L, int idx) | |||
507 | } else if (tvisudata(o)) { | 583 | } else if (tvisudata(o)) { |
508 | return udataV(o)->len; | 584 | return udataV(o)->len; |
509 | } else if (tvisnumber(o)) { | 585 | } else if (tvisnumber(o)) { |
510 | GCstr *s = lj_str_fromnumber(L, o); | 586 | GCstr *s = lj_strfmt_number(L, o); |
511 | setstrV(L, o, s); | 587 | setstrV(L, o, s); |
512 | return s->len; | 588 | return s->len; |
513 | } else { | 589 | } else { |
@@ -532,7 +608,7 @@ LUA_API void *lua_touserdata(lua_State *L, int idx) | |||
532 | if (tvisudata(o)) | 608 | if (tvisudata(o)) |
533 | return uddata(udataV(o)); | 609 | return uddata(udataV(o)); |
534 | else if (tvislightud(o)) | 610 | else if (tvislightud(o)) |
535 | return lightudV(o); | 611 | return lightudV(G(L), o); |
536 | else | 612 | else |
537 | return NULL; | 613 | return NULL; |
538 | } | 614 | } |
@@ -545,17 +621,7 @@ LUA_API lua_State *lua_tothread(lua_State *L, int idx) | |||
545 | 621 | ||
546 | LUA_API const void *lua_topointer(lua_State *L, int idx) | 622 | LUA_API const void *lua_topointer(lua_State *L, int idx) |
547 | { | 623 | { |
548 | cTValue *o = index2adr(L, idx); | 624 | 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 | } | 625 | } |
560 | 626 | ||
561 | /* -- Stack setters (object creation) ------------------------------------- */ | 627 | /* -- Stack setters (object creation) ------------------------------------- */ |
@@ -606,7 +672,7 @@ LUA_API const char *lua_pushvfstring(lua_State *L, const char *fmt, | |||
606 | va_list argp) | 672 | va_list argp) |
607 | { | 673 | { |
608 | lj_gc_check(L); | 674 | lj_gc_check(L); |
609 | return lj_str_pushvf(L, fmt, argp); | 675 | return lj_strfmt_pushvf(L, fmt, argp); |
610 | } | 676 | } |
611 | 677 | ||
612 | LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...) | 678 | LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...) |
@@ -615,7 +681,7 @@ LUA_API const char *lua_pushfstring(lua_State *L, const char *fmt, ...) | |||
615 | va_list argp; | 681 | va_list argp; |
616 | lj_gc_check(L); | 682 | lj_gc_check(L); |
617 | va_start(argp, fmt); | 683 | va_start(argp, fmt); |
618 | ret = lj_str_pushvf(L, fmt, argp); | 684 | ret = lj_strfmt_pushvf(L, fmt, argp); |
619 | va_end(argp); | 685 | va_end(argp); |
620 | return ret; | 686 | return ret; |
621 | } | 687 | } |
@@ -624,14 +690,14 @@ LUA_API void lua_pushcclosure(lua_State *L, lua_CFunction f, int n) | |||
624 | { | 690 | { |
625 | GCfunc *fn; | 691 | GCfunc *fn; |
626 | lj_gc_check(L); | 692 | lj_gc_check(L); |
627 | api_checknelems(L, n); | 693 | lj_checkapi_slot(n); |
628 | fn = lj_func_newC(L, (MSize)n, getcurrenv(L)); | 694 | fn = lj_func_newC(L, (MSize)n, getcurrenv(L)); |
629 | fn->c.f = f; | 695 | fn->c.f = f; |
630 | L->top -= n; | 696 | L->top -= n; |
631 | while (n--) | 697 | while (n--) |
632 | copyTV(L, &fn->c.upvalue[n], L->top+n); | 698 | copyTV(L, &fn->c.upvalue[n], L->top+n); |
633 | setfuncV(L, L->top, fn); | 699 | setfuncV(L, L->top, fn); |
634 | lua_assert(iswhite(obj2gco(fn))); | 700 | lj_assertL(iswhite(obj2gco(fn)), "new GC object is not white"); |
635 | incr_top(L); | 701 | incr_top(L); |
636 | } | 702 | } |
637 | 703 | ||
@@ -643,16 +709,17 @@ LUA_API void lua_pushboolean(lua_State *L, int b) | |||
643 | 709 | ||
644 | LUA_API void lua_pushlightuserdata(lua_State *L, void *p) | 710 | LUA_API void lua_pushlightuserdata(lua_State *L, void *p) |
645 | { | 711 | { |
646 | setlightudV(L->top, checklightudptr(L, p)); | 712 | #if LJ_64 |
713 | p = lj_lightud_intern(L, p); | ||
714 | #endif | ||
715 | setrawlightudV(L->top, p); | ||
647 | incr_top(L); | 716 | incr_top(L); |
648 | } | 717 | } |
649 | 718 | ||
650 | LUA_API void lua_createtable(lua_State *L, int narray, int nrec) | 719 | LUA_API void lua_createtable(lua_State *L, int narray, int nrec) |
651 | { | 720 | { |
652 | GCtab *t; | ||
653 | lj_gc_check(L); | 721 | lj_gc_check(L); |
654 | t = lj_tab_new(L, (uint32_t)(narray > 0 ? narray+1 : 0), hsize2hbits(nrec)); | 722 | settabV(L, L->top, lj_tab_new_ah(L, narray, nrec)); |
655 | settabV(L, L->top, t); | ||
656 | incr_top(L); | 723 | incr_top(L); |
657 | } | 724 | } |
658 | 725 | ||
@@ -703,7 +770,7 @@ LUA_API void *lua_newuserdata(lua_State *L, size_t size) | |||
703 | 770 | ||
704 | LUA_API void lua_concat(lua_State *L, int n) | 771 | LUA_API void lua_concat(lua_State *L, int n) |
705 | { | 772 | { |
706 | api_checknelems(L, n); | 773 | lj_checkapi_slot(n); |
707 | if (n >= 2) { | 774 | if (n >= 2) { |
708 | n--; | 775 | n--; |
709 | do { | 776 | do { |
@@ -715,8 +782,8 @@ LUA_API void lua_concat(lua_State *L, int n) | |||
715 | n -= (int)(L->top - top); | 782 | n -= (int)(L->top - top); |
716 | L->top = top+2; | 783 | L->top = top+2; |
717 | lj_vm_call(L, top, 1+1); | 784 | lj_vm_call(L, top, 1+1); |
718 | L->top--; | 785 | L->top -= 1+LJ_FR2; |
719 | copyTV(L, L->top-1, L->top); | 786 | copyTV(L, L->top-1, L->top+LJ_FR2); |
720 | } while (--n > 0); | 787 | } while (--n > 0); |
721 | } else if (n == 0) { /* Push empty string. */ | 788 | } else if (n == 0) { /* Push empty string. */ |
722 | setstrV(L, L->top, &G(L)->strempty); | 789 | setstrV(L, L->top, &G(L)->strempty); |
@@ -729,30 +796,28 @@ LUA_API void lua_concat(lua_State *L, int n) | |||
729 | 796 | ||
730 | LUA_API void lua_gettable(lua_State *L, int idx) | 797 | LUA_API void lua_gettable(lua_State *L, int idx) |
731 | { | 798 | { |
732 | cTValue *v, *t = index2adr(L, idx); | 799 | cTValue *t = index2adr_check(L, idx); |
733 | api_checkvalidindex(L, t); | 800 | cTValue *v = lj_meta_tget(L, t, L->top-1); |
734 | v = lj_meta_tget(L, t, L->top-1); | ||
735 | if (v == NULL) { | 801 | if (v == NULL) { |
736 | L->top += 2; | 802 | L->top += 2; |
737 | lj_vm_call(L, L->top-2, 1+1); | 803 | lj_vm_call(L, L->top-2, 1+1); |
738 | L->top -= 2; | 804 | L->top -= 2+LJ_FR2; |
739 | v = L->top+1; | 805 | v = L->top+1+LJ_FR2; |
740 | } | 806 | } |
741 | copyTV(L, L->top-1, v); | 807 | copyTV(L, L->top-1, v); |
742 | } | 808 | } |
743 | 809 | ||
744 | LUA_API void lua_getfield(lua_State *L, int idx, const char *k) | 810 | LUA_API void lua_getfield(lua_State *L, int idx, const char *k) |
745 | { | 811 | { |
746 | cTValue *v, *t = index2adr(L, idx); | 812 | cTValue *v, *t = index2adr_check(L, idx); |
747 | TValue key; | 813 | TValue key; |
748 | api_checkvalidindex(L, t); | ||
749 | setstrV(L, &key, lj_str_newz(L, k)); | 814 | setstrV(L, &key, lj_str_newz(L, k)); |
750 | v = lj_meta_tget(L, t, &key); | 815 | v = lj_meta_tget(L, t, &key); |
751 | if (v == NULL) { | 816 | if (v == NULL) { |
752 | L->top += 2; | 817 | L->top += 2; |
753 | lj_vm_call(L, L->top-2, 1+1); | 818 | lj_vm_call(L, L->top-2, 1+1); |
754 | L->top -= 2; | 819 | L->top -= 2+LJ_FR2; |
755 | v = L->top+1; | 820 | v = L->top+1+LJ_FR2; |
756 | } | 821 | } |
757 | copyTV(L, L->top, v); | 822 | copyTV(L, L->top, v); |
758 | incr_top(L); | 823 | incr_top(L); |
@@ -761,14 +826,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) | 826 | LUA_API void lua_rawget(lua_State *L, int idx) |
762 | { | 827 | { |
763 | cTValue *t = index2adr(L, idx); | 828 | cTValue *t = index2adr(L, idx); |
764 | api_check(L, tvistab(t)); | 829 | 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)); | 830 | copyTV(L, L->top-1, lj_tab_get(L, tabV(t), L->top-1)); |
766 | } | 831 | } |
767 | 832 | ||
768 | LUA_API void lua_rawgeti(lua_State *L, int idx, int n) | 833 | LUA_API void lua_rawgeti(lua_State *L, int idx, int n) |
769 | { | 834 | { |
770 | cTValue *v, *t = index2adr(L, idx); | 835 | cTValue *v, *t = index2adr(L, idx); |
771 | api_check(L, tvistab(t)); | 836 | lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); |
772 | v = lj_tab_getint(tabV(t), n); | 837 | v = lj_tab_getint(tabV(t), n); |
773 | if (v) { | 838 | if (v) { |
774 | copyTV(L, L->top, v); | 839 | copyTV(L, L->top, v); |
@@ -810,8 +875,7 @@ LUALIB_API int luaL_getmetafield(lua_State *L, int idx, const char *field) | |||
810 | 875 | ||
811 | LUA_API void lua_getfenv(lua_State *L, int idx) | 876 | LUA_API void lua_getfenv(lua_State *L, int idx) |
812 | { | 877 | { |
813 | cTValue *o = index2adr(L, idx); | 878 | cTValue *o = index2adr_check(L, idx); |
814 | api_checkvalidindex(L, o); | ||
815 | if (tvisfunc(o)) { | 879 | if (tvisfunc(o)) { |
816 | settabV(L, L->top, tabref(funcV(o)->c.env)); | 880 | settabV(L, L->top, tabref(funcV(o)->c.env)); |
817 | } else if (tvisudata(o)) { | 881 | } else if (tvisudata(o)) { |
@@ -828,12 +892,14 @@ LUA_API int lua_next(lua_State *L, int idx) | |||
828 | { | 892 | { |
829 | cTValue *t = index2adr(L, idx); | 893 | cTValue *t = index2adr(L, idx); |
830 | int more; | 894 | int more; |
831 | api_check(L, tvistab(t)); | 895 | lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); |
832 | more = lj_tab_next(L, tabV(t), L->top-1); | 896 | more = lj_tab_next(tabV(t), L->top-1, L->top-1); |
833 | if (more) { | 897 | if (more > 0) { |
834 | incr_top(L); /* Return new key and value slot. */ | 898 | incr_top(L); /* Return new key and value slot. */ |
835 | } else { /* End of traversal. */ | 899 | } else if (!more) { /* End of traversal. */ |
836 | L->top--; /* Remove key slot. */ | 900 | L->top--; /* Remove key slot. */ |
901 | } else { | ||
902 | lj_err_msg(L, LJ_ERR_NEXTIDX); | ||
837 | } | 903 | } |
838 | return more; | 904 | return more; |
839 | } | 905 | } |
@@ -854,7 +920,7 @@ LUA_API void *lua_upvalueid(lua_State *L, int idx, int n) | |||
854 | { | 920 | { |
855 | GCfunc *fn = funcV(index2adr(L, idx)); | 921 | GCfunc *fn = funcV(index2adr(L, idx)); |
856 | n--; | 922 | n--; |
857 | api_check(L, (uint32_t)n < fn->l.nupvalues); | 923 | lj_checkapi((uint32_t)n < fn->l.nupvalues, "bad upvalue %d", n); |
858 | return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) : | 924 | return isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) : |
859 | (void *)&fn->c.upvalue[n]; | 925 | (void *)&fn->c.upvalue[n]; |
860 | } | 926 | } |
@@ -864,13 +930,15 @@ LUA_API void lua_upvaluejoin(lua_State *L, int idx1, int n1, int idx2, int n2) | |||
864 | GCfunc *fn1 = funcV(index2adr(L, idx1)); | 930 | GCfunc *fn1 = funcV(index2adr(L, idx1)); |
865 | GCfunc *fn2 = funcV(index2adr(L, idx2)); | 931 | GCfunc *fn2 = funcV(index2adr(L, idx2)); |
866 | n1--; n2--; | 932 | n1--; n2--; |
867 | api_check(L, isluafunc(fn1) && (uint32_t)n1 < fn1->l.nupvalues); | 933 | 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); | 934 | lj_checkapi(isluafunc(fn2), "stack slot %d is not a Lua function", idx2); |
935 | lj_checkapi((uint32_t)n1 < fn1->l.nupvalues, "bad upvalue %d", n1+1); | ||
936 | lj_checkapi((uint32_t)n2 < fn2->l.nupvalues, "bad upvalue %d", n2+1); | ||
869 | setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]); | 937 | setgcrefr(fn1->l.uvptr[n1], fn2->l.uvptr[n2]); |
870 | lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1])); | 938 | lj_gc_objbarrier(L, fn1, gcref(fn1->l.uvptr[n1])); |
871 | } | 939 | } |
872 | 940 | ||
873 | LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname) | 941 | LUALIB_API void *luaL_testudata(lua_State *L, int idx, const char *tname) |
874 | { | 942 | { |
875 | cTValue *o = index2adr(L, idx); | 943 | cTValue *o = index2adr(L, idx); |
876 | if (tvisudata(o)) { | 944 | if (tvisudata(o)) { |
@@ -879,8 +947,14 @@ LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname) | |||
879 | if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable)) | 947 | if (tv && tvistab(tv) && tabV(tv) == tabref(ud->metatable)) |
880 | return uddata(ud); | 948 | return uddata(ud); |
881 | } | 949 | } |
882 | lj_err_argtype(L, idx, tname); | 950 | return NULL; /* value is not a userdata with a metatable */ |
883 | return NULL; /* unreachable */ | 951 | } |
952 | |||
953 | LUALIB_API void *luaL_checkudata(lua_State *L, int idx, const char *tname) | ||
954 | { | ||
955 | void *p = luaL_testudata(L, idx, tname); | ||
956 | if (!p) lj_err_argtype(L, idx, tname); | ||
957 | return p; | ||
884 | } | 958 | } |
885 | 959 | ||
886 | /* -- Object setters ------------------------------------------------------ */ | 960 | /* -- Object setters ------------------------------------------------------ */ |
@@ -888,19 +962,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) | 962 | LUA_API void lua_settable(lua_State *L, int idx) |
889 | { | 963 | { |
890 | TValue *o; | 964 | TValue *o; |
891 | cTValue *t = index2adr(L, idx); | 965 | cTValue *t = index2adr_check(L, idx); |
892 | api_checknelems(L, 2); | 966 | lj_checkapi_slot(2); |
893 | api_checkvalidindex(L, t); | ||
894 | o = lj_meta_tset(L, t, L->top-2); | 967 | o = lj_meta_tset(L, t, L->top-2); |
895 | if (o) { | 968 | if (o) { |
896 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ | 969 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ |
897 | copyTV(L, o, L->top-1); | ||
898 | L->top -= 2; | 970 | L->top -= 2; |
971 | copyTV(L, o, L->top+1); | ||
899 | } else { | 972 | } else { |
900 | L->top += 3; | 973 | TValue *base = L->top; |
901 | copyTV(L, L->top-1, L->top-6); | 974 | copyTV(L, base+2, base-3-2*LJ_FR2); |
902 | lj_vm_call(L, L->top-3, 0+1); | 975 | L->top = base+3; |
903 | L->top -= 3; | 976 | lj_vm_call(L, base, 0+1); |
977 | L->top -= 3+LJ_FR2; | ||
904 | } | 978 | } |
905 | } | 979 | } |
906 | 980 | ||
@@ -908,20 +982,19 @@ LUA_API void lua_setfield(lua_State *L, int idx, const char *k) | |||
908 | { | 982 | { |
909 | TValue *o; | 983 | TValue *o; |
910 | TValue key; | 984 | TValue key; |
911 | cTValue *t = index2adr(L, idx); | 985 | cTValue *t = index2adr_check(L, idx); |
912 | api_checknelems(L, 1); | 986 | lj_checkapi_slot(1); |
913 | api_checkvalidindex(L, t); | ||
914 | setstrV(L, &key, lj_str_newz(L, k)); | 987 | setstrV(L, &key, lj_str_newz(L, k)); |
915 | o = lj_meta_tset(L, t, &key); | 988 | o = lj_meta_tset(L, t, &key); |
916 | if (o) { | 989 | if (o) { |
917 | L->top--; | ||
918 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ | 990 | /* NOBARRIER: lj_meta_tset ensures the table is not black. */ |
919 | copyTV(L, o, L->top); | 991 | copyTV(L, o, --L->top); |
920 | } else { | 992 | } else { |
921 | L->top += 3; | 993 | TValue *base = L->top; |
922 | copyTV(L, L->top-1, L->top-6); | 994 | copyTV(L, base+2, base-3-2*LJ_FR2); |
923 | lj_vm_call(L, L->top-3, 0+1); | 995 | L->top = base+3; |
924 | L->top -= 2; | 996 | lj_vm_call(L, base, 0+1); |
997 | L->top -= 2+LJ_FR2; | ||
925 | } | 998 | } |
926 | } | 999 | } |
927 | 1000 | ||
@@ -929,7 +1002,7 @@ LUA_API void lua_rawset(lua_State *L, int idx) | |||
929 | { | 1002 | { |
930 | GCtab *t = tabV(index2adr(L, idx)); | 1003 | GCtab *t = tabV(index2adr(L, idx)); |
931 | TValue *dst, *key; | 1004 | TValue *dst, *key; |
932 | api_checknelems(L, 2); | 1005 | lj_checkapi_slot(2); |
933 | key = L->top-2; | 1006 | key = L->top-2; |
934 | dst = lj_tab_set(L, t, key); | 1007 | dst = lj_tab_set(L, t, key); |
935 | copyTV(L, dst, key+1); | 1008 | copyTV(L, dst, key+1); |
@@ -941,7 +1014,7 @@ LUA_API void lua_rawseti(lua_State *L, int idx, int n) | |||
941 | { | 1014 | { |
942 | GCtab *t = tabV(index2adr(L, idx)); | 1015 | GCtab *t = tabV(index2adr(L, idx)); |
943 | TValue *dst, *src; | 1016 | TValue *dst, *src; |
944 | api_checknelems(L, 1); | 1017 | lj_checkapi_slot(1); |
945 | dst = lj_tab_setint(L, t, n); | 1018 | dst = lj_tab_setint(L, t, n); |
946 | src = L->top-1; | 1019 | src = L->top-1; |
947 | copyTV(L, dst, src); | 1020 | copyTV(L, dst, src); |
@@ -953,13 +1026,12 @@ LUA_API int lua_setmetatable(lua_State *L, int idx) | |||
953 | { | 1026 | { |
954 | global_State *g; | 1027 | global_State *g; |
955 | GCtab *mt; | 1028 | GCtab *mt; |
956 | cTValue *o = index2adr(L, idx); | 1029 | cTValue *o = index2adr_check(L, idx); |
957 | api_checknelems(L, 1); | 1030 | lj_checkapi_slot(1); |
958 | api_checkvalidindex(L, o); | ||
959 | if (tvisnil(L->top-1)) { | 1031 | if (tvisnil(L->top-1)) { |
960 | mt = NULL; | 1032 | mt = NULL; |
961 | } else { | 1033 | } else { |
962 | api_check(L, tvistab(L->top-1)); | 1034 | lj_checkapi(tvistab(L->top-1), "top stack slot is not a table"); |
963 | mt = tabV(L->top-1); | 1035 | mt = tabV(L->top-1); |
964 | } | 1036 | } |
965 | g = G(L); | 1037 | g = G(L); |
@@ -988,13 +1060,18 @@ LUA_API int lua_setmetatable(lua_State *L, int idx) | |||
988 | return 1; | 1060 | return 1; |
989 | } | 1061 | } |
990 | 1062 | ||
1063 | LUALIB_API void luaL_setmetatable(lua_State *L, const char *tname) | ||
1064 | { | ||
1065 | lua_getfield(L, LUA_REGISTRYINDEX, tname); | ||
1066 | lua_setmetatable(L, -2); | ||
1067 | } | ||
1068 | |||
991 | LUA_API int lua_setfenv(lua_State *L, int idx) | 1069 | LUA_API int lua_setfenv(lua_State *L, int idx) |
992 | { | 1070 | { |
993 | cTValue *o = index2adr(L, idx); | 1071 | cTValue *o = index2adr_check(L, idx); |
994 | GCtab *t; | 1072 | GCtab *t; |
995 | api_checknelems(L, 1); | 1073 | lj_checkapi_slot(1); |
996 | api_checkvalidindex(L, o); | 1074 | lj_checkapi(tvistab(L->top-1), "top stack slot is not a table"); |
997 | api_check(L, tvistab(L->top-1)); | ||
998 | t = tabV(L->top-1); | 1075 | t = tabV(L->top-1); |
999 | if (tvisfunc(o)) { | 1076 | if (tvisfunc(o)) { |
1000 | setgcref(funcV(o)->c.env, obj2gco(t)); | 1077 | setgcref(funcV(o)->c.env, obj2gco(t)); |
@@ -1017,7 +1094,7 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n) | |||
1017 | TValue *val; | 1094 | TValue *val; |
1018 | GCobj *o; | 1095 | GCobj *o; |
1019 | const char *name; | 1096 | const char *name; |
1020 | api_checknelems(L, 1); | 1097 | lj_checkapi_slot(1); |
1021 | name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o); | 1098 | name = lj_debug_uvnamev(f, (uint32_t)(n-1), &val, &o); |
1022 | if (name) { | 1099 | if (name) { |
1023 | L->top--; | 1100 | L->top--; |
@@ -1029,11 +1106,25 @@ LUA_API const char *lua_setupvalue(lua_State *L, int idx, int n) | |||
1029 | 1106 | ||
1030 | /* -- Calls --------------------------------------------------------------- */ | 1107 | /* -- Calls --------------------------------------------------------------- */ |
1031 | 1108 | ||
1109 | #if LJ_FR2 | ||
1110 | static TValue *api_call_base(lua_State *L, int nargs) | ||
1111 | { | ||
1112 | TValue *o = L->top, *base = o - nargs; | ||
1113 | L->top = o+1; | ||
1114 | for (; o > base; o--) copyTV(L, o, o-1); | ||
1115 | setnilV(o); | ||
1116 | return o+1; | ||
1117 | } | ||
1118 | #else | ||
1119 | #define api_call_base(L, nargs) (L->top - (nargs)) | ||
1120 | #endif | ||
1121 | |||
1032 | LUA_API void lua_call(lua_State *L, int nargs, int nresults) | 1122 | LUA_API void lua_call(lua_State *L, int nargs, int nresults) |
1033 | { | 1123 | { |
1034 | api_check(L, L->status == 0 || L->status == LUA_ERRERR); | 1124 | lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR, |
1035 | api_checknelems(L, nargs+1); | 1125 | "thread called in wrong state %d", L->status); |
1036 | lj_vm_call(L, L->top - nargs, nresults+1); | 1126 | lj_checkapi_slot(nargs+1); |
1127 | lj_vm_call(L, api_call_base(L, nargs), nresults+1); | ||
1037 | } | 1128 | } |
1038 | 1129 | ||
1039 | LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) | 1130 | LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) |
@@ -1042,16 +1133,16 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) | |||
1042 | uint8_t oldh = hook_save(g); | 1133 | uint8_t oldh = hook_save(g); |
1043 | ptrdiff_t ef; | 1134 | ptrdiff_t ef; |
1044 | int status; | 1135 | int status; |
1045 | api_check(L, L->status == 0 || L->status == LUA_ERRERR); | 1136 | lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR, |
1046 | api_checknelems(L, nargs+1); | 1137 | "thread called in wrong state %d", L->status); |
1138 | lj_checkapi_slot(nargs+1); | ||
1047 | if (errfunc == 0) { | 1139 | if (errfunc == 0) { |
1048 | ef = 0; | 1140 | ef = 0; |
1049 | } else { | 1141 | } else { |
1050 | cTValue *o = stkindex2adr(L, errfunc); | 1142 | cTValue *o = index2adr_stack(L, errfunc); |
1051 | api_checkvalidindex(L, o); | ||
1052 | ef = savestack(L, o); | 1143 | ef = savestack(L, o); |
1053 | } | 1144 | } |
1054 | status = lj_vm_pcall(L, L->top - nargs, nresults+1, ef); | 1145 | status = lj_vm_pcall(L, api_call_base(L, nargs), nresults+1, ef); |
1055 | if (status) hook_restore(g, oldh); | 1146 | if (status) hook_restore(g, oldh); |
1056 | return status; | 1147 | return status; |
1057 | } | 1148 | } |
@@ -1059,12 +1150,17 @@ LUA_API int lua_pcall(lua_State *L, int nargs, int nresults, int errfunc) | |||
1059 | static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) | 1150 | static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud) |
1060 | { | 1151 | { |
1061 | GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L)); | 1152 | GCfunc *fn = lj_func_newC(L, 0, getcurrenv(L)); |
1153 | TValue *top = L->top; | ||
1062 | fn->c.f = func; | 1154 | fn->c.f = func; |
1063 | setfuncV(L, L->top, fn); | 1155 | setfuncV(L, top++, fn); |
1064 | setlightudV(L->top+1, checklightudptr(L, ud)); | 1156 | if (LJ_FR2) setnilV(top++); |
1157 | #if LJ_64 | ||
1158 | ud = lj_lightud_intern(L, ud); | ||
1159 | #endif | ||
1160 | setrawlightudV(top++, ud); | ||
1065 | cframe_nres(L->cframe) = 1+0; /* Zero results. */ | 1161 | cframe_nres(L->cframe) = 1+0; /* Zero results. */ |
1066 | L->top += 2; | 1162 | L->top = top; |
1067 | return L->top-1; /* Now call the newly allocated C function. */ | 1163 | return top-1; /* Now call the newly allocated C function. */ |
1068 | } | 1164 | } |
1069 | 1165 | ||
1070 | LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) | 1166 | LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) |
@@ -1072,7 +1168,8 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) | |||
1072 | global_State *g = G(L); | 1168 | global_State *g = G(L); |
1073 | uint8_t oldh = hook_save(g); | 1169 | uint8_t oldh = hook_save(g); |
1074 | int status; | 1170 | int status; |
1075 | api_check(L, L->status == 0 || L->status == LUA_ERRERR); | 1171 | lj_checkapi(L->status == LUA_OK || L->status == LUA_ERRERR, |
1172 | "thread called in wrong state %d", L->status); | ||
1076 | status = lj_vm_cpcall(L, func, ud, cpcall); | 1173 | status = lj_vm_cpcall(L, func, ud, cpcall); |
1077 | if (status) hook_restore(g, oldh); | 1174 | if (status) hook_restore(g, oldh); |
1078 | return status; | 1175 | return status; |
@@ -1081,10 +1178,11 @@ LUA_API int lua_cpcall(lua_State *L, lua_CFunction func, void *ud) | |||
1081 | LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) | 1178 | LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) |
1082 | { | 1179 | { |
1083 | if (luaL_getmetafield(L, idx, field)) { | 1180 | if (luaL_getmetafield(L, idx, field)) { |
1084 | TValue *base = L->top--; | 1181 | TValue *top = L->top--; |
1085 | copyTV(L, base, index2adr(L, idx)); | 1182 | if (LJ_FR2) setnilV(top++); |
1086 | L->top = base+1; | 1183 | copyTV(L, top++, index2adr(L, idx)); |
1087 | lj_vm_call(L, base, 1+1); | 1184 | L->top = top; |
1185 | lj_vm_call(L, top-1, 1+1); | ||
1088 | return 1; | 1186 | return 1; |
1089 | } | 1187 | } |
1090 | return 0; | 1188 | return 0; |
@@ -1092,6 +1190,11 @@ LUALIB_API int luaL_callmeta(lua_State *L, int idx, const char *field) | |||
1092 | 1190 | ||
1093 | /* -- Coroutine yield and resume ------------------------------------------ */ | 1191 | /* -- Coroutine yield and resume ------------------------------------------ */ |
1094 | 1192 | ||
1193 | LUA_API int lua_isyieldable(lua_State *L) | ||
1194 | { | ||
1195 | return cframe_canyield(L->cframe); | ||
1196 | } | ||
1197 | |||
1095 | LUA_API int lua_yield(lua_State *L, int nresults) | 1198 | LUA_API int lua_yield(lua_State *L, int nresults) |
1096 | { | 1199 | { |
1097 | void *cf = L->cframe; | 1200 | void *cf = L->cframe; |
@@ -1111,13 +1214,16 @@ LUA_API int lua_yield(lua_State *L, int nresults) | |||
1111 | } else { /* Yield from hook: add a pseudo-frame. */ | 1214 | } else { /* Yield from hook: add a pseudo-frame. */ |
1112 | TValue *top = L->top; | 1215 | TValue *top = L->top; |
1113 | hook_leave(g); | 1216 | hook_leave(g); |
1114 | top->u64 = cframe_multres(cf); | 1217 | (top++)->u64 = cframe_multres(cf); |
1115 | setcont(top+1, lj_cont_hook); | 1218 | setcont(top, lj_cont_hook); |
1116 | setframe_pc(top+1, cframe_pc(cf)-1); | 1219 | if (LJ_FR2) top++; |
1117 | setframe_gc(top+2, obj2gco(L)); | 1220 | setframe_pc(top, cframe_pc(cf)-1); |
1118 | setframe_ftsz(top+2, (int)((char *)(top+3)-(char *)L->base)+FRAME_CONT); | 1221 | top++; |
1119 | L->top = L->base = top+3; | 1222 | setframe_gc(top, obj2gco(L), LJ_TTHREAD); |
1120 | #if LJ_TARGET_X64 | 1223 | if (LJ_FR2) top++; |
1224 | setframe_ftsz(top, ((char *)(top+1)-(char *)L->base)+FRAME_CONT); | ||
1225 | L->top = L->base = top+1; | ||
1226 | #if ((defined(__GNUC__) || defined(__clang__)) && (LJ_TARGET_X64 || defined(LUAJIT_UNWIND_EXTERNAL)) && !LJ_NO_UNWIND) || LJ_TARGET_WINDOWS | ||
1121 | lj_err_throw(L, LUA_YIELD); | 1227 | lj_err_throw(L, LUA_YIELD); |
1122 | #else | 1228 | #else |
1123 | L->cframe = NULL; | 1229 | L->cframe = NULL; |
@@ -1133,7 +1239,9 @@ LUA_API int lua_yield(lua_State *L, int nresults) | |||
1133 | LUA_API int lua_resume(lua_State *L, int nargs) | 1239 | LUA_API int lua_resume(lua_State *L, int nargs) |
1134 | { | 1240 | { |
1135 | if (L->cframe == NULL && L->status <= LUA_YIELD) | 1241 | if (L->cframe == NULL && L->status <= LUA_YIELD) |
1136 | return lj_vm_resume(L, L->top - nargs, 0, 0); | 1242 | return lj_vm_resume(L, |
1243 | L->status == LUA_OK ? api_call_base(L, nargs) : L->top - nargs, | ||
1244 | 0, 0); | ||
1137 | L->top = L->base; | 1245 | L->top = L->base; |
1138 | setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP)); | 1246 | setstrV(L, L->top, lj_err_str(L, LJ_ERR_COSUSP)); |
1139 | incr_top(L); | 1247 | incr_top(L); |
@@ -1163,7 +1271,7 @@ LUA_API int lua_gc(lua_State *L, int what, int data) | |||
1163 | res = (int)(g->gc.total & 0x3ff); | 1271 | res = (int)(g->gc.total & 0x3ff); |
1164 | break; | 1272 | break; |
1165 | case LUA_GCSTEP: { | 1273 | case LUA_GCSTEP: { |
1166 | MSize a = (MSize)data << 10; | 1274 | GCSize a = (GCSize)data << 10; |
1167 | g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0; | 1275 | g->gc.threshold = (a <= g->gc.total) ? (g->gc.total - a) : 0; |
1168 | while (g->gc.total >= g->gc.threshold) | 1276 | while (g->gc.total >= g->gc.threshold) |
1169 | if (lj_gc_step(L) > 0) { | 1277 | if (lj_gc_step(L) > 0) { |
@@ -1180,6 +1288,9 @@ LUA_API int lua_gc(lua_State *L, int what, int data) | |||
1180 | res = (int)(g->gc.stepmul); | 1288 | res = (int)(g->gc.stepmul); |
1181 | g->gc.stepmul = (MSize)data; | 1289 | g->gc.stepmul = (MSize)data; |
1182 | break; | 1290 | break; |
1291 | case LUA_GCISRUNNING: | ||
1292 | res = (g->gc.threshold != LJ_MAX_MEM); | ||
1293 | break; | ||
1183 | default: | 1294 | default: |
1184 | res = -1; /* Invalid option. */ | 1295 | res = -1; /* Invalid option. */ |
1185 | } | 1296 | } |