Showing the changes to src/lapi.c (1 of 60 files). Show all
Unified · Split
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | /* |
| 2 | −** $Id: lapi.c,v 2.185 2013/07/05 14:29:51 roberto Exp $ | |
| 2 | +** $Id: lapi.c,v 2.201 2014/03/12 20:57:40 roberto Exp $ | |
| 3 | 3 | ** Lua API |
| 4 | 4 | ** See Copyright Notice in lua.h |
| 5 | 5 | */ |
| @@ -286,7 +286,7 @@ LUA_API int lua_isstring (lua_State *L, int idx) { · 280 unmodified lines | ||
| 286 | 286 | |
| 287 | 287 | LUA_API int lua_isuserdata (lua_State *L, int idx) { |
| 288 | 288 | const TValue *o = index2addr(L, idx); |
| 289 | − return (ttisuserdata(o) || ttislightuserdata(o)); | |
| 289 | + return (ttisfulluserdata(o) || ttislightuserdata(o)); | |
| 290 | 290 | } |
| 291 | 291 | |
| 292 | 292 | |
| @@ -299,9 +299,9 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { · 6 unmodified lines | ||
| 299 | 299 | |
| 300 | 300 | LUA_API void lua_arith (lua_State *L, int op) { |
| 301 | 301 | lua_lock(L); |
| 302 | − if (op != LUA_OPUNM) /* all other operations expect two operands */ | |
| 303 | − api_checknelems(L, 2); | |
| 304 | − else { /* for unary minus, add fake 2nd operand */ | |
| 302 | + if (op != LUA_OPUNM && op != LUA_OPBNOT) | |
| 303 | + api_checknelems(L, 2); /* all other operations expect two operands */ | |
| 304 | + else { /* for unary operations, add fake 2nd operand */ | |
| 305 | 305 | api_checknelems(L, 1); |
| 306 | 306 | setobjs2s(L, L->top, L->top - 1); |
| 307 | 307 | L->top++; |
| @@ -379,20 +379,20 @@ LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *pisnum) { · 71 unmodified lines | ||
| 379 | 379 | isnum = 1; |
| 380 | 380 | break; |
| 381 | 381 | } |
| 382 | − case LUA_TNUMFLT: { | |
| 383 | − const lua_Number twop = (~(lua_Unsigned)0) + cast_num(1); | |
| 384 | − lua_Number n = fltvalue(o); | |
| 382 | + case LUA_TNUMFLT: { /* compute floor(n) % 2^(numbits in an integer) */ | |
| 383 | + const lua_Number twop = cast_num(MAX_UINTEGER) + cast_num(1); /* 2^n */ | |
| 384 | + lua_Number n = fltvalue(o); /* get value */ | |
| 385 | 385 | int neg = 0; |
| 386 | − n = l_floor(n); | |
| 386 | + n = l_floor(n); /* get its floor */ | |
| 387 | 387 | if (n < 0) { |
| 388 | 388 | neg = 1; |
| 389 | − n = -n; | |
| 389 | + n = -n; /* make 'n' positive, so that 'fmod' is the same as '%' */ | |
| 390 | 390 | } |
| 391 | − n = l_mathop(fmod)(n, twop); | |
| 392 | − if (luai_numisnan(L,n)) /* not a number? */ | |
| 391 | + n = l_mathop(fmod)(n, twop); /* n = n % 2^(numbits in an integer) */ | |
| 392 | + if (luai_numisnan(n)) /* not a number? */ | |
| 393 | 393 | break; /* not an integer, too */ |
| 394 | − res = cast_unsigned(n); | |
| 395 | − if (neg) res = 0u - res; | |
| 394 | + res = cast_unsigned(n); /* 'n' now must fit in an unsigned */ | |
| 395 | + if (neg) res = 0u - res; /* back to negative, if needed */ | |
| 396 | 396 | isnum = 1; |
| 397 | 397 | break; |
| 398 | 398 | } |
| @@ -586,8 +586,10 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { · 187 unmodified lines | ||
| 586 | 586 | cl = luaF_newCclosure(L, n); |
| 587 | 587 | cl->c.f = fn; |
| 588 | 588 | L->top -= n; |
| 589 | − while (n--) | |
| 589 | + while (n--) { | |
| 590 | 590 | setobj2n(L, &cl->c.upvalue[n], L->top + n); |
| 591 | + /* does not need barrier because closure is white */ | |
| 592 | + } | |
| 591 | 593 | setclCvalue(L, L->top, cl); |
| 592 | 594 | } |
| 593 | 595 | api_incr_top(L); |
| @@ -626,7 +628,7 @@ LUA_API int lua_pushthread (lua_State *L) { · 32 unmodified lines | ||
| 626 | 628 | */ |
| 627 | 629 | |
| 628 | 630 | |
| 629 | −LUA_API void lua_getglobal (lua_State *L, const char *var) { | |
| 631 | +LUA_API int lua_getglobal (lua_State *L, const char *var) { | |
| 630 | 632 | Table *reg = hvalue(&G(L)->l_registry); |
| 631 | 633 | const TValue *gt; /* global table */ |
| 632 | 634 | lua_lock(L); |
| @@ -634,19 +636,21 @@ LUA_API void lua_getglobal (lua_State *L, const char *var) { · 1 unmodified line | ||
| 634 | 636 | setsvalue2s(L, L->top++, luaS_new(L, var)); |
| 635 | 637 | luaV_gettable(L, gt, L->top - 1, L->top - 1); |
| 636 | 638 | lua_unlock(L); |
| 639 | + return ttnov(L->top - 1); | |
| 637 | 640 | } |
| 638 | 641 | |
| 639 | 642 | |
| 640 | −LUA_API void lua_gettable (lua_State *L, int idx) { | |
| 643 | +LUA_API int lua_gettable (lua_State *L, int idx) { | |
| 641 | 644 | StkId t; |
| 642 | 645 | lua_lock(L); |
| 643 | 646 | t = index2addr(L, idx); |
| 644 | 647 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
| 645 | 648 | lua_unlock(L); |
| 649 | + return ttnov(L->top - 1); | |
| 646 | 650 | } |
| 647 | 651 | |
| 648 | 652 | |
| 649 | −LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { | |
| 653 | +LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { | |
| 650 | 654 | StkId t; |
| 651 | 655 | lua_lock(L); |
| 652 | 656 | t = index2addr(L, idx); |
| @@ -654,20 +658,22 @@ LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { · 1 unmodified line | ||
| 654 | 658 | api_incr_top(L); |
| 655 | 659 | luaV_gettable(L, t, L->top - 1, L->top - 1); |
| 656 | 660 | lua_unlock(L); |
| 661 | + return ttnov(L->top - 1); | |
| 657 | 662 | } |
| 658 | 663 | |
| 659 | 664 | |
| 660 | −LUA_API void lua_rawget (lua_State *L, int idx) { | |
| 665 | +LUA_API int lua_rawget (lua_State *L, int idx) { | |
| 661 | 666 | StkId t; |
| 662 | 667 | lua_lock(L); |
| 663 | 668 | t = index2addr(L, idx); |
| 664 | 669 | api_check(L, ttistable(t), "table expected"); |
| 665 | 670 | setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); |
| 666 | 671 | lua_unlock(L); |
| 672 | + return ttnov(L->top - 1); | |
| 667 | 673 | } |
| 668 | 674 | |
| 669 | 675 | |
| 670 | −LUA_API void lua_rawgeti (lua_State *L, int idx, lua_Integer n) { | |
| 676 | +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { | |
| 671 | 677 | StkId t; |
| 672 | 678 | lua_lock(L); |
| 673 | 679 | t = index2addr(L, idx); |
| @@ -675,10 +681,11 @@ LUA_API void lua_rawgeti (lua_State *L, int idx, lua_Integer n) { · 1 unmodified line | ||
| 675 | 681 | setobj2s(L, L->top, luaH_getint(hvalue(t), n)); |
| 676 | 682 | api_incr_top(L); |
| 677 | 683 | lua_unlock(L); |
| 684 | + return ttnov(L->top - 1); | |
| 678 | 685 | } |
| 679 | 686 | |
| 680 | 687 | |
| 681 | −LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { | |
| 688 | +LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { | |
| 682 | 689 | StkId t; |
| 683 | 690 | TValue k; |
| 684 | 691 | lua_lock(L); |
| @@ -688,6 +695,7 @@ LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { · 3 unmodified lines | ||
| 688 | 695 | setobj2s(L, L->top, luaH_get(hvalue(t), &k)); |
| 689 | 696 | api_incr_top(L); |
| 690 | 697 | lua_unlock(L); |
| 698 | + return ttnov(L->top - 1); | |
| 691 | 699 | } |
| 692 | 700 | |
| 693 | 701 | |
| @@ -737,11 +745,8 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) { · 43 unmodified lines | ||
| 737 | 745 | StkId o; |
| 738 | 746 | lua_lock(L); |
| 739 | 747 | o = index2addr(L, idx); |
| 740 | − api_check(L, ttisuserdata(o), "userdata expected"); | |
| 741 | − if (uvalue(o)->env) { | |
| 742 | − sethvalue(L, L->top, uvalue(o)->env); | |
| 743 | − } else | |
| 744 | − setnilvalue(L->top); | |
| 748 | + api_check(L, ttisfulluserdata(o), "full userdata expected"); | |
| 749 | + getuservalue(L, rawuvalue(o), L->top); | |
| 745 | 750 | api_incr_top(L); |
| 746 | 751 | lua_unlock(L); |
| 747 | 752 | } |
| @@ -846,7 +851,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { · 98 unmodified lines | ||
| 846 | 851 | case LUA_TTABLE: { |
| 847 | 852 | hvalue(obj)->metatable = mt; |
| 848 | 853 | if (mt) { |
| 849 | − luaC_objbarrierback(L, gcvalue(obj), mt); | |
| 854 | + luaC_objbarrier(L, gcvalue(obj), mt); | |
| 850 | 855 | luaC_checkfinalizer(L, gcvalue(obj), mt); |
| 851 | 856 | } |
| 852 | 857 | break; |
| @@ -875,14 +880,9 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { · 22 unmodified lines | ||
| 875 | 880 | lua_lock(L); |
| 876 | 881 | api_checknelems(L, 1); |
| 877 | 882 | o = index2addr(L, idx); |
| 878 | − api_check(L, ttisuserdata(o), "userdata expected"); | |
| 879 | − if (ttisnil(L->top - 1)) | |
| 880 | − uvalue(o)->env = NULL; | |
| 881 | − else { | |
| 882 | − api_check(L, ttistable(L->top - 1), "table expected"); | |
| 883 | − uvalue(o)->env = hvalue(L->top - 1); | |
| 884 | − luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); | |
| 885 | − } | |
| 883 | + api_check(L, ttisfulluserdata(o), "full userdata expected"); | |
| 884 | + setuservalue(L, rawuvalue(o), L->top - 1); | |
| 885 | + luaC_barrier(L, gcvalue(o), L->top - 1); | |
| 886 | 886 | L->top--; |
| 887 | 887 | lua_unlock(L); |
| 888 | 888 | } |
| @@ -1015,14 +1015,14 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, · 126 unmodified lines | ||
| 1015 | 1015 | } |
| 1016 | 1016 | |
| 1017 | 1017 | |
| 1018 | −LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { | |
| 1018 | +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { | |
| 1019 | 1019 | int status; |
| 1020 | 1020 | TValue *o; |
| 1021 | 1021 | lua_lock(L); |
| 1022 | 1022 | api_checknelems(L, 1); |
| 1023 | 1023 | o = L->top - 1; |
| 1024 | 1024 | if (isLfunction(o)) |
| 1025 | − status = luaU_dump(L, getproto(o), writer, data, 0); | |
| 1025 | + status = luaU_dump(L, getproto(o), writer, data, strip); | |
| 1026 | 1026 | else |
| 1027 | 1027 | status = 1; |
| 1028 | 1028 | lua_unlock(L); |
| @@ -1068,19 +1068,21 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { · 39 unmodified lines | ||
| 1068 | 1068 | break; |
| 1069 | 1069 | } |
| 1070 | 1070 | case LUA_GCSTEP: { |
| 1071 | − if (g->gckind == KGC_GEN) { /* generational mode? */ | |
| 1072 | − res = (g->GCestimate == 0); /* true if it will do major collection */ | |
| 1073 | − luaC_forcestep(L); /* do a single step */ | |
| 1071 | + l_mem debt = 1; /* =1 to signal that it did an actual step */ | |
| 1072 | + int oldrunning = g->gcrunning; | |
| 1073 | + g->gcrunning = 1; /* force GC to run */ | |
| 1074 | + if (data == 0) { | |
| 1075 | + luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ | |
| 1076 | + luaC_step(L); | |
| 1074 | 1077 | } |
| 1075 | − else { | |
| 1076 | − lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; | |
| 1077 | − if (g->gcrunning) | |
| 1078 | − debt += g->GCdebt; /* include current debt */ | |
| 1079 | − luaE_setdebt(g, debt); | |
| 1080 | − luaC_forcestep(L); | |
| 1081 | − if (g->gcstate == GCSpause) /* end of cycle? */ | |
| 1082 | − res = 1; /* signal it */ | |
| 1078 | + else { /* add 'data' to total debt */ | |
| 1079 | + debt = cast(l_mem, data) * 1024 + g->GCdebt; | |
| 1080 | + luaE_setdebt(g, debt); | |
| 1081 | + luaC_checkGC(L); | |
| 1083 | 1082 | } |
| 1083 | + g->gcrunning = oldrunning; /* restore previous state */ | |
| 1084 | + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ | |
| 1085 | + res = 1; /* signal it */ | |
| 1084 | 1086 | break; |
| 1085 | 1087 | } |
| 1086 | 1088 | case LUA_GCSETPAUSE: { |
| @@ -1088,13 +1090,9 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { · 1 unmodified line | ||
| 1088 | 1090 | g->gcpause = data; |
| 1089 | 1091 | break; |
| 1090 | 1092 | } |
| 1091 | − case LUA_GCSETMAJORINC: { | |
| 1092 | − res = g->gcmajorinc; | |
| 1093 | − g->gcmajorinc = data; | |
| 1094 | − break; | |
| 1095 | − } | |
| 1096 | 1093 | case LUA_GCSETSTEPMUL: { |
| 1097 | 1094 | res = g->gcstepmul; |
| 1095 | + if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ | |
| 1098 | 1096 | g->gcstepmul = data; |
| 1099 | 1097 | break; |
| 1100 | 1098 | } |
| @@ -1102,14 +1100,6 @@ LUA_API int lua_gc (lua_State *L, int what, int data) { · 1 unmodified line | ||
| 1102 | 1100 | res = g->gcrunning; |
| 1103 | 1101 | break; |
| 1104 | 1102 | } |
| 1105 | − case LUA_GCGEN: { /* change collector to generational mode */ | |
| 1106 | − luaC_changemode(L, KGC_GEN); | |
| 1107 | − break; | |
| 1108 | − } | |
| 1109 | − case LUA_GCINC: { /* change collector to incremental mode */ | |
| 1110 | − luaC_changemode(L, KGC_NORMAL); | |
| 1111 | − break; | |
| 1112 | − } | |
| 1113 | 1103 | default: res = -1; /* invalid option */ |
| 1114 | 1104 | } |
| 1115 | 1105 | lua_unlock(L); |
| @@ -1197,7 +1187,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { · 81 unmodified lines | ||
| 1197 | 1187 | Udata *u; |
| 1198 | 1188 | lua_lock(L); |
| 1199 | 1189 | luaC_checkGC(L); |
| 1200 | − u = luaS_newudata(L, size, NULL); | |
| 1190 | + u = luaS_newudata(L, size); | |
| 1201 | 1191 | setuvalue(L, L->top, u); |
| 1202 | 1192 | api_incr_top(L); |
| 1203 | 1193 | lua_unlock(L); |
| @@ -1207,7 +1197,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { · 3 unmodified lines | ||
| 1207 | 1197 | |
| 1208 | 1198 | |
| 1209 | 1199 | static const char *aux_upvalue (StkId fi, int n, TValue **val, |
| 1210 | − GCObject **owner) { | |
| 1200 | + GCObject **owner, UpVal **uv) { | |
| 1211 | 1201 | switch (ttype(fi)) { |
| 1212 | 1202 | case LUA_TCCL: { /* C closure */ |
| 1213 | 1203 | CClosure *f = clCvalue(fi); |
| @@ -1222,9 +1212,9 @@ static const char *aux_upvalue (StkId fi, int n, TValue **val, · 8 unmodified lines | ||
| 1222 | 1212 | Proto *p = f->p; |
| 1223 | 1213 | if (!(1 <= n && n <= p->sizeupvalues)) return NULL; |
| 1224 | 1214 | *val = f->upvals[n-1]->v; |
| 1225 | − if (owner) *owner = obj2gco(f->upvals[n - 1]); | |
| 1215 | + if (uv) *uv = f->upvals[n - 1]; | |
| 1226 | 1216 | name = p->upvalues[n-1].name; |
| 1227 | − return (name == NULL) ? "" : getstr(name); | |
| 1217 | + return (name == NULL) ? "(*no name)" : getstr(name); | |
| 1228 | 1218 | } |
| 1229 | 1219 | default: return NULL; /* not a closure */ |
| 1230 | 1220 | } |
| @@ -1235,7 +1225,7 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { · 4 unmodified lines | ||
| 1235 | 1225 | const char *name; |
| 1236 | 1226 | TValue *val = NULL; /* to avoid warnings */ |
| 1237 | 1227 | lua_lock(L); |
| 1238 | − name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); | |
| 1228 | + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); | |
| 1239 | 1229 | if (name) { |
| 1240 | 1230 | setobj2s(L, L->top, val); |
| 1241 | 1231 | api_incr_top(L); |
| @@ -1248,16 +1238,18 @@ LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { · 6 unmodified lines | ||
| 1248 | 1238 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { |
| 1249 | 1239 | const char *name; |
| 1250 | 1240 | TValue *val = NULL; /* to avoid warnings */ |
| 1251 | − GCObject *owner = NULL; /* to avoid warnings */ | |
| 1241 | + GCObject *owner = NULL; | |
| 1242 | + UpVal *uv = NULL; | |
| 1252 | 1243 | StkId fi; |
| 1253 | 1244 | lua_lock(L); |
| 1254 | 1245 | fi = index2addr(L, funcindex); |
| 1255 | 1246 | api_checknelems(L, 1); |
| 1256 | − name = aux_upvalue(fi, n, &val, &owner); | |
| 1247 | + name = aux_upvalue(fi, n, &val, &owner, &uv); | |
| 1257 | 1248 | if (name) { |
| 1258 | 1249 | L->top--; |
| 1259 | 1250 | setobj(L, val, L->top); |
| 1260 | − luaC_barrier(L, owner, L->top); | |
| 1251 | + if (owner) { luaC_barrier(L, owner, L->top); } | |
| 1252 | + else if (uv) { luaC_upvalbarrier(L, uv); } | |
| 1261 | 1253 | } |
| 1262 | 1254 | lua_unlock(L); |
| 1263 | 1255 | return name; |
| @@ -1299,7 +1291,11 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, · 35 unmodified lines | ||
| 1299 | 1291 | LClosure *f1; |
| 1300 | 1292 | UpVal **up1 = getupvalref(L, fidx1, n1, &f1); |
| 1301 | 1293 | UpVal **up2 = getupvalref(L, fidx2, n2, NULL); |
| 1294 | + luaC_upvdeccount(L, *up1); | |
| 1302 | 1295 | *up1 = *up2; |
| 1303 | − luaC_objbarrier(L, f1, *up2); | |
| 1296 | + (*up1)->refcount++; | |
| 1297 | + if (upisopen(*up1)) (*up1)->u.open.touched = 1; | |
| 1298 | + luaC_upvalbarrier(L, *up1); | |
| 1304 | 1299 | } |
| 1305 | 1300 | |
| 1301 | + | |