3 ** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h
18 /* -- C data allocation --------------------------------------------------- */
20 /* Allocate a new C data object holding a reference to another object. */
21 GCcdata
*lj_cdata_newref(CTState
*cts
, const void *p
, CTypeID id
)
23 CTypeID refid
= lj_ctype_intern(cts
, CTINFO_REF(id
), CTSIZE_PTR
);
24 GCcdata
*cd
= lj_cdata_new(cts
, refid
, CTSIZE_PTR
);
25 *(const void **)cdataptr(cd
) = p
;
29 /* Allocate variable-sized or specially aligned C data object. */
30 GCcdata
*lj_cdata_newv(CTState
*cts
, CTypeID id
, CTSize sz
, CTSize align
)
33 MSize extra
= sizeof(GCcdataVar
) + sizeof(GCcdata
) +
34 (align
> CT_MEMALIGN
? (1u<<align
) - (1u<<CT_MEMALIGN
) : 0);
35 char *p
= lj_mem_newt(cts
->L
, extra
+ sz
, char);
36 uintptr_t adata
= (uintptr_t)p
+ sizeof(GCcdataVar
) + sizeof(GCcdata
);
37 uintptr_t almask
= (1u << align
) - 1u;
38 GCcdata
*cd
= (GCcdata
*)(((adata
+ almask
) & ~almask
) - sizeof(GCcdata
));
39 lua_assert((char *)cd
- p
< 65536);
40 cdatav(cd
)->offset
= (uint16_t)((char *)cd
- p
);
41 cdatav(cd
)->extra
= extra
;
44 setgcrefr(cd
->nextgc
, g
->gc
.root
);
45 setgcref(g
->gc
.root
, obj2gco(cd
));
46 newwhite(g
, obj2gco(cd
));
53 /* Free a C data object. */
54 void LJ_FASTCALL
lj_cdata_free(global_State
*g
, GCcdata
*cd
)
56 if (LJ_UNLIKELY(cd
->marked
& LJ_GC_CDATA_FIN
)) {
58 makewhite(g
, obj2gco(cd
));
59 markfinalized(obj2gco(cd
));
60 if ((root
= gcref(g
->gc
.mmudata
)) != NULL
) {
61 setgcrefr(cd
->nextgc
, root
->gch
.nextgc
);
62 setgcref(root
->gch
.nextgc
, obj2gco(cd
));
63 setgcref(g
->gc
.mmudata
, obj2gco(cd
));
65 setgcref(cd
->nextgc
, obj2gco(cd
));
66 setgcref(g
->gc
.mmudata
, obj2gco(cd
));
68 } else if (LJ_LIKELY(!cdataisv(cd
))) {
69 CType
*ct
= ctype_raw(ctype_ctsG(g
), cd
->ctypeid
);
70 CTSize sz
= ctype_hassize(ct
->info
) ? ct
->size
: CTSIZE_PTR
;
71 lua_assert(ctype_hassize(ct
->info
) || ctype_isfunc(ct
->info
) ||
72 ctype_isextern(ct
->info
));
73 lj_mem_free(g
, cd
, sizeof(GCcdata
) + sz
);
75 lj_mem_free(g
, memcdatav(cd
), sizecdatav(cd
));
79 TValue
* LJ_FASTCALL
lj_cdata_setfin(lua_State
*L
, GCcdata
*cd
)
81 global_State
*g
= G(L
);
82 GCtab
*t
= ctype_ctsG(g
)->finalizer
;
83 if (gcref(t
->metatable
)) {
84 /* Add cdata to finalizer table, if still enabled. */
86 setcdataV(L
, &tmp
, cd
);
87 lj_gc_anybarriert(L
, t
);
88 tv
= lj_tab_set(L
, t
, &tmp
);
89 cd
->marked
|= LJ_GC_CDATA_FIN
;
92 /* Otherwise return dummy TValue. */
97 /* -- C data indexing ----------------------------------------------------- */
99 /* Index C data by a TValue. Return CType and pointer. */
100 CType
*lj_cdata_index(CTState
*cts
, GCcdata
*cd
, cTValue
*key
, uint8_t **pp
,
103 uint8_t *p
= (uint8_t *)cdataptr(cd
);
104 CType
*ct
= ctype_get(cts
, cd
->ctypeid
);
107 /* Resolve reference for cdata object. */
108 if (ctype_isref(ct
->info
)) {
109 lua_assert(ct
->size
== CTSIZE_PTR
);
111 ct
= ctype_child(cts
, ct
);
115 /* Skip attributes and collect qualifiers. */
116 while (ctype_isattrib(ct
->info
)) {
117 if (ctype_attrib(ct
->info
) == CTA_QUAL
) *qual
|= ct
->size
;
118 ct
= ctype_child(cts
, ct
);
120 lua_assert(!ctype_isref(ct
->info
)); /* Interning rejects refs to refs. */
123 idx
= (ptrdiff_t)intV(key
);
125 } else if (tvisnum(key
)) { /* Numeric key. */
126 idx
= LJ_64
? (ptrdiff_t)numV(key
) : (ptrdiff_t)lj_num2int(numV(key
));
128 if (ctype_ispointer(ct
->info
)) {
129 CTSize sz
= lj_ctype_size(cts
, ctype_cid(ct
->info
)); /* Element size. */
130 if (sz
!= CTSIZE_INVALID
) {
131 if (ctype_isptr(ct
->info
)) {
132 p
= (uint8_t *)cdata_getptr(p
, ct
->size
);
133 } else if ((ct
->info
& (CTF_VECTOR
|CTF_COMPLEX
))) {
134 if ((ct
->info
& CTF_COMPLEX
)) idx
&= 1;
135 *qual
|= CTF_CONST
; /* Valarray elements are constant. */
137 *pp
= p
+ idx
*(int32_t)sz
;
141 } else if (tviscdata(key
)) { /* Integer cdata key. */
142 GCcdata
*cdk
= cdataV(key
);
143 CType
*ctk
= ctype_raw(cts
, cdk
->ctypeid
);
144 if (ctype_isenum(ctk
->info
)) ctk
= ctype_child(cts
, ctk
);
145 if (ctype_isinteger(ctk
->info
)) {
146 lj_cconv_ct_ct(cts
, ctype_get(cts
, CTID_INT_PSZ
), ctk
,
147 (uint8_t *)&idx
, cdataptr(cdk
), 0);
150 } else if (tvisstr(key
)) { /* String key. */
151 GCstr
*name
= strV(key
);
152 if (ctype_isstruct(ct
->info
)) {
154 CType
*fct
= lj_ctype_getfieldq(cts
, ct
, name
, &ofs
, qual
);
159 } else if (ctype_iscomplex(ct
->info
)) {
160 if (name
->len
== 2) {
161 *qual
|= CTF_CONST
; /* Complex fields are constant. */
162 if (strdata(name
)[0] == 'r' && strdata(name
)[1] == 'e') {
165 } else if (strdata(name
)[0] == 'i' && strdata(name
)[1] == 'm') {
166 *pp
= p
+ (ct
->size
>> 1);
170 } else if (cd
->ctypeid
== CTID_CTYPEID
) {
171 /* Allow indexing a (pointer to) struct constructor to get constants. */
172 CType
*sct
= ctype_raw(cts
, *(CTypeID
*)p
);
173 if (ctype_isptr(sct
->info
))
174 sct
= ctype_rawchild(cts
, sct
);
175 if (ctype_isstruct(sct
->info
)) {
177 CType
*fct
= lj_ctype_getfield(cts
, sct
, name
, &ofs
);
178 if (fct
&& ctype_isconstval(fct
->info
))
181 ct
= sct
; /* Allow resolving metamethods for constructors, too. */
184 if (ctype_isptr(ct
->info
)) { /* Automatically perform '->'. */
185 if (ctype_isstruct(ctype_rawchild(cts
, ct
)->info
)) {
186 p
= (uint8_t *)cdata_getptr(p
, ct
->size
);
187 ct
= ctype_child(cts
, ct
);
191 *qual
|= 1; /* Lookup failed. */
192 return ct
; /* But return the resolved raw type. */
195 /* -- C data getters ------------------------------------------------------ */
197 /* Get constant value and convert to TValue. */
198 static void cdata_getconst(CTState
*cts
, TValue
*o
, CType
*ct
)
200 CType
*ctt
= ctype_child(cts
, ct
);
201 lua_assert(ctype_isinteger(ctt
->info
) && ctt
->size
<= 4);
202 /* Constants are already zero-extended/sign-extended to 32 bits. */
203 if ((ctt
->info
& CTF_UNSIGNED
) && (int32_t)ct
->size
< 0)
204 setnumV(o
, (lua_Number
)(uint32_t)ct
->size
);
206 setintV(o
, (int32_t)ct
->size
);
209 /* Get C data value and convert to TValue. */
210 int lj_cdata_get(CTState
*cts
, CType
*s
, TValue
*o
, uint8_t *sp
)
214 if (ctype_isconstval(s
->info
)) {
215 cdata_getconst(cts
, o
, s
);
216 return 0; /* No GC step needed. */
217 } else if (ctype_isbitfield(s
->info
)) {
218 return lj_cconv_tv_bf(cts
, s
, o
, sp
);
221 /* Get child type of pointer/array/field. */
222 lua_assert(ctype_ispointer(s
->info
) || ctype_isfield(s
->info
));
223 sid
= ctype_cid(s
->info
);
224 s
= ctype_get(cts
, sid
);
226 /* Resolve reference for field. */
227 if (ctype_isref(s
->info
)) {
228 lua_assert(s
->size
== CTSIZE_PTR
);
229 sp
= *(uint8_t **)sp
;
230 sid
= ctype_cid(s
->info
);
231 s
= ctype_get(cts
, sid
);
234 /* Skip attributes. */
235 while (ctype_isattrib(s
->info
))
236 s
= ctype_child(cts
, s
);
238 return lj_cconv_tv_ct(cts
, s
, sid
, o
, sp
);
241 /* -- C data setters ------------------------------------------------------ */
243 /* Convert TValue and set C data value. */
244 void lj_cdata_set(CTState
*cts
, CType
*d
, uint8_t *dp
, TValue
*o
, CTInfo qual
)
246 if (ctype_isconstval(d
->info
)) {
248 } else if (ctype_isbitfield(d
->info
)) {
249 if (((d
->info
|qual
) & CTF_CONST
)) goto err_const
;
250 lj_cconv_bf_tv(cts
, d
, dp
, o
);
254 /* Get child type of pointer/array/field. */
255 lua_assert(ctype_ispointer(d
->info
) || ctype_isfield(d
->info
));
256 d
= ctype_child(cts
, d
);
258 /* Resolve reference for field. */
259 if (ctype_isref(d
->info
)) {
260 lua_assert(d
->size
== CTSIZE_PTR
);
261 dp
= *(uint8_t **)dp
;
262 d
= ctype_child(cts
, d
);
265 /* Skip attributes and collect qualifiers. */
267 if (ctype_isattrib(d
->info
)) {
268 if (ctype_attrib(d
->info
) == CTA_QUAL
) qual
|= d
->size
;
272 d
= ctype_child(cts
, d
);
275 lua_assert(ctype_hassize(d
->info
) && !ctype_isvoid(d
->info
));
277 if (((d
->info
|qual
) & CTF_CONST
)) {
279 lj_err_caller(cts
->L
, LJ_ERR_FFI_WRCONST
);
282 lj_cconv_ct_tv(cts
, d
, dp
, o
, 0);