diff options
Diffstat (limited to 'src/lj_cdata.c')
-rw-r--r-- | src/lj_cdata.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/src/lj_cdata.c b/src/lj_cdata.c index 425e6bcf..01a74f5d 100644 --- a/src/lj_cdata.c +++ b/src/lj_cdata.c | |||
@@ -9,7 +9,6 @@ | |||
9 | 9 | ||
10 | #include "lj_gc.h" | 10 | #include "lj_gc.h" |
11 | #include "lj_err.h" | 11 | #include "lj_err.h" |
12 | #include "lj_str.h" | ||
13 | #include "lj_tab.h" | 12 | #include "lj_tab.h" |
14 | #include "lj_ctype.h" | 13 | #include "lj_ctype.h" |
15 | #include "lj_cconv.h" | 14 | #include "lj_cconv.h" |
@@ -27,20 +26,20 @@ GCcdata *lj_cdata_newref(CTState *cts, const void *p, CTypeID id) | |||
27 | } | 26 | } |
28 | 27 | ||
29 | /* Allocate variable-sized or specially aligned C data object. */ | 28 | /* Allocate variable-sized or specially aligned C data object. */ |
30 | GCcdata *lj_cdata_newv(CTState *cts, CTypeID id, CTSize sz, CTSize align) | 29 | GCcdata *lj_cdata_newv(lua_State *L, CTypeID id, CTSize sz, CTSize align) |
31 | { | 30 | { |
32 | global_State *g; | 31 | global_State *g; |
33 | MSize extra = sizeof(GCcdataVar) + sizeof(GCcdata) + | 32 | MSize extra = sizeof(GCcdataVar) + sizeof(GCcdata) + |
34 | (align > CT_MEMALIGN ? (1u<<align) - (1u<<CT_MEMALIGN) : 0); | 33 | (align > CT_MEMALIGN ? (1u<<align) - (1u<<CT_MEMALIGN) : 0); |
35 | char *p = lj_mem_newt(cts->L, extra + sz, char); | 34 | char *p = lj_mem_newt(L, extra + sz, char); |
36 | uintptr_t adata = (uintptr_t)p + sizeof(GCcdataVar) + sizeof(GCcdata); | 35 | uintptr_t adata = (uintptr_t)p + sizeof(GCcdataVar) + sizeof(GCcdata); |
37 | uintptr_t almask = (1u << align) - 1u; | 36 | uintptr_t almask = (1u << align) - 1u; |
38 | GCcdata *cd = (GCcdata *)(((adata + almask) & ~almask) - sizeof(GCcdata)); | 37 | GCcdata *cd = (GCcdata *)(((adata + almask) & ~almask) - sizeof(GCcdata)); |
39 | lua_assert((char *)cd - p < 65536); | 38 | lj_assertL((char *)cd - p < 65536, "excessive cdata alignment"); |
40 | cdatav(cd)->offset = (uint16_t)((char *)cd - p); | 39 | cdatav(cd)->offset = (uint16_t)((char *)cd - p); |
41 | cdatav(cd)->extra = extra; | 40 | cdatav(cd)->extra = extra; |
42 | cdatav(cd)->len = sz; | 41 | cdatav(cd)->len = sz; |
43 | g = cts->g; | 42 | g = G(L); |
44 | setgcrefr(cd->nextgc, g->gc.root); | 43 | setgcrefr(cd->nextgc, g->gc.root); |
45 | setgcref(g->gc.root, obj2gco(cd)); | 44 | setgcref(g->gc.root, obj2gco(cd)); |
46 | newwhite(g, obj2gco(cd)); | 45 | newwhite(g, obj2gco(cd)); |
@@ -50,6 +49,15 @@ GCcdata *lj_cdata_newv(CTState *cts, CTypeID id, CTSize sz, CTSize align) | |||
50 | return cd; | 49 | return cd; |
51 | } | 50 | } |
52 | 51 | ||
52 | /* Allocate arbitrary C data object. */ | ||
53 | GCcdata *lj_cdata_newx(CTState *cts, CTypeID id, CTSize sz, CTInfo info) | ||
54 | { | ||
55 | if (!(info & CTF_VLA) && ctype_align(info) <= CT_MEMALIGN) | ||
56 | return lj_cdata_new(cts, id, sz); | ||
57 | else | ||
58 | return lj_cdata_newv(cts->L, id, sz, ctype_align(info)); | ||
59 | } | ||
60 | |||
53 | /* Free a C data object. */ | 61 | /* Free a C data object. */ |
54 | void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd) | 62 | void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd) |
55 | { | 63 | { |
@@ -68,29 +76,30 @@ void LJ_FASTCALL lj_cdata_free(global_State *g, GCcdata *cd) | |||
68 | } else if (LJ_LIKELY(!cdataisv(cd))) { | 76 | } else if (LJ_LIKELY(!cdataisv(cd))) { |
69 | CType *ct = ctype_raw(ctype_ctsG(g), cd->ctypeid); | 77 | CType *ct = ctype_raw(ctype_ctsG(g), cd->ctypeid); |
70 | CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR; | 78 | CTSize sz = ctype_hassize(ct->info) ? ct->size : CTSIZE_PTR; |
71 | lua_assert(ctype_hassize(ct->info) || ctype_isfunc(ct->info) || | 79 | lj_assertG(ctype_hassize(ct->info) || ctype_isfunc(ct->info) || |
72 | ctype_isextern(ct->info)); | 80 | ctype_isextern(ct->info), "free of ctype without a size"); |
73 | lj_mem_free(g, cd, sizeof(GCcdata) + sz); | 81 | lj_mem_free(g, cd, sizeof(GCcdata) + sz); |
74 | } else { | 82 | } else { |
75 | lj_mem_free(g, memcdatav(cd), sizecdatav(cd)); | 83 | lj_mem_free(g, memcdatav(cd), sizecdatav(cd)); |
76 | } | 84 | } |
77 | } | 85 | } |
78 | 86 | ||
79 | TValue * LJ_FASTCALL lj_cdata_setfin(lua_State *L, GCcdata *cd) | 87 | void lj_cdata_setfin(lua_State *L, GCcdata *cd, GCobj *obj, uint32_t it) |
80 | { | 88 | { |
81 | global_State *g = G(L); | 89 | GCtab *t = ctype_ctsG(G(L))->finalizer; |
82 | GCtab *t = ctype_ctsG(g)->finalizer; | ||
83 | if (gcref(t->metatable)) { | 90 | if (gcref(t->metatable)) { |
84 | /* Add cdata to finalizer table, if still enabled. */ | 91 | /* Add cdata to finalizer table, if still enabled. */ |
85 | TValue *tv, tmp; | 92 | TValue *tv, tmp; |
86 | setcdataV(L, &tmp, cd); | 93 | setcdataV(L, &tmp, cd); |
87 | lj_gc_anybarriert(L, t); | 94 | lj_gc_anybarriert(L, t); |
88 | tv = lj_tab_set(L, t, &tmp); | 95 | tv = lj_tab_set(L, t, &tmp); |
89 | cd->marked |= LJ_GC_CDATA_FIN; | 96 | if (it == LJ_TNIL) { |
90 | return tv; | 97 | setnilV(tv); |
91 | } else { | 98 | cd->marked &= ~LJ_GC_CDATA_FIN; |
92 | /* Otherwise return dummy TValue. */ | 99 | } else { |
93 | return &g->tmptv; | 100 | setgcV(L, tv, obj, it); |
101 | cd->marked |= LJ_GC_CDATA_FIN; | ||
102 | } | ||
94 | } | 103 | } |
95 | } | 104 | } |
96 | 105 | ||
@@ -106,7 +115,7 @@ CType *lj_cdata_index(CTState *cts, GCcdata *cd, cTValue *key, uint8_t **pp, | |||
106 | 115 | ||
107 | /* Resolve reference for cdata object. */ | 116 | /* Resolve reference for cdata object. */ |
108 | if (ctype_isref(ct->info)) { | 117 | if (ctype_isref(ct->info)) { |
109 | lua_assert(ct->size == CTSIZE_PTR); | 118 | lj_assertCTS(ct->size == CTSIZE_PTR, "ref is not pointer-sized"); |
110 | p = *(uint8_t **)p; | 119 | p = *(uint8_t **)p; |
111 | ct = ctype_child(cts, ct); | 120 | ct = ctype_child(cts, ct); |
112 | } | 121 | } |
@@ -117,13 +126,19 @@ collect_attrib: | |||
117 | if (ctype_attrib(ct->info) == CTA_QUAL) *qual |= ct->size; | 126 | if (ctype_attrib(ct->info) == CTA_QUAL) *qual |= ct->size; |
118 | ct = ctype_child(cts, ct); | 127 | ct = ctype_child(cts, ct); |
119 | } | 128 | } |
120 | lua_assert(!ctype_isref(ct->info)); /* Interning rejects refs to refs. */ | 129 | /* Interning rejects refs to refs. */ |
130 | lj_assertCTS(!ctype_isref(ct->info), "bad ref of ref"); | ||
121 | 131 | ||
122 | if (tvisint(key)) { | 132 | if (tvisint(key)) { |
123 | idx = (ptrdiff_t)intV(key); | 133 | idx = (ptrdiff_t)intV(key); |
124 | goto integer_key; | 134 | goto integer_key; |
125 | } else if (tvisnum(key)) { /* Numeric key. */ | 135 | } else if (tvisnum(key)) { /* Numeric key. */ |
126 | idx = LJ_64 ? (ptrdiff_t)numV(key) : (ptrdiff_t)lj_num2int(numV(key)); | 136 | #ifdef _MSC_VER |
137 | /* Workaround for MSVC bug. */ | ||
138 | volatile | ||
139 | #endif | ||
140 | lua_Number n = numV(key); | ||
141 | idx = LJ_64 ? (ptrdiff_t)n : (ptrdiff_t)lj_num2int(n); | ||
127 | integer_key: | 142 | integer_key: |
128 | if (ctype_ispointer(ct->info)) { | 143 | if (ctype_ispointer(ct->info)) { |
129 | CTSize sz = lj_ctype_size(cts, ctype_cid(ct->info)); /* Element size. */ | 144 | CTSize sz = lj_ctype_size(cts, ctype_cid(ct->info)); /* Element size. */ |
@@ -198,7 +213,8 @@ collect_attrib: | |||
198 | static void cdata_getconst(CTState *cts, TValue *o, CType *ct) | 213 | static void cdata_getconst(CTState *cts, TValue *o, CType *ct) |
199 | { | 214 | { |
200 | CType *ctt = ctype_child(cts, ct); | 215 | CType *ctt = ctype_child(cts, ct); |
201 | lua_assert(ctype_isinteger(ctt->info) && ctt->size <= 4); | 216 | lj_assertCTS(ctype_isinteger(ctt->info) && ctt->size <= 4, |
217 | "only 32 bit const supported"); /* NYI */ | ||
202 | /* Constants are already zero-extended/sign-extended to 32 bits. */ | 218 | /* Constants are already zero-extended/sign-extended to 32 bits. */ |
203 | if ((ctt->info & CTF_UNSIGNED) && (int32_t)ct->size < 0) | 219 | if ((ctt->info & CTF_UNSIGNED) && (int32_t)ct->size < 0) |
204 | setnumV(o, (lua_Number)(uint32_t)ct->size); | 220 | setnumV(o, (lua_Number)(uint32_t)ct->size); |
@@ -219,13 +235,14 @@ int lj_cdata_get(CTState *cts, CType *s, TValue *o, uint8_t *sp) | |||
219 | } | 235 | } |
220 | 236 | ||
221 | /* Get child type of pointer/array/field. */ | 237 | /* Get child type of pointer/array/field. */ |
222 | lua_assert(ctype_ispointer(s->info) || ctype_isfield(s->info)); | 238 | lj_assertCTS(ctype_ispointer(s->info) || ctype_isfield(s->info), |
239 | "pointer or field expected"); | ||
223 | sid = ctype_cid(s->info); | 240 | sid = ctype_cid(s->info); |
224 | s = ctype_get(cts, sid); | 241 | s = ctype_get(cts, sid); |
225 | 242 | ||
226 | /* Resolve reference for field. */ | 243 | /* Resolve reference for field. */ |
227 | if (ctype_isref(s->info)) { | 244 | if (ctype_isref(s->info)) { |
228 | lua_assert(s->size == CTSIZE_PTR); | 245 | lj_assertCTS(s->size == CTSIZE_PTR, "ref is not pointer-sized"); |
229 | sp = *(uint8_t **)sp; | 246 | sp = *(uint8_t **)sp; |
230 | sid = ctype_cid(s->info); | 247 | sid = ctype_cid(s->info); |
231 | s = ctype_get(cts, sid); | 248 | s = ctype_get(cts, sid); |
@@ -252,12 +269,13 @@ void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o, CTInfo qual) | |||
252 | } | 269 | } |
253 | 270 | ||
254 | /* Get child type of pointer/array/field. */ | 271 | /* Get child type of pointer/array/field. */ |
255 | lua_assert(ctype_ispointer(d->info) || ctype_isfield(d->info)); | 272 | lj_assertCTS(ctype_ispointer(d->info) || ctype_isfield(d->info), |
273 | "pointer or field expected"); | ||
256 | d = ctype_child(cts, d); | 274 | d = ctype_child(cts, d); |
257 | 275 | ||
258 | /* Resolve reference for field. */ | 276 | /* Resolve reference for field. */ |
259 | if (ctype_isref(d->info)) { | 277 | if (ctype_isref(d->info)) { |
260 | lua_assert(d->size == CTSIZE_PTR); | 278 | lj_assertCTS(d->size == CTSIZE_PTR, "ref is not pointer-sized"); |
261 | dp = *(uint8_t **)dp; | 279 | dp = *(uint8_t **)dp; |
262 | d = ctype_child(cts, d); | 280 | d = ctype_child(cts, d); |
263 | } | 281 | } |
@@ -272,7 +290,8 @@ void lj_cdata_set(CTState *cts, CType *d, uint8_t *dp, TValue *o, CTInfo qual) | |||
272 | d = ctype_child(cts, d); | 290 | d = ctype_child(cts, d); |
273 | } | 291 | } |
274 | 292 | ||
275 | lua_assert(ctype_hassize(d->info) && !ctype_isvoid(d->info)); | 293 | lj_assertCTS(ctype_hassize(d->info), "store to ctype without size"); |
294 | lj_assertCTS(!ctype_isvoid(d->info), "store to void type"); | ||
276 | 295 | ||
277 | if (((d->info|qual) & CTF_CONST)) { | 296 | if (((d->info|qual) & CTF_CONST)) { |
278 | err_const: | 297 | err_const: |