diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-20 13:52:50 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-20 13:52:50 -0300 |
| commit | ca6fe7449a74efde6f959605dbe77acf3e64ca0b (patch) | |
| tree | a6190e813ff712f7db750d4ecd3afd3ac9c0dbab | |
| parent | 1afd5a152dc8b3a304236dc4e07bca38ea5eb53a (diff) | |
| download | lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.tar.gz lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.tar.bz2 lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.zip | |
userdata can have multiple user values
| -rw-r--r-- | lapi.c | 35 | ||||
| -rw-r--r-- | ldblib.c | 13 | ||||
| -rw-r--r-- | lgc.c | 33 | ||||
| -rw-r--r-- | lobject.h | 60 | ||||
| -rw-r--r-- | lstring.c | 13 | ||||
| -rw-r--r-- | lstring.h | 7 | ||||
| -rw-r--r-- | ltests.c | 25 | ||||
| -rw-r--r-- | lua.h | 15 |
8 files changed, 121 insertions, 80 deletions
| @@ -10,6 +10,7 @@ | |||
| 10 | #include "lprefix.h" | 10 | #include "lprefix.h" |
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | #include <limits.h> | ||
| 13 | #include <stdarg.h> | 14 | #include <stdarg.h> |
| 14 | #include <string.h> | 15 | #include <string.h> |
| 15 | 16 | ||
| @@ -733,15 +734,23 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { | |||
| 733 | } | 734 | } |
| 734 | 735 | ||
| 735 | 736 | ||
| 736 | LUA_API int lua_getuservalue (lua_State *L, int idx) { | 737 | LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { |
| 737 | TValue *o; | 738 | TValue *o; |
| 739 | int t; | ||
| 738 | lua_lock(L); | 740 | lua_lock(L); |
| 739 | o = index2value(L, idx); | 741 | o = index2value(L, idx); |
| 740 | api_check(L, ttisfulluserdata(o), "full userdata expected"); | 742 | api_check(L, ttisfulluserdata(o), "full userdata expected"); |
| 741 | getuservalue(L, uvalue(o), s2v(L->top)); | 743 | if (n <= 0 || n > uvalue(o)->nuvalue) { |
| 744 | setnilvalue(s2v(L->top)); | ||
| 745 | t = LUA_TNONE; | ||
| 746 | } | ||
| 747 | else { | ||
| 748 | setobj2s(L, L->top, &uvalue(o)->uv[n - 1].uv); | ||
| 749 | t = ttnov(s2v(L->top)); | ||
| 750 | } | ||
| 742 | api_incr_top(L); | 751 | api_incr_top(L); |
| 743 | lua_unlock(L); | 752 | lua_unlock(L); |
| 744 | return ttnov(s2v(L->top - 1)); | 753 | return t; |
| 745 | } | 754 | } |
| 746 | 755 | ||
| 747 | 756 | ||
| @@ -903,16 +912,23 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { | |||
| 903 | } | 912 | } |
| 904 | 913 | ||
| 905 | 914 | ||
| 906 | LUA_API void lua_setuservalue (lua_State *L, int idx) { | 915 | LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { |
| 907 | TValue *o; | 916 | TValue *o; |
| 917 | int res; | ||
| 908 | lua_lock(L); | 918 | lua_lock(L); |
| 909 | api_checknelems(L, 1); | 919 | api_checknelems(L, 1); |
| 910 | o = index2value(L, idx); | 920 | o = index2value(L, idx); |
| 911 | api_check(L, ttisfulluserdata(o), "full userdata expected"); | 921 | api_check(L, ttisfulluserdata(o), "full userdata expected"); |
| 912 | setuservalue(L, uvalue(o), s2v(L->top - 1)); | 922 | if (!(0 < n && n <= uvalue(o)->nuvalue)) |
| 913 | luaC_barrier(L, gcvalue(o), s2v(L->top - 1)); | 923 | res = 0; |
| 914 | L->top--; | 924 | else { |
| 925 | setobj(L, &uvalue(o)->uv[n - 1].uv, s2v(L->top - 1)); | ||
| 926 | luaC_barrierback(L, gcvalue(o), s2v(L->top - 1)); | ||
| 927 | L->top--; | ||
| 928 | res = 1; | ||
| 929 | } | ||
| 915 | lua_unlock(L); | 930 | lua_unlock(L); |
| 931 | return res; | ||
| 916 | } | 932 | } |
| 917 | 933 | ||
| 918 | 934 | ||
| @@ -1231,10 +1247,11 @@ LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { | |||
| 1231 | } | 1247 | } |
| 1232 | 1248 | ||
| 1233 | 1249 | ||
| 1234 | LUA_API void *lua_newuserdata (lua_State *L, size_t size) { | 1250 | LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { |
| 1235 | Udata *u; | 1251 | Udata *u; |
| 1236 | lua_lock(L); | 1252 | lua_lock(L); |
| 1237 | u = luaS_newudata(L, size); | 1253 | api_check(L, 0 <= nuvalue && nuvalue < USHRT_MAX, "invalid value"); |
| 1254 | u = luaS_newudata(L, size, nuvalue); | ||
| 1238 | setuvalue(L, s2v(L->top), u); | 1255 | setuvalue(L, s2v(L->top), u); |
| 1239 | api_incr_top(L); | 1256 | api_incr_top(L); |
| 1240 | luaC_checkGC(L); | 1257 | luaC_checkGC(L); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldblib.c,v 1.151 2015/11/23 11:29:43 roberto Exp roberto $ | 2 | ** $Id: ldblib.c,v 1.152 2018/02/17 19:29:29 roberto Exp roberto $ |
| 3 | ** Interface from Lua to its debug API | 3 | ** Interface from Lua to its debug API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -64,19 +64,24 @@ static int db_setmetatable (lua_State *L) { | |||
| 64 | 64 | ||
| 65 | 65 | ||
| 66 | static int db_getuservalue (lua_State *L) { | 66 | static int db_getuservalue (lua_State *L) { |
| 67 | int n = luaL_optinteger(L, 2, 1); | ||
| 67 | if (lua_type(L, 1) != LUA_TUSERDATA) | 68 | if (lua_type(L, 1) != LUA_TUSERDATA) |
| 68 | lua_pushnil(L); | 69 | lua_pushnil(L); |
| 69 | else | 70 | else if (lua_getiuservalue(L, 1, n) != LUA_TNONE) { |
| 70 | lua_getuservalue(L, 1); | 71 | lua_pushboolean(L, 1); |
| 72 | return 2; | ||
| 73 | } | ||
| 71 | return 1; | 74 | return 1; |
| 72 | } | 75 | } |
| 73 | 76 | ||
| 74 | 77 | ||
| 75 | static int db_setuservalue (lua_State *L) { | 78 | static int db_setuservalue (lua_State *L) { |
| 79 | int n = luaL_optinteger(L, 3, 1); | ||
| 76 | luaL_checktype(L, 1, LUA_TUSERDATA); | 80 | luaL_checktype(L, 1, LUA_TUSERDATA); |
| 77 | luaL_checkany(L, 2); | 81 | luaL_checkany(L, 2); |
| 78 | lua_settop(L, 2); | 82 | lua_settop(L, 2); |
| 79 | lua_setuservalue(L, 1); | 83 | if (!lua_setiuservalue(L, 1, n)) |
| 84 | lua_pushnil(L); | ||
| 80 | return 1; | 85 | return 1; |
| 81 | } | 86 | } |
| 82 | 87 | ||
| @@ -113,6 +113,7 @@ static lu_mem atomic (lua_State *L); | |||
| 113 | static GCObject **getgclist (GCObject *o) { | 113 | static GCObject **getgclist (GCObject *o) { |
| 114 | switch (o->tt) { | 114 | switch (o->tt) { |
| 115 | case LUA_TTABLE: return &gco2t(o)->gclist; | 115 | case LUA_TTABLE: return &gco2t(o)->gclist; |
| 116 | case LUA_TUSERDATA: return &gco2u(o)->gclist; | ||
| 116 | case LUA_TLCL: return &gco2lcl(o)->gclist; | 117 | case LUA_TLCL: return &gco2lcl(o)->gclist; |
| 117 | case LUA_TCCL: return &gco2ccl(o)->gclist; | 118 | case LUA_TCCL: return &gco2ccl(o)->gclist; |
| 118 | case LUA_TTHREAD: return &gco2th(o)->gclist; | 119 | case LUA_TTHREAD: return &gco2th(o)->gclist; |
| @@ -269,7 +270,6 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { | |||
| 269 | ** to avoid barriers, as their values will be revisited by the thread.) | 270 | ** to avoid barriers, as their values will be revisited by the thread.) |
| 270 | */ | 271 | */ |
| 271 | static void reallymarkobject (global_State *g, GCObject *o) { | 272 | static void reallymarkobject (global_State *g, GCObject *o) { |
| 272 | reentry: | ||
| 273 | white2gray(o); | 273 | white2gray(o); |
| 274 | switch (o->tt) { | 274 | switch (o->tt) { |
| 275 | case LUA_TSHRSTR: | 275 | case LUA_TSHRSTR: |
| @@ -277,17 +277,6 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 277 | gray2black(o); | 277 | gray2black(o); |
| 278 | break; | 278 | break; |
| 279 | } | 279 | } |
| 280 | case LUA_TUSERDATA: { | ||
| 281 | TValue uvalue; | ||
| 282 | markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ | ||
| 283 | gray2black(o); | ||
| 284 | getuservalue(g->mainthread, gco2u(o), &uvalue); | ||
| 285 | if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ | ||
| 286 | o = gcvalue(&uvalue); | ||
| 287 | goto reentry; | ||
| 288 | } | ||
| 289 | break; | ||
| 290 | } | ||
| 291 | case LUA_TUPVAL: { | 280 | case LUA_TUPVAL: { |
| 292 | UpVal *uv = gco2upv(o); | 281 | UpVal *uv = gco2upv(o); |
| 293 | if (!upisopen(uv)) /* open upvalues are kept gray */ | 282 | if (!upisopen(uv)) /* open upvalues are kept gray */ |
| @@ -296,7 +285,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 296 | break; | 285 | break; |
| 297 | } | 286 | } |
| 298 | case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: | 287 | case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: |
| 299 | case LUA_TTHREAD: case LUA_TPROTO: { | 288 | case LUA_TUSERDATA: case LUA_TTHREAD: case LUA_TPROTO: { |
| 300 | linkobjgclist(o, g->gray); | 289 | linkobjgclist(o, g->gray); |
| 301 | break; | 290 | break; |
| 302 | } | 291 | } |
| @@ -602,6 +591,15 @@ static int traversethread (global_State *g, lua_State *th) { | |||
| 602 | } | 591 | } |
| 603 | 592 | ||
| 604 | 593 | ||
| 594 | static int traverseudata (global_State *g, Udata *u) { | ||
| 595 | int i; | ||
| 596 | markobjectN(g, u->metatable); /* mark its metatable */ | ||
| 597 | for (i = 0; i < u->nuvalue; i++) | ||
| 598 | markvalue(g, &u->uv[i].uv); | ||
| 599 | return 1 + u->nuvalue; | ||
| 600 | } | ||
| 601 | |||
| 602 | |||
| 605 | /* | 603 | /* |
| 606 | ** traverse one gray object, turning it to black (except for threads, | 604 | ** traverse one gray object, turning it to black (except for threads, |
| 607 | ** which are always gray). | 605 | ** which are always gray). |
| @@ -612,6 +610,7 @@ static lu_mem propagatemark (global_State *g) { | |||
| 612 | g->gray = *getgclist(o); /* remove from 'gray' list */ | 610 | g->gray = *getgclist(o); /* remove from 'gray' list */ |
| 613 | switch (o->tt) { | 611 | switch (o->tt) { |
| 614 | case LUA_TTABLE: return traversetable(g, gco2t(o)); | 612 | case LUA_TTABLE: return traversetable(g, gco2t(o)); |
| 613 | case LUA_TUSERDATA: return traverseudata(g, gco2u(o)); | ||
| 615 | case LUA_TLCL: return traverseLclosure(g, gco2lcl(o)); | 614 | case LUA_TLCL: return traverseLclosure(g, gco2lcl(o)); |
| 616 | case LUA_TCCL: return traverseCclosure(g, gco2ccl(o)); | 615 | case LUA_TCCL: return traverseCclosure(g, gco2ccl(o)); |
| 617 | case LUA_TPROTO: return traverseproto(g, gco2p(o)); | 616 | case LUA_TPROTO: return traverseproto(g, gco2p(o)); |
| @@ -742,9 +741,11 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
| 742 | case LUA_TTHREAD: | 741 | case LUA_TTHREAD: |
| 743 | luaE_freethread(L, gco2th(o)); | 742 | luaE_freethread(L, gco2th(o)); |
| 744 | break; | 743 | break; |
| 745 | case LUA_TUSERDATA: | 744 | case LUA_TUSERDATA: { |
| 746 | luaM_freemem(L, o, sizeudata(gco2u(o))); | 745 | Udata *u = gco2u(o); |
| 746 | luaM_freemem(L, o, sizeudata(u->nuvalue, u->len)); | ||
| 747 | break; | 747 | break; |
| 748 | } | ||
| 748 | case LUA_TSHRSTR: | 749 | case LUA_TSHRSTR: |
| 749 | luaS_remove(L, gco2ts(o)); /* remove it from hash table */ | 750 | luaS_remove(L, gco2ts(o)); /* remove it from hash table */ |
| 750 | luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); | 751 | luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); |
| @@ -1065,7 +1066,7 @@ static GCObject **correctgraylist (GCObject **p) { | |||
| 1065 | GCObject *curr; | 1066 | GCObject *curr; |
| 1066 | while ((curr = *p) != NULL) { | 1067 | while ((curr = *p) != NULL) { |
| 1067 | switch (curr->tt) { | 1068 | switch (curr->tt) { |
| 1068 | case LUA_TTABLE: { | 1069 | case LUA_TTABLE: case LUA_TUSERDATA: { |
| 1069 | GCObject **next = getgclist(curr); | 1070 | GCObject **next = getgclist(curr); |
| 1070 | if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ | 1071 | if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ |
| 1071 | lua_assert(isgray(curr)); | 1072 | lua_assert(isgray(curr)); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.132 2018/01/28 12:07:53 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.133 2018/01/28 15:13:26 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -365,47 +365,53 @@ typedef union UTString { | |||
| 365 | 365 | ||
| 366 | 366 | ||
| 367 | /* | 367 | /* |
| 368 | ** Header for userdata; memory area follows the end of this structure | 368 | ** {================================================================== |
| 369 | ** (aligned according to 'UUdata'; see next). | 369 | ** Userdata |
| 370 | ** =================================================================== | ||
| 371 | */ | ||
| 372 | |||
| 373 | /* Ensures that addresses after this type are always fully aligned. */ | ||
| 374 | typedef union UValue { | ||
| 375 | TValue uv; | ||
| 376 | LUAI_MAXALIGN; /* ensures maximum alignment for udata bytes */ | ||
| 377 | } UValue; | ||
| 378 | |||
| 379 | |||
| 380 | /* | ||
| 381 | ** Header for userdata; memory area follows the end of this structure. | ||
| 370 | */ | 382 | */ |
| 371 | typedef struct Udata { | 383 | typedef struct Udata { |
| 372 | CommonHeader; | 384 | CommonHeader; |
| 373 | lu_byte ttuv_; /* user value's tag */ | 385 | unsigned short nuvalue; /* number of user values */ |
| 374 | struct Table *metatable; | ||
| 375 | size_t len; /* number of bytes */ | 386 | size_t len; /* number of bytes */ |
| 376 | union Value user_; /* user value */ | 387 | struct Table *metatable; |
| 388 | GCObject *gclist; | ||
| 389 | UValue uv[1]; /* user values */ | ||
| 377 | } Udata; | 390 | } Udata; |
| 378 | 391 | ||
| 379 | 392 | ||
| 380 | /* | 393 | /* computes the offset of the memory area of a userdata */ |
| 381 | ** Ensures that address after this type is always fully aligned. | 394 | #define udatamemoffset(nuv) (sizeof(Udata) + (sizeof(UValue) * ((nuv) - 1))) |
| 382 | */ | ||
| 383 | typedef union UUdata { | ||
| 384 | LUAI_MAXALIGN; /* ensures maximum alignment for 'local' udata */ | ||
| 385 | Udata uv; | ||
| 386 | } UUdata; | ||
| 387 | |||
| 388 | 395 | ||
| 389 | /* | 396 | /* |
| 390 | ** Get the address of memory block inside 'Udata'. | 397 | ** Get the address of the memory block inside 'Udata'. |
| 391 | ** (Access to 'ttuv_' ensures that value is really a 'Udata'.) | ||
| 392 | */ | 398 | */ |
| 393 | #define getudatamem(u) \ | 399 | #define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue)) |
| 394 | check_exp(sizeof((u)->ttuv_), (cast_charp(u) + sizeof(UUdata))) | ||
| 395 | 400 | ||
| 396 | #define setuservalue(L,u,o) \ | 401 | /* computes the size of a userdata */ |
| 397 | { const TValue *io=(o); Udata *iu = (u); \ | 402 | #define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb)) |
| 398 | iu->user_ = io->value_; iu->ttuv_ = rttype(io); \ | ||
| 399 | checkliveness(L,io); } | ||
| 400 | 403 | ||
| 404 | /* }================================================================== */ | ||
| 401 | 405 | ||
| 402 | #define getuservalue(L,u,o) \ | ||
| 403 | { TValue *io=(o); const Udata *iu = (u); \ | ||
| 404 | io->value_ = iu->user_; settt_(io, iu->ttuv_); \ | ||
| 405 | checkliveness(L,io); } | ||
| 406 | 406 | ||
| 407 | 407 | ||
| 408 | /* | 408 | /* |
| 409 | ** {================================================================== | ||
| 410 | ** Prototypes | ||
| 411 | ** =================================================================== | ||
| 412 | */ | ||
| 413 | |||
| 414 | /* | ||
| 409 | ** Description of an upvalue for function prototypes | 415 | ** Description of an upvalue for function prototypes |
| 410 | */ | 416 | */ |
| 411 | typedef struct Upvaldesc { | 417 | typedef struct Upvaldesc { |
| @@ -471,6 +477,8 @@ typedef struct Proto { | |||
| 471 | GCObject *gclist; | 477 | GCObject *gclist; |
| 472 | } Proto; | 478 | } Proto; |
| 473 | 479 | ||
| 480 | /* }================================================================== */ | ||
| 481 | |||
| 474 | 482 | ||
| 475 | 483 | ||
| 476 | /* | 484 | /* |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 2.63 2018/01/28 15:13:26 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.64 2018/02/15 18:06:24 roberto Exp roberto $ |
| 3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -265,16 +265,19 @@ TString *luaS_new (lua_State *L, const char *str) { | |||
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | 267 | ||
| 268 | Udata *luaS_newudata (lua_State *L, size_t s) { | 268 | Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) { |
| 269 | Udata *u; | 269 | Udata *u; |
| 270 | int i; | ||
| 270 | GCObject *o; | 271 | GCObject *o; |
| 271 | if (s > MAX_SIZE - sizeof(Udata)) | 272 | if (s > MAX_SIZE - udatamemoffset(nuvalue)) |
| 272 | luaM_toobig(L); | 273 | luaM_toobig(L); |
| 273 | o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); | 274 | o = luaC_newobj(L, LUA_TUSERDATA, sizeudata(nuvalue, s)); |
| 274 | u = gco2u(o); | 275 | u = gco2u(o); |
| 275 | u->len = s; | 276 | u->len = s; |
| 277 | u->nuvalue = nuvalue; | ||
| 276 | u->metatable = NULL; | 278 | u->metatable = NULL; |
| 277 | setuservalue(L, u, luaO_nilobject); | 279 | for (i = 0; i < nuvalue; i++) |
| 280 | setnilvalue(&u->uv[i].uv); | ||
| 278 | return u; | 281 | return u; |
| 279 | } | 282 | } |
| 280 | 283 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.h,v 1.62 2017/07/27 13:50:16 roberto Exp roberto $ | 2 | ** $Id: lstring.h,v 1.63 2017/11/23 19:29:04 roberto Exp roberto $ |
| 3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -21,9 +21,6 @@ | |||
| 21 | 21 | ||
| 22 | #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) | 22 | #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) |
| 23 | 23 | ||
| 24 | #define sizeludata(l) (sizeof(union UUdata) + (l)) | ||
| 25 | #define sizeudata(u) sizeludata((u)->len) | ||
| 26 | |||
| 27 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ | 24 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ |
| 28 | (sizeof(s)/sizeof(char))-1)) | 25 | (sizeof(s)/sizeof(char))-1)) |
| 29 | 26 | ||
| @@ -47,7 +44,7 @@ LUAI_FUNC void luaS_resize (lua_State *L, int newsize); | |||
| 47 | LUAI_FUNC void luaS_clearcache (global_State *g); | 44 | LUAI_FUNC void luaS_clearcache (global_State *g); |
| 48 | LUAI_FUNC void luaS_init (lua_State *L); | 45 | LUAI_FUNC void luaS_init (lua_State *L); |
| 49 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); | 46 | LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); |
| 50 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); | 47 | LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue); |
| 51 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); | 48 | LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); |
| 52 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); | 49 | LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); |
| 53 | LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); | 50 | LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 2.239 2018/01/09 11:24:12 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.240 2018/01/28 15:13:26 roberto Exp roberto $ |
| 3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -265,6 +265,15 @@ static void checktable (global_State *g, Table *h) { | |||
| 265 | } | 265 | } |
| 266 | 266 | ||
| 267 | 267 | ||
| 268 | static void checkudata (global_State *g, Udata *u) { | ||
| 269 | int i; | ||
| 270 | GCObject *hgc = obj2gco(u); | ||
| 271 | checkobjref(g, hgc, u->metatable); | ||
| 272 | for (i = 0; i < u->nuvalue; i++) | ||
| 273 | checkvalref(g, hgc, &u->uv[i].uv); | ||
| 274 | } | ||
| 275 | |||
| 276 | |||
| 268 | /* | 277 | /* |
| 269 | ** All marks are conditional because a GC may happen while the | 278 | ** All marks are conditional because a GC may happen while the |
| 270 | ** prototype is still being created | 279 | ** prototype is still being created |
| @@ -287,7 +296,6 @@ static void checkproto (global_State *g, Proto *f) { | |||
| 287 | } | 296 | } |
| 288 | 297 | ||
| 289 | 298 | ||
| 290 | |||
| 291 | static void checkCclosure (global_State *g, CClosure *cl) { | 299 | static void checkCclosure (global_State *g, CClosure *cl) { |
| 292 | GCObject *clgc = obj2gco(cl); | 300 | GCObject *clgc = obj2gco(cl); |
| 293 | int i; | 301 | int i; |
| @@ -344,11 +352,7 @@ static void checkstack (global_State *g, lua_State *L1) { | |||
| 344 | static void checkrefs (global_State *g, GCObject *o) { | 352 | static void checkrefs (global_State *g, GCObject *o) { |
| 345 | switch (o->tt) { | 353 | switch (o->tt) { |
| 346 | case LUA_TUSERDATA: { | 354 | case LUA_TUSERDATA: { |
| 347 | TValue uservalue; | 355 | checkudata(g, gco2u(o)); |
| 348 | Table *mt = gco2u(o)->metatable; | ||
| 349 | checkobjref(g, o, mt); | ||
| 350 | getuservalue(g->mainthread, gco2u(o), &uservalue); | ||
| 351 | checkvalref(g, o, &uservalue); | ||
| 352 | break; | 356 | break; |
| 353 | } | 357 | } |
| 354 | case LUA_TUPVAL: { | 358 | case LUA_TUPVAL: { |
| @@ -728,7 +732,7 @@ static int gc_color (lua_State *L) { | |||
| 728 | GCObject *obj = gcvalue(o); | 732 | GCObject *obj = gcvalue(o); |
| 729 | lua_pushstring(L, isdead(G(L), obj) ? "dead" : | 733 | lua_pushstring(L, isdead(G(L), obj) ? "dead" : |
| 730 | iswhite(obj) ? "white" : | 734 | iswhite(obj) ? "white" : |
| 731 | isblack(obj) ? "black" : "grey"); | 735 | isblack(obj) ? "black" : "gray"); |
| 732 | } | 736 | } |
| 733 | return 1; | 737 | return 1; |
| 734 | } | 738 | } |
| @@ -919,8 +923,9 @@ static int upvalue (lua_State *L) { | |||
| 919 | 923 | ||
| 920 | 924 | ||
| 921 | static int newuserdata (lua_State *L) { | 925 | static int newuserdata (lua_State *L) { |
| 922 | size_t size = cast_sizet(luaL_checkinteger(L, 1)); | 926 | size_t size = cast_sizet(luaL_optinteger(L, 1, 0)); |
| 923 | char *p = cast_charp(lua_newuserdata(L, size)); | 927 | int nuv = luaL_optinteger(L, 2, 0); |
| 928 | char *p = cast_charp(lua_newuserdatauv(L, size, nuv)); | ||
| 924 | while (size--) *p++ = '\0'; | 929 | while (size--) *p++ = '\0'; |
| 925 | return 1; | 930 | return 1; |
| 926 | } | 931 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lua.h,v 1.339 2017/11/07 13:25:26 roberto Exp roberto $ | 2 | ** $Id: lua.h,v 1.340 2018/02/17 19:29:29 roberto Exp roberto $ |
| 3 | ** Lua - A Scripting Language | 3 | ** Lua - A Scripting Language |
| 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) | 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) |
| 5 | ** See Copyright Notice at the end of this file | 5 | ** See Copyright Notice at the end of this file |
| @@ -247,9 +247,9 @@ LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); | |||
| 247 | LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); | 247 | LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); |
| 248 | 248 | ||
| 249 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); | 249 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); |
| 250 | LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); | 250 | LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); |
| 251 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); | 251 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); |
| 252 | LUA_API int (lua_getuservalue) (lua_State *L, int idx); | 252 | LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n); |
| 253 | 253 | ||
| 254 | 254 | ||
| 255 | /* | 255 | /* |
| @@ -263,7 +263,7 @@ LUA_API void (lua_rawset) (lua_State *L, int idx); | |||
| 263 | LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); | 263 | LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); |
| 264 | LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); | 264 | LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); |
| 265 | LUA_API int (lua_setmetatable) (lua_State *L, int objindex); | 265 | LUA_API int (lua_setmetatable) (lua_State *L, int objindex); |
| 266 | LUA_API void (lua_setuservalue) (lua_State *L, int idx); | 266 | LUA_API int (lua_setiuservalue) (lua_State *L, int idx, int n); |
| 267 | 267 | ||
| 268 | 268 | ||
| 269 | /* | 269 | /* |
| @@ -380,7 +380,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | |||
| 380 | 380 | ||
| 381 | /* | 381 | /* |
| 382 | ** {============================================================== | 382 | ** {============================================================== |
| 383 | ** compatibility macros for unsigned conversions | 383 | ** compatibility macros |
| 384 | ** =============================================================== | 384 | ** =============================================================== |
| 385 | */ | 385 | */ |
| 386 | #if defined(LUA_COMPAT_APIINTCASTS) | 386 | #if defined(LUA_COMPAT_APIINTCASTS) |
| @@ -390,6 +390,11 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); | |||
| 390 | #define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) | 390 | #define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) |
| 391 | 391 | ||
| 392 | #endif | 392 | #endif |
| 393 | |||
| 394 | #define lua_newuserdata(L,s) lua_newuserdatauv(L,s,1) | ||
| 395 | #define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1) | ||
| 396 | #define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1) | ||
| 397 | |||
| 393 | /* }============================================================== */ | 398 | /* }============================================================== */ |
| 394 | 399 | ||
| 395 | /* | 400 | /* |
