3 ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
17 /* -- C data allocation --------------------------------------------------- */
19 /* Allocate a new C data object holding a reference to another object. */
20 GCcdata
*lj_cdata_newref(CTState
*cts
, const void *p
, CTypeID id
)
22 CTypeID refid
= lj_ctype_intern(cts
, CTINFO_REF(id
), CTSIZE_PTR
);
23 GCcdata
*cd
= lj_cdata_new(cts
, refid
, CTSIZE_PTR
);
24 *(const void **)cdataptr(cd
) = p
;
28 /* Allocate variable-sized or specially aligned C data object. */
29 GCcdata
*lj_cdata_newv(lua_State
*L
, CTypeID id
, CTSize sz
, CTSize align
)
32 MSize extra
= sizeof(GCcdataVar
) + sizeof(GCcdata
) +
33 (align
> CT_MEMALIGN
? (1u<<align
) - (1u<<CT_MEMALIGN
) : 0);
34 char *p
= lj_mem_newt(L
, extra
+ sz
, char);
35 uintptr_t adata
= (uintptr_t)p
+ sizeof(GCcdataVar
) + sizeof(GCcdata
);
36 uintptr_t almask
= (1u << align
) - 1u;
37 GCcdata
*cd
= (GCcdata
*)(((adata
+ almask
) & ~almask
) - sizeof(GCcdata
));
38 lua_assert((char *)cd
- p
< 65536);
39 cdatav(cd
)->offset
= (uint16_t)((char *)cd
- p
);
40 cdatav(cd
)->extra
= extra
;
43 setgcrefr(cd
->nextgc
, g
->gc
.root
);
44 setgcref(g
->gc
.root
, obj2gco(cd
));
45 newwhite(g
, obj2gco(cd
));
52 /* Free a C data object. */
53 void LJ_FASTCALL
lj_cdata_free(global_State
*g
, GCcdata
*cd
)
55 if (LJ_UNLIKELY(cd
->marked
& LJ_GC_CDATA_FIN
)) {
57 makewhite(g
, obj2gco(cd
));
58 markfinalized(obj2gco(cd
));
59 if ((root
= gcref(g
->gc
.mmudata
)) != NULL
) {
60 setgcrefr(cd
->nextgc
, root
->gch
.nextgc
);
61 setgcref(root
->gch
.nextgc
, obj2gco(cd
));
62 setgcref(g
->gc
.mmudata
, obj2gco(cd
));
64 setgcref(cd
->nextgc
, obj2gco(cd
));
65 setgcref(g
->gc
.mmudata
, obj2gco(cd
));
67 } else if (LJ_LIKELY(!cdataisv(cd
))) {
68 CType
*ct
= ctype_raw(ctype_ctsG(g
), cd
->ctypeid
);
69 CTSize sz
= ctype_hassize(ct
->info
) ? ct
->size
: CTSIZE_PTR
;
70 lua_assert(ctype_hassize(ct
->info
) || ctype_isfunc(ct
->info
) ||
71 ctype_isextern(ct
->info
));
72 lj_mem_free(g
, cd
, sizeof(GCcdata
) + sz
);
74 lj_mem_free(g
, memcdatav(cd
), sizecdatav(cd
));
78 void lj_cdata_setfin(lua_State
*L
, GCcdata
*cd
, GCobj
*obj
, uint32_t it
)
80 GCtab
*t
= ctype_ctsG(G(L
))->finalizer
;
81 if (gcref(t
->metatable
)) {
82 /* Add cdata to finalizer table, if still enabled. */
84 setcdataV(L
, &tmp
, cd
);
85 lj_gc_anybarriert(L
, t
);
86 tv
= lj_tab_set(L
, t
, &tmp
);
87 setgcV(L
, tv
, obj
, it
);
89 cd
->marked
|= LJ_GC_CDATA_FIN
;
91 cd
->marked
&= ~LJ_GC_CDATA_FIN
;
95 /* -- C data indexing ----------------------------------------------------- */
97 /* Index C data by a TValue. Return CType and pointer. */
98 CType
*lj_cdata_index(CTState
*cts
, GCcdata
*cd
, cTValue
*key
, uint8_t **pp
,
101 uint8_t *p
= (uint8_t *)cdataptr(cd
);
102 CType
*ct
= ctype_get(cts
, cd
->ctypeid
);
105 /* Resolve reference for cdata object. */
106 if (ctype_isref(ct
->info
)) {
107 lua_assert(ct
->size
== CTSIZE_PTR
);
109 ct
= ctype_child(cts
, ct
);
113 /* Skip attributes and collect qualifiers. */
114 while (ctype_isattrib(ct
->info
)) {
115 if (ctype_attrib(ct
->info
) == CTA_QUAL
) *qual
|= ct
->size
;
116 ct
= ctype_child(cts
, ct
);
118 lua_assert(!ctype_isref(ct
->info
)); /* Interning rejects refs to refs. */
121 idx
= (ptrdiff_t)intV(key
);
123 } else if (tvisnum(key
)) { /* Numeric key. */
124 idx
= LJ_64
? (ptrdiff_t)numV(key
) : (ptrdiff_t)lj_num2int(numV(key
));
126 if (ctype_ispointer(ct
->info
)) {
127 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ct
->info
)); /* Element size. */
128 if (sz
== CTSIZE_INVALID
)
129 lj_err_caller(cts
->L
, LJ_ERR_FFI_INVSIZE
);
130 if (ctype_isptr(ct
->info
)) {
131 p
= (uint8_t *)cdata_getptr(p
, ct
->size
);
132 } else if ((ct
->info
& (CTF_VECTOR
|CTF_COMPLEX
))) {
133 if ((ct
->info
& CTF_COMPLEX
)) idx
&= 1;
134 *qual
|= CTF_CONST
; /* Valarray elements are constant. */
136 *pp
= p
+ idx
*(int32_t)sz
;
139 } else if (tviscdata(key
)) { /* Integer cdata key. */
140 GCcdata
*cdk
= cdataV(key
);
141 CType
*ctk
= ctype_raw(cts
, cdk
->ctypeid
);
142 if (ctype_isenum(ctk
->info
)) ctk
= ctype_child(cts
, ctk
);
143 if (ctype_isinteger(ctk
->info
)) {
144 lj_cconv_ct_ct(cts
, ctype_get(cts
, CTID_INT_PSZ
), ctk
,
145 (uint8_t *)&idx
, cdataptr(cdk
), 0);
148 } else if (tvisstr(key
)) { /* String key. */
149 GCstr
*name
= strV(key
);
150 if (ctype_isstruct(ct
->info
)) {
152 CType
*fct
= lj_ctype_getfieldq(cts
, ct
, name
, &ofs
, qual
);
157 } else if (ctype_iscomplex(ct
->info
)) {
158 if (name
->len
== 2) {
159 *qual
|= CTF_CONST
; /* Complex fields are constant. */
160 if (strdata(name
)[0] == 'r' && strdata(name
)[1] == 'e') {
163 } else if (strdata(name
)[0] == 'i' && strdata(name
)[1] == 'm') {
164 *pp
= p
+ (ct
->size
>> 1);
168 } else if (cd
->ctypeid
== CTID_CTYPEID
) {
169 /* Allow indexing a (pointer to) struct constructor to get constants. */
170 CType
*sct
= ctype_raw(cts
, *(CTypeID
*)p
);
171 if (ctype_isptr(sct
->info
))
172 sct
= ctype_rawchild(cts
, sct
);
173 if (ctype_isstruct(sct
->info
)) {
175 CType
*fct
= lj_ctype_getfield(cts
, sct
, name
, &ofs
);
176 if (fct
&& ctype_isconstval(fct
->info
))
179 ct
= sct
; /* Allow resolving metamethods for constructors, too. */
182 if (ctype_isptr(ct
->info
)) { /* Automatically perform '->'. */
183 if (ctype_isstruct(ctype_rawchild(cts
, ct
)->info
)) {
184 p
= (uint8_t *)cdata_getptr(p
, ct
->size
);
185 ct
= ctype_child(cts
, ct
);
189 *qual
|= 1; /* Lookup failed. */
190 return ct
; /* But return the resolved raw type. */
193 /* -- C data getters ------------------------------------------------------ */
195 /* Get constant value and convert to TValue. */
196 static void cdata_getconst(CTState
*cts
, TValue
*o
, CType
*ct
)
198 CType
*ctt
= ctype_child(cts
, ct
);
199 lua_assert(ctype_isinteger(ctt
->info
) && ctt
->size
<= 4);
200 /* Constants are already zero-extended/sign-extended to 32 bits. */
201 if ((ctt
->info
& CTF_UNSIGNED
) && (int32_t)ct
->size
< 0)
202 setnumV(o
, (lua_Number
)(uint32_t)ct
->size
);
204 setintV(o
, (int32_t)ct
->size
);
207 /* Get C data value and convert to TValue. */
208 int lj_cdata_get(CTState
*cts
, CType
*s
, TValue
*o
, uint8_t *sp
)
212 if (ctype_isconstval(s
->info
)) {
213 cdata_getconst(cts
, o
, s
);
214 return 0; /* No GC step needed. */
215 } else if (ctype_isbitfield(s
->info
)) {
216 return lj_cconv_tv_bf(cts
, s
, o
, sp
);
219 /* Get child type of pointer/array/field. */
220 lua_assert(ctype_ispointer(s
->info
) || ctype_isfield(s
->info
));
221 sid
= ctype_cid(s
->info
);
222 s
= ctype_get(cts
, sid
);
224 /* Resolve reference for field. */
225 if (ctype_isref(s
->info
)) {
226 lua_assert(s
->size
== CTSIZE_PTR
);
227 sp
= *(uint8_t **)sp
;
228 sid
= ctype_cid(s
->info
);
229 s
= ctype_get(cts
, sid
);
232 /* Skip attributes. */
233 while (ctype_isattrib(s
->info
))
234 s
= ctype_child(cts
, s
);
236 return lj_cconv_tv_ct(cts
, s
, sid
, o
, sp
);
239 /* -- C data setters ------------------------------------------------------ */
241 /* Convert TValue and set C data value. */
242 void lj_cdata_set(CTState
*cts
, CType
*d
, uint8_t *dp
, TValue
*o
, CTInfo qual
)
244 if (ctype_isconstval(d
->info
)) {
246 } else if (ctype_isbitfield(d
->info
)) {
247 if (((d
->info
|qual
) & CTF_CONST
)) goto err_const
;
248 lj_cconv_bf_tv(cts
, d
, dp
, o
);
252 /* Get child type of pointer/array/field. */
253 lua_assert(ctype_ispointer(d
->info
) || ctype_isfield(d
->info
));
254 d
= ctype_child(cts
, d
);
256 /* Resolve reference for field. */
257 if (ctype_isref(d
->info
)) {
258 lua_assert(d
->size
== CTSIZE_PTR
);
259 dp
= *(uint8_t **)dp
;
260 d
= ctype_child(cts
, d
);
263 /* Skip attributes and collect qualifiers. */
265 if (ctype_isattrib(d
->info
)) {
266 if (ctype_attrib(d
->info
) == CTA_QUAL
) qual
|= d
->size
;
270 d
= ctype_child(cts
, d
);
273 lua_assert(ctype_hassize(d
->info
) && !ctype_isvoid(d
->info
));
275 if (((d
->info
|qual
) & CTF_CONST
)) {
277 lj_err_caller(cts
->L
, LJ_ERR_FFI_WRCONST
);
280 lj_cconv_ct_tv(cts
, d
, dp
, o
, 0);