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 | /* |