diff options
Diffstat (limited to 'src/lj_obj.h')
-rw-r--r-- | src/lj_obj.h | 302 |
1 files changed, 241 insertions, 61 deletions
diff --git a/src/lj_obj.h b/src/lj_obj.h index 3e506bdb..0a63fddf 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
@@ -13,44 +13,81 @@ | |||
13 | #include "lj_def.h" | 13 | #include "lj_def.h" |
14 | #include "lj_arch.h" | 14 | #include "lj_arch.h" |
15 | 15 | ||
16 | /* -- Memory references (32 bit address space) ---------------------------- */ | 16 | /* -- Memory references --------------------------------------------------- */ |
17 | 17 | ||
18 | /* Memory size. */ | 18 | /* Memory and GC object sizes. */ |
19 | typedef uint32_t MSize; | 19 | typedef uint32_t MSize; |
20 | #if LJ_GC64 | ||
21 | typedef uint64_t GCSize; | ||
22 | #else | ||
23 | typedef uint32_t GCSize; | ||
24 | #endif | ||
20 | 25 | ||
21 | /* Memory reference */ | 26 | /* Memory reference */ |
22 | typedef struct MRef { | 27 | typedef struct MRef { |
28 | #if LJ_GC64 | ||
29 | uint64_t ptr64; /* True 64 bit pointer. */ | ||
30 | #else | ||
23 | uint32_t ptr32; /* Pseudo 32 bit pointer. */ | 31 | uint32_t ptr32; /* Pseudo 32 bit pointer. */ |
32 | #endif | ||
24 | } MRef; | 33 | } MRef; |
25 | 34 | ||
35 | #if LJ_GC64 | ||
36 | #define mref(r, t) ((t *)(void *)(r).ptr64) | ||
37 | #define mrefu(r) ((r).ptr64) | ||
38 | |||
39 | #define setmref(r, p) ((r).ptr64 = (uint64_t)(void *)(p)) | ||
40 | #define setmrefu(r, u) ((r).ptr64 = (uint64_t)(u)) | ||
41 | #define setmrefr(r, v) ((r).ptr64 = (v).ptr64) | ||
42 | #else | ||
26 | #define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32) | 43 | #define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32) |
44 | #define mrefu(r) ((r).ptr32) | ||
27 | 45 | ||
28 | #define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p)) | 46 | #define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p)) |
47 | #define setmrefu(r, u) ((r).ptr32 = (uint32_t)(u)) | ||
29 | #define setmrefr(r, v) ((r).ptr32 = (v).ptr32) | 48 | #define setmrefr(r, v) ((r).ptr32 = (v).ptr32) |
49 | #endif | ||
30 | 50 | ||
31 | /* -- GC object references (32 bit address space) ------------------------- */ | 51 | /* -- GC object references ------------------------------------------------ */ |
32 | 52 | ||
33 | /* GCobj reference */ | 53 | /* GCobj reference */ |
34 | typedef struct GCRef { | 54 | typedef struct GCRef { |
55 | #if LJ_GC64 | ||
56 | uint64_t gcptr64; /* True 64 bit pointer. */ | ||
57 | #else | ||
35 | uint32_t gcptr32; /* Pseudo 32 bit pointer. */ | 58 | uint32_t gcptr32; /* Pseudo 32 bit pointer. */ |
59 | #endif | ||
36 | } GCRef; | 60 | } GCRef; |
37 | 61 | ||
38 | /* Common GC header for all collectable objects. */ | 62 | /* Common GC header for all collectable objects. */ |
39 | #define GCHeader GCRef nextgc; uint8_t marked; uint8_t gct | 63 | #define GCHeader GCRef nextgc; uint8_t marked; uint8_t gct |
40 | /* This occupies 6 bytes, so use the next 2 bytes for non-32 bit fields. */ | 64 | /* This occupies 6 bytes, so use the next 2 bytes for non-32 bit fields. */ |
41 | 65 | ||
66 | #if LJ_GC64 | ||
67 | #define gcref(r) ((GCobj *)(r).gcptr64) | ||
68 | #define gcrefp(r, t) ((t *)(void *)(r).gcptr64) | ||
69 | #define gcrefu(r) ((r).gcptr64) | ||
70 | #define gcrefeq(r1, r2) ((r1).gcptr64 == (r2).gcptr64) | ||
71 | |||
72 | #define setgcref(r, gc) ((r).gcptr64 = (uint64_t)&(gc)->gch) | ||
73 | #define setgcreft(r, gc, it) \ | ||
74 | (r).gcptr64 = (uint64_t)&(gc)->gch | (((uint64_t)(it)) << 47) | ||
75 | #define setgcrefp(r, p) ((r).gcptr64 = (uint64_t)(p)) | ||
76 | #define setgcrefnull(r) ((r).gcptr64 = 0) | ||
77 | #define setgcrefr(r, v) ((r).gcptr64 = (v).gcptr64) | ||
78 | #else | ||
42 | #define gcref(r) ((GCobj *)(uintptr_t)(r).gcptr32) | 79 | #define gcref(r) ((GCobj *)(uintptr_t)(r).gcptr32) |
43 | #define gcrefp(r, t) ((t *)(void *)(uintptr_t)(r).gcptr32) | 80 | #define gcrefp(r, t) ((t *)(void *)(uintptr_t)(r).gcptr32) |
44 | #define gcrefu(r) ((r).gcptr32) | 81 | #define gcrefu(r) ((r).gcptr32) |
45 | #define gcrefi(r) ((int32_t)(r).gcptr32) | ||
46 | #define gcrefeq(r1, r2) ((r1).gcptr32 == (r2).gcptr32) | 82 | #define gcrefeq(r1, r2) ((r1).gcptr32 == (r2).gcptr32) |
47 | #define gcnext(gc) (gcref((gc)->gch.nextgc)) | ||
48 | 83 | ||
49 | #define setgcref(r, gc) ((r).gcptr32 = (uint32_t)(uintptr_t)&(gc)->gch) | 84 | #define setgcref(r, gc) ((r).gcptr32 = (uint32_t)(uintptr_t)&(gc)->gch) |
50 | #define setgcrefi(r, i) ((r).gcptr32 = (uint32_t)(i)) | ||
51 | #define setgcrefp(r, p) ((r).gcptr32 = (uint32_t)(uintptr_t)(p)) | 85 | #define setgcrefp(r, p) ((r).gcptr32 = (uint32_t)(uintptr_t)(p)) |
52 | #define setgcrefnull(r) ((r).gcptr32 = 0) | 86 | #define setgcrefnull(r) ((r).gcptr32 = 0) |
53 | #define setgcrefr(r, v) ((r).gcptr32 = (v).gcptr32) | 87 | #define setgcrefr(r, v) ((r).gcptr32 = (v).gcptr32) |
88 | #endif | ||
89 | |||
90 | #define gcnext(gc) (gcref((gc)->gch.nextgc)) | ||
54 | 91 | ||
55 | /* IMPORTANT NOTE: | 92 | /* IMPORTANT NOTE: |
56 | ** | 93 | ** |
@@ -119,11 +156,10 @@ typedef int32_t BCLine; /* Bytecode line number. */ | |||
119 | /* Internal assembler functions. Never call these directly from C. */ | 156 | /* Internal assembler functions. Never call these directly from C. */ |
120 | typedef void (*ASMFunction)(void); | 157 | typedef void (*ASMFunction)(void); |
121 | 158 | ||
122 | /* Resizable string buffer. Need this here, details in lj_str.h. */ | 159 | /* Resizable string buffer. Need this here, details in lj_buf.h. */ |
160 | #define SBufHeader char *w, *e, *b; MRef L | ||
123 | typedef struct SBuf { | 161 | typedef struct SBuf { |
124 | char *buf; /* String buffer base. */ | 162 | SBufHeader; |
125 | MSize n; /* String buffer length. */ | ||
126 | MSize sz; /* String buffer size. */ | ||
127 | } SBuf; | 163 | } SBuf; |
128 | 164 | ||
129 | /* -- Tags and values ----------------------------------------------------- */ | 165 | /* -- Tags and values ----------------------------------------------------- */ |
@@ -131,13 +167,23 @@ typedef struct SBuf { | |||
131 | /* Frame link. */ | 167 | /* Frame link. */ |
132 | typedef union { | 168 | typedef union { |
133 | int32_t ftsz; /* Frame type and size of previous frame. */ | 169 | int32_t ftsz; /* Frame type and size of previous frame. */ |
134 | MRef pcr; /* Overlaps PC for Lua frames. */ | 170 | MRef pcr; /* Or PC for Lua frames. */ |
135 | } FrameLink; | 171 | } FrameLink; |
136 | 172 | ||
137 | /* Tagged value. */ | 173 | /* Tagged value. */ |
138 | typedef LJ_ALIGN(8) union TValue { | 174 | typedef LJ_ALIGN(8) union TValue { |
139 | uint64_t u64; /* 64 bit pattern overlaps number. */ | 175 | uint64_t u64; /* 64 bit pattern overlaps number. */ |
140 | lua_Number n; /* Number object overlaps split tag/value object. */ | 176 | lua_Number n; /* Number object overlaps split tag/value object. */ |
177 | #if LJ_GC64 | ||
178 | GCRef gcr; /* GCobj reference with tag. */ | ||
179 | int64_t it64; | ||
180 | struct { | ||
181 | LJ_ENDIAN_LOHI( | ||
182 | int32_t i; /* Integer value. */ | ||
183 | , uint32_t it; /* Internal object tag. Must overlap MSW of number. */ | ||
184 | ) | ||
185 | }; | ||
186 | #else | ||
141 | struct { | 187 | struct { |
142 | LJ_ENDIAN_LOHI( | 188 | LJ_ENDIAN_LOHI( |
143 | union { | 189 | union { |
@@ -147,12 +193,17 @@ typedef LJ_ALIGN(8) union TValue { | |||
147 | , uint32_t it; /* Internal object tag. Must overlap MSW of number. */ | 193 | , uint32_t it; /* Internal object tag. Must overlap MSW of number. */ |
148 | ) | 194 | ) |
149 | }; | 195 | }; |
196 | #endif | ||
197 | #if LJ_FR2 | ||
198 | int64_t ftsz; /* Frame type and size of previous frame, or PC. */ | ||
199 | #else | ||
150 | struct { | 200 | struct { |
151 | LJ_ENDIAN_LOHI( | 201 | LJ_ENDIAN_LOHI( |
152 | GCRef func; /* Function for next frame (or dummy L). */ | 202 | GCRef func; /* Function for next frame (or dummy L). */ |
153 | , FrameLink tp; /* Link to previous frame. */ | 203 | , FrameLink tp; /* Link to previous frame. */ |
154 | ) | 204 | ) |
155 | } fr; | 205 | } fr; |
206 | #endif | ||
156 | struct { | 207 | struct { |
157 | LJ_ENDIAN_LOHI( | 208 | LJ_ENDIAN_LOHI( |
158 | uint32_t lo; /* Lower 32 bits of number. */ | 209 | uint32_t lo; /* Lower 32 bits of number. */ |
@@ -172,6 +223,8 @@ typedef const TValue cTValue; | |||
172 | 223 | ||
173 | /* Internal object tags. | 224 | /* Internal object tags. |
174 | ** | 225 | ** |
226 | ** Format for 32 bit GC references (!LJ_GC64): | ||
227 | ** | ||
175 | ** Internal tags overlap the MSW of a number object (must be a double). | 228 | ** Internal tags overlap the MSW of a number object (must be a double). |
176 | ** Interpreted as a double these are special NaNs. The FPU only generates | 229 | ** Interpreted as a double these are special NaNs. The FPU only generates |
177 | ** one type of NaN (0xfff8_0000_0000_0000). So MSWs > 0xfff80000 are available | 230 | ** one type of NaN (0xfff8_0000_0000_0000). So MSWs > 0xfff80000 are available |
@@ -181,11 +234,24 @@ typedef const TValue cTValue; | |||
181 | ** ---MSW---.---LSW--- | 234 | ** ---MSW---.---LSW--- |
182 | ** primitive types | itype | | | 235 | ** primitive types | itype | | |
183 | ** lightuserdata | itype | void * | (32 bit platforms) | 236 | ** lightuserdata | itype | void * | (32 bit platforms) |
184 | ** lightuserdata |ffff| void * | (64 bit platforms, 47 bit pointers) | 237 | ** lightuserdata |ffff|seg| ofs | (64 bit platforms) |
185 | ** GC objects | itype | GCRef | | 238 | ** GC objects | itype | GCRef | |
186 | ** int (LJ_DUALNUM)| itype | int | | 239 | ** int (LJ_DUALNUM)| itype | int | |
187 | ** number -------double------ | 240 | ** number -------double------ |
188 | ** | 241 | ** |
242 | ** Format for 64 bit GC references (LJ_GC64): | ||
243 | ** | ||
244 | ** The upper 13 bits must be 1 (0xfff8...) for a special NaN. The next | ||
245 | ** 4 bits hold the internal tag. The lowest 47 bits either hold a pointer, | ||
246 | ** a zero-extended 32 bit integer or all bits set to 1 for primitive types. | ||
247 | ** | ||
248 | ** ------MSW------.------LSW------ | ||
249 | ** primitive types |1..1|itype|1..................1| | ||
250 | ** GC objects |1..1|itype|-------GCRef--------| | ||
251 | ** lightuserdata |1..1|itype|seg|------ofs-------| | ||
252 | ** int (LJ_DUALNUM) |1..1|itype|0..0|-----int-------| | ||
253 | ** number ------------double------------- | ||
254 | ** | ||
189 | ** ORDER LJ_T | 255 | ** ORDER LJ_T |
190 | ** Primitive types nil/false/true must be first, lightuserdata next. | 256 | ** Primitive types nil/false/true must be first, lightuserdata next. |
191 | ** GC objects are at the end, table/userdata must be lowest. | 257 | ** GC objects are at the end, table/userdata must be lowest. |
@@ -208,7 +274,7 @@ typedef const TValue cTValue; | |||
208 | #define LJ_TNUMX (~13u) | 274 | #define LJ_TNUMX (~13u) |
209 | 275 | ||
210 | /* Integers have itype == LJ_TISNUM doubles have itype < LJ_TISNUM */ | 276 | /* Integers have itype == LJ_TISNUM doubles have itype < LJ_TISNUM */ |
211 | #if LJ_64 | 277 | #if LJ_64 && !LJ_GC64 |
212 | #define LJ_TISNUM 0xfffeffffu | 278 | #define LJ_TISNUM 0xfffeffffu |
213 | #else | 279 | #else |
214 | #define LJ_TISNUM LJ_TNUMX | 280 | #define LJ_TISNUM LJ_TNUMX |
@@ -218,14 +284,31 @@ typedef const TValue cTValue; | |||
218 | #define LJ_TISGCV (LJ_TSTR+1) | 284 | #define LJ_TISGCV (LJ_TSTR+1) |
219 | #define LJ_TISTABUD LJ_TTAB | 285 | #define LJ_TISTABUD LJ_TTAB |
220 | 286 | ||
287 | /* Type marker for slot holding a traversal index. Must be lightuserdata. */ | ||
288 | #define LJ_KEYINDEX 0xfffe7fffu | ||
289 | |||
290 | #if LJ_GC64 | ||
291 | #define LJ_GCVMASK (((uint64_t)1 << 47) - 1) | ||
292 | #endif | ||
293 | |||
294 | #if LJ_64 | ||
295 | /* To stay within 47 bits, lightuserdata is segmented. */ | ||
296 | #define LJ_LIGHTUD_BITS_SEG 8 | ||
297 | #define LJ_LIGHTUD_BITS_LO (47 - LJ_LIGHTUD_BITS_SEG) | ||
298 | #endif | ||
299 | |||
221 | /* -- String object ------------------------------------------------------- */ | 300 | /* -- String object ------------------------------------------------------- */ |
222 | 301 | ||
302 | typedef uint32_t StrHash; /* String hash value. */ | ||
303 | typedef uint32_t StrID; /* String ID. */ | ||
304 | |||
223 | /* String object header. String payload follows. */ | 305 | /* String object header. String payload follows. */ |
224 | typedef struct GCstr { | 306 | typedef struct GCstr { |
225 | GCHeader; | 307 | GCHeader; |
226 | uint8_t reserved; /* Used by lexer for fast lookup of reserved words. */ | 308 | uint8_t reserved; /* Used by lexer for fast lookup of reserved words. */ |
227 | uint8_t unused; | 309 | uint8_t hashalg; /* Hash algorithm. */ |
228 | MSize hash; /* Hash of string. */ | 310 | StrID sid; /* Interned string ID. */ |
311 | StrHash hash; /* Hash of string. */ | ||
229 | MSize len; /* Size of string. */ | 312 | MSize len; /* Size of string. */ |
230 | } GCstr; | 313 | } GCstr; |
231 | 314 | ||
@@ -233,7 +316,6 @@ typedef struct GCstr { | |||
233 | #define strdata(s) ((const char *)((s)+1)) | 316 | #define strdata(s) ((const char *)((s)+1)) |
234 | #define strdatawr(s) ((char *)((s)+1)) | 317 | #define strdatawr(s) ((char *)((s)+1)) |
235 | #define strVdata(o) strdata(strV(o)) | 318 | #define strVdata(o) strdata(strV(o)) |
236 | #define sizestring(s) (sizeof(struct GCstr)+(s)->len+1) | ||
237 | 319 | ||
238 | /* -- Userdata object ----------------------------------------------------- */ | 320 | /* -- Userdata object ----------------------------------------------------- */ |
239 | 321 | ||
@@ -253,6 +335,7 @@ enum { | |||
253 | UDTYPE_USERDATA, /* Regular userdata. */ | 335 | UDTYPE_USERDATA, /* Regular userdata. */ |
254 | UDTYPE_IO_FILE, /* I/O library FILE. */ | 336 | UDTYPE_IO_FILE, /* I/O library FILE. */ |
255 | UDTYPE_FFI_CLIB, /* FFI C library namespace. */ | 337 | UDTYPE_FFI_CLIB, /* FFI C library namespace. */ |
338 | UDTYPE_BUFFER, /* String buffer. */ | ||
256 | UDTYPE__MAX | 339 | UDTYPE__MAX |
257 | }; | 340 | }; |
258 | 341 | ||
@@ -291,6 +374,9 @@ typedef struct GCproto { | |||
291 | uint8_t numparams; /* Number of parameters. */ | 374 | uint8_t numparams; /* Number of parameters. */ |
292 | uint8_t framesize; /* Fixed frame size. */ | 375 | uint8_t framesize; /* Fixed frame size. */ |
293 | MSize sizebc; /* Number of bytecode instructions. */ | 376 | MSize sizebc; /* Number of bytecode instructions. */ |
377 | #if LJ_GC64 | ||
378 | uint32_t unused_gc64; | ||
379 | #endif | ||
294 | GCRef gclist; | 380 | GCRef gclist; |
295 | MRef k; /* Split constant array (points to the middle). */ | 381 | MRef k; /* Split constant array (points to the middle). */ |
296 | MRef uv; /* Upvalue list. local slot|0x8000 or parent uv idx. */ | 382 | MRef uv; /* Upvalue list. local slot|0x8000 or parent uv idx. */ |
@@ -402,7 +488,9 @@ typedef struct Node { | |||
402 | TValue val; /* Value object. Must be first field. */ | 488 | TValue val; /* Value object. Must be first field. */ |
403 | TValue key; /* Key object. */ | 489 | TValue key; /* Key object. */ |
404 | MRef next; /* Hash chain. */ | 490 | MRef next; /* Hash chain. */ |
491 | #if !LJ_GC64 | ||
405 | MRef freetop; /* Top of free elements (stored in t->node[0]). */ | 492 | MRef freetop; /* Top of free elements (stored in t->node[0]). */ |
493 | #endif | ||
406 | } Node; | 494 | } Node; |
407 | 495 | ||
408 | LJ_STATIC_ASSERT(offsetof(Node, val) == 0); | 496 | LJ_STATIC_ASSERT(offsetof(Node, val) == 0); |
@@ -417,12 +505,22 @@ typedef struct GCtab { | |||
417 | MRef node; /* Hash part. */ | 505 | MRef node; /* Hash part. */ |
418 | uint32_t asize; /* Size of array part (keys [0, asize-1]). */ | 506 | uint32_t asize; /* Size of array part (keys [0, asize-1]). */ |
419 | uint32_t hmask; /* Hash part mask (size of hash part - 1). */ | 507 | uint32_t hmask; /* Hash part mask (size of hash part - 1). */ |
508 | #if LJ_GC64 | ||
509 | MRef freetop; /* Top of free elements. */ | ||
510 | #endif | ||
420 | } GCtab; | 511 | } GCtab; |
421 | 512 | ||
422 | #define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab)) | 513 | #define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab)) |
423 | #define tabref(r) (&gcref((r))->tab) | 514 | #define tabref(r) (&gcref((r))->tab) |
424 | #define noderef(r) (mref((r), Node)) | 515 | #define noderef(r) (mref((r), Node)) |
425 | #define nextnode(n) (mref((n)->next, Node)) | 516 | #define nextnode(n) (mref((n)->next, Node)) |
517 | #if LJ_GC64 | ||
518 | #define getfreetop(t, n) (noderef((t)->freetop)) | ||
519 | #define setfreetop(t, n, v) (setmref((t)->freetop, (v))) | ||
520 | #else | ||
521 | #define getfreetop(t, n) (noderef((n)->freetop)) | ||
522 | #define setfreetop(t, n, v) (setmref((n)->freetop, (v))) | ||
523 | #endif | ||
426 | 524 | ||
427 | /* -- State objects ------------------------------------------------------- */ | 525 | /* -- State objects ------------------------------------------------------- */ |
428 | 526 | ||
@@ -488,13 +586,18 @@ typedef enum { | |||
488 | #define basemt_obj(g, o) ((g)->gcroot[GCROOT_BASEMT+itypemap(o)]) | 586 | #define basemt_obj(g, o) ((g)->gcroot[GCROOT_BASEMT+itypemap(o)]) |
489 | #define mmname_str(g, mm) (strref((g)->gcroot[GCROOT_MMNAME+(mm)])) | 587 | #define mmname_str(g, mm) (strref((g)->gcroot[GCROOT_MMNAME+(mm)])) |
490 | 588 | ||
589 | /* Garbage collector state. */ | ||
491 | typedef struct GCState { | 590 | typedef struct GCState { |
492 | MSize total; /* Memory currently allocated. */ | 591 | GCSize total; /* Memory currently allocated. */ |
493 | MSize threshold; /* Memory threshold. */ | 592 | GCSize threshold; /* Memory threshold. */ |
494 | uint8_t currentwhite; /* Current white color. */ | 593 | uint8_t currentwhite; /* Current white color. */ |
495 | uint8_t state; /* GC state. */ | 594 | uint8_t state; /* GC state. */ |
496 | uint8_t nocdatafin; /* No cdata finalizer called. */ | 595 | uint8_t nocdatafin; /* No cdata finalizer called. */ |
497 | uint8_t unused2; | 596 | #if LJ_64 |
597 | uint8_t lightudnum; /* Number of lightuserdata segments - 1. */ | ||
598 | #else | ||
599 | uint8_t unused1; | ||
600 | #endif | ||
498 | MSize sweepstr; /* Sweep position in string table. */ | 601 | MSize sweepstr; /* Sweep position in string table. */ |
499 | GCRef root; /* List of all collectable objects. */ | 602 | GCRef root; /* List of all collectable objects. */ |
500 | MRef sweep; /* Sweep position in root list. */ | 603 | MRef sweep; /* Sweep position in root list. */ |
@@ -502,42 +605,57 @@ typedef struct GCState { | |||
502 | GCRef grayagain; /* List of objects for atomic traversal. */ | 605 | GCRef grayagain; /* List of objects for atomic traversal. */ |
503 | GCRef weak; /* List of weak tables (to be cleared). */ | 606 | GCRef weak; /* List of weak tables (to be cleared). */ |
504 | GCRef mmudata; /* List of userdata (to be finalized). */ | 607 | GCRef mmudata; /* List of userdata (to be finalized). */ |
608 | GCSize debt; /* Debt (how much GC is behind schedule). */ | ||
609 | GCSize estimate; /* Estimate of memory actually in use. */ | ||
505 | MSize stepmul; /* Incremental GC step granularity. */ | 610 | MSize stepmul; /* Incremental GC step granularity. */ |
506 | MSize debt; /* Debt (how much GC is behind schedule). */ | ||
507 | MSize estimate; /* Estimate of memory actually in use. */ | ||
508 | MSize pause; /* Pause between successive GC cycles. */ | 611 | MSize pause; /* Pause between successive GC cycles. */ |
612 | #if LJ_64 | ||
613 | MRef lightudseg; /* Upper bits of lightuserdata segments. */ | ||
614 | #endif | ||
509 | } GCState; | 615 | } GCState; |
510 | 616 | ||
617 | /* String interning state. */ | ||
618 | typedef struct StrInternState { | ||
619 | GCRef *tab; /* String hash table anchors. */ | ||
620 | MSize mask; /* String hash mask (size of hash table - 1). */ | ||
621 | MSize num; /* Number of strings in hash table. */ | ||
622 | StrID id; /* Next string ID. */ | ||
623 | uint8_t idreseed; /* String ID reseed counter. */ | ||
624 | uint8_t second; /* String interning table uses secondary hashing. */ | ||
625 | uint8_t unused1; | ||
626 | uint8_t unused2; | ||
627 | LJ_ALIGN(8) uint64_t seed; /* Random string seed. */ | ||
628 | } StrInternState; | ||
629 | |||
511 | /* Global state, shared by all threads of a Lua universe. */ | 630 | /* Global state, shared by all threads of a Lua universe. */ |
512 | typedef struct global_State { | 631 | typedef struct global_State { |
513 | GCRef *strhash; /* String hash table (hash chain anchors). */ | ||
514 | MSize strmask; /* String hash mask (size of hash table - 1). */ | ||
515 | MSize strnum; /* Number of strings in hash table. */ | ||
516 | lua_Alloc allocf; /* Memory allocator. */ | 632 | lua_Alloc allocf; /* Memory allocator. */ |
517 | void *allocd; /* Memory allocator data. */ | 633 | void *allocd; /* Memory allocator data. */ |
518 | GCState gc; /* Garbage collector. */ | 634 | GCState gc; /* Garbage collector. */ |
519 | SBuf tmpbuf; /* Temporary buffer for string concatenation. */ | ||
520 | Node nilnode; /* Fallback 1-element hash part (nil key and value). */ | ||
521 | GCstr strempty; /* Empty string. */ | 635 | GCstr strempty; /* Empty string. */ |
522 | uint8_t stremptyz; /* Zero terminator of empty string. */ | 636 | uint8_t stremptyz; /* Zero terminator of empty string. */ |
523 | uint8_t hookmask; /* Hook mask. */ | 637 | uint8_t hookmask; /* Hook mask. */ |
524 | uint8_t dispatchmode; /* Dispatch mode. */ | 638 | uint8_t dispatchmode; /* Dispatch mode. */ |
525 | uint8_t vmevmask; /* VM event mask. */ | 639 | uint8_t vmevmask; /* VM event mask. */ |
640 | StrInternState str; /* String interning. */ | ||
641 | volatile int32_t vmstate; /* VM state or current JIT code trace number. */ | ||
526 | GCRef mainthref; /* Link to main thread. */ | 642 | GCRef mainthref; /* Link to main thread. */ |
527 | TValue registrytv; /* Anchor for registry. */ | 643 | SBuf tmpbuf; /* Temporary string buffer. */ |
528 | TValue tmptv, tmptv2; /* Temporary TValues. */ | 644 | TValue tmptv, tmptv2; /* Temporary TValues. */ |
645 | Node nilnode; /* Fallback 1-element hash part (nil key and value). */ | ||
646 | TValue registrytv; /* Anchor for registry. */ | ||
529 | GCupval uvhead; /* Head of double-linked list of all open upvalues. */ | 647 | GCupval uvhead; /* Head of double-linked list of all open upvalues. */ |
530 | int32_t hookcount; /* Instruction hook countdown. */ | 648 | int32_t hookcount; /* Instruction hook countdown. */ |
531 | int32_t hookcstart; /* Start count for instruction hook counter. */ | 649 | int32_t hookcstart; /* Start count for instruction hook counter. */ |
532 | lua_Hook hookf; /* Hook function. */ | 650 | lua_Hook hookf; /* Hook function. */ |
533 | lua_CFunction wrapf; /* Wrapper for C function calls. */ | 651 | lua_CFunction wrapf; /* Wrapper for C function calls. */ |
534 | lua_CFunction panic; /* Called as a last resort for errors. */ | 652 | lua_CFunction panic; /* Called as a last resort for errors. */ |
535 | volatile int32_t vmstate; /* VM state or current JIT code trace number. */ | ||
536 | BCIns bc_cfunc_int; /* Bytecode for internal C function calls. */ | 653 | BCIns bc_cfunc_int; /* Bytecode for internal C function calls. */ |
537 | BCIns bc_cfunc_ext; /* Bytecode for external C function calls. */ | 654 | BCIns bc_cfunc_ext; /* Bytecode for external C function calls. */ |
538 | GCRef jit_L; /* Current JIT code lua_State or NULL. */ | 655 | GCRef cur_L; /* Currently executing lua_State. */ |
539 | MRef jit_base; /* Current JIT code L->base. */ | 656 | MRef jit_base; /* Current JIT code L->base or NULL. */ |
540 | MRef ctype_state; /* Pointer to C type state. */ | 657 | MRef ctype_state; /* Pointer to C type state. */ |
658 | PRNGState prng; /* Global PRNG state. */ | ||
541 | GCRef gcroot[GCROOT_MAX]; /* GC roots. */ | 659 | GCRef gcroot[GCROOT_MAX]; /* GC roots. */ |
542 | } global_State; | 660 | } global_State; |
543 | 661 | ||
@@ -553,9 +671,11 @@ typedef struct global_State { | |||
553 | #define HOOK_ACTIVE_SHIFT 4 | 671 | #define HOOK_ACTIVE_SHIFT 4 |
554 | #define HOOK_VMEVENT 0x20 | 672 | #define HOOK_VMEVENT 0x20 |
555 | #define HOOK_GC 0x40 | 673 | #define HOOK_GC 0x40 |
674 | #define HOOK_PROFILE 0x80 | ||
556 | #define hook_active(g) ((g)->hookmask & HOOK_ACTIVE) | 675 | #define hook_active(g) ((g)->hookmask & HOOK_ACTIVE) |
557 | #define hook_enter(g) ((g)->hookmask |= HOOK_ACTIVE) | 676 | #define hook_enter(g) ((g)->hookmask |= HOOK_ACTIVE) |
558 | #define hook_entergc(g) ((g)->hookmask |= (HOOK_ACTIVE|HOOK_GC)) | 677 | #define hook_entergc(g) \ |
678 | ((g)->hookmask = ((g)->hookmask | (HOOK_ACTIVE|HOOK_GC)) & ~HOOK_PROFILE) | ||
559 | #define hook_vmevent(g) ((g)->hookmask |= (HOOK_ACTIVE|HOOK_VMEVENT)) | 679 | #define hook_vmevent(g) ((g)->hookmask |= (HOOK_ACTIVE|HOOK_VMEVENT)) |
560 | #define hook_leave(g) ((g)->hookmask &= ~HOOK_ACTIVE) | 680 | #define hook_leave(g) ((g)->hookmask &= ~HOOK_ACTIVE) |
561 | #define hook_save(g) ((g)->hookmask & ~HOOK_EVENTMASK) | 681 | #define hook_save(g) ((g)->hookmask & ~HOOK_EVENTMASK) |
@@ -583,12 +703,23 @@ struct lua_State { | |||
583 | #define registry(L) (&G(L)->registrytv) | 703 | #define registry(L) (&G(L)->registrytv) |
584 | 704 | ||
585 | /* Macros to access the currently executing (Lua) function. */ | 705 | /* Macros to access the currently executing (Lua) function. */ |
706 | #if LJ_GC64 | ||
707 | #define curr_func(L) (&gcval(L->base-2)->fn) | ||
708 | #elif LJ_FR2 | ||
709 | #define curr_func(L) (&gcref((L->base-2)->gcr)->fn) | ||
710 | #else | ||
586 | #define curr_func(L) (&gcref((L->base-1)->fr.func)->fn) | 711 | #define curr_func(L) (&gcref((L->base-1)->fr.func)->fn) |
712 | #endif | ||
587 | #define curr_funcisL(L) (isluafunc(curr_func(L))) | 713 | #define curr_funcisL(L) (isluafunc(curr_func(L))) |
588 | #define curr_proto(L) (funcproto(curr_func(L))) | 714 | #define curr_proto(L) (funcproto(curr_func(L))) |
589 | #define curr_topL(L) (L->base + curr_proto(L)->framesize) | 715 | #define curr_topL(L) (L->base + curr_proto(L)->framesize) |
590 | #define curr_top(L) (curr_funcisL(L) ? curr_topL(L) : L->top) | 716 | #define curr_top(L) (curr_funcisL(L) ? curr_topL(L) : L->top) |
591 | 717 | ||
718 | #if defined(LUA_USE_ASSERT) || defined(LUA_USE_APICHECK) | ||
719 | LJ_FUNC_NORET void lj_assert_fail(global_State *g, const char *file, int line, | ||
720 | const char *func, const char *fmt, ...); | ||
721 | #endif | ||
722 | |||
592 | /* -- GC object definition and conversions -------------------------------- */ | 723 | /* -- GC object definition and conversions -------------------------------- */ |
593 | 724 | ||
594 | /* GC header for generic access to common fields of GC objects. */ | 725 | /* GC header for generic access to common fields of GC objects. */ |
@@ -642,17 +773,18 @@ typedef union GCobj { | |||
642 | 773 | ||
643 | /* -- TValue getters/setters ---------------------------------------------- */ | 774 | /* -- TValue getters/setters ---------------------------------------------- */ |
644 | 775 | ||
645 | #ifdef LUA_USE_ASSERT | ||
646 | #include "lj_gc.h" | ||
647 | #endif | ||
648 | |||
649 | /* Macros to test types. */ | 776 | /* Macros to test types. */ |
777 | #if LJ_GC64 | ||
778 | #define itype(o) ((uint32_t)((o)->it64 >> 47)) | ||
779 | #define tvisnil(o) ((o)->it64 == -1) | ||
780 | #else | ||
650 | #define itype(o) ((o)->it) | 781 | #define itype(o) ((o)->it) |
651 | #define tvisnil(o) (itype(o) == LJ_TNIL) | 782 | #define tvisnil(o) (itype(o) == LJ_TNIL) |
783 | #endif | ||
652 | #define tvisfalse(o) (itype(o) == LJ_TFALSE) | 784 | #define tvisfalse(o) (itype(o) == LJ_TFALSE) |
653 | #define tvistrue(o) (itype(o) == LJ_TTRUE) | 785 | #define tvistrue(o) (itype(o) == LJ_TTRUE) |
654 | #define tvisbool(o) (tvisfalse(o) || tvistrue(o)) | 786 | #define tvisbool(o) (tvisfalse(o) || tvistrue(o)) |
655 | #if LJ_64 | 787 | #if LJ_64 && !LJ_GC64 |
656 | #define tvislightud(o) (((int32_t)itype(o) >> 15) == -2) | 788 | #define tvislightud(o) (((int32_t)itype(o) >> 15) == -2) |
657 | #else | 789 | #else |
658 | #define tvislightud(o) (itype(o) == LJ_TLIGHTUD) | 790 | #define tvislightud(o) (itype(o) == LJ_TLIGHTUD) |
@@ -686,7 +818,7 @@ typedef union GCobj { | |||
686 | #define rawnumequal(o1, o2) ((o1)->u64 == (o2)->u64) | 818 | #define rawnumequal(o1, o2) ((o1)->u64 == (o2)->u64) |
687 | 819 | ||
688 | /* Macros to convert type ids. */ | 820 | /* Macros to convert type ids. */ |
689 | #if LJ_64 | 821 | #if LJ_64 && !LJ_GC64 |
690 | #define itypemap(o) \ | 822 | #define itypemap(o) \ |
691 | (tvisnumber(o) ? ~LJ_TNUMX : tvislightud(o) ? ~LJ_TLIGHTUD : ~itype(o)) | 823 | (tvisnumber(o) ? ~LJ_TNUMX : tvislightud(o) ? ~LJ_TLIGHTUD : ~itype(o)) |
692 | #else | 824 | #else |
@@ -694,13 +826,30 @@ typedef union GCobj { | |||
694 | #endif | 826 | #endif |
695 | 827 | ||
696 | /* Macros to get tagged values. */ | 828 | /* Macros to get tagged values. */ |
829 | #if LJ_GC64 | ||
830 | #define gcval(o) ((GCobj *)(gcrefu((o)->gcr) & LJ_GCVMASK)) | ||
831 | #else | ||
697 | #define gcval(o) (gcref((o)->gcr)) | 832 | #define gcval(o) (gcref((o)->gcr)) |
698 | #define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - (o)->it)) | 833 | #endif |
834 | #define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - itype(o))) | ||
699 | #if LJ_64 | 835 | #if LJ_64 |
700 | #define lightudV(o) \ | 836 | #define lightudseg(u) \ |
701 | check_exp(tvislightud(o), (void *)((o)->u64 & U64x(00007fff,ffffffff))) | 837 | (((u) >> LJ_LIGHTUD_BITS_LO) & ((1 << LJ_LIGHTUD_BITS_SEG)-1)) |
838 | #define lightudlo(u) \ | ||
839 | ((u) & (((uint64_t)1 << LJ_LIGHTUD_BITS_LO) - 1)) | ||
840 | #define lightudup(p) \ | ||
841 | ((uint32_t)(((p) >> LJ_LIGHTUD_BITS_LO) << (LJ_LIGHTUD_BITS_LO-32))) | ||
842 | static LJ_AINLINE void *lightudV(global_State *g, cTValue *o) | ||
843 | { | ||
844 | uint64_t u = o->u64; | ||
845 | uint64_t seg = lightudseg(u); | ||
846 | uint32_t *segmap = mref(g->gc.lightudseg, uint32_t); | ||
847 | lj_assertG(tvislightud(o), "lightuserdata expected"); | ||
848 | lj_assertG(seg <= g->gc.lightudnum, "bad lightuserdata segment %d", seg); | ||
849 | return (void *)(((uint64_t)segmap[seg] << 32) | lightudlo(u)); | ||
850 | } | ||
702 | #else | 851 | #else |
703 | #define lightudV(o) check_exp(tvislightud(o), gcrefp((o)->gcr, void)) | 852 | #define lightudV(g, o) check_exp(tvislightud(o), gcrefp((o)->gcr, void)) |
704 | #endif | 853 | #endif |
705 | #define gcV(o) check_exp(tvisgcv(o), gcval(o)) | 854 | #define gcV(o) check_exp(tvisgcv(o), gcval(o)) |
706 | #define strV(o) check_exp(tvisstr(o), &gcval(o)->str) | 855 | #define strV(o) check_exp(tvisstr(o), &gcval(o)->str) |
@@ -714,40 +863,70 @@ typedef union GCobj { | |||
714 | #define intV(o) check_exp(tvisint(o), (int32_t)(o)->i) | 863 | #define intV(o) check_exp(tvisint(o), (int32_t)(o)->i) |
715 | 864 | ||
716 | /* Macros to set tagged values. */ | 865 | /* Macros to set tagged values. */ |
866 | #if LJ_GC64 | ||
867 | #define setitype(o, i) ((o)->it = ((i) << 15)) | ||
868 | #define setnilV(o) ((o)->it64 = -1) | ||
869 | #define setpriV(o, x) ((o)->it64 = (int64_t)~((uint64_t)~(x)<<47)) | ||
870 | #define setboolV(o, x) ((o)->it64 = (int64_t)~((uint64_t)((x)+1)<<47)) | ||
871 | #else | ||
717 | #define setitype(o, i) ((o)->it = (i)) | 872 | #define setitype(o, i) ((o)->it = (i)) |
718 | #define setnilV(o) ((o)->it = LJ_TNIL) | 873 | #define setnilV(o) ((o)->it = LJ_TNIL) |
719 | #define setboolV(o, x) ((o)->it = LJ_TFALSE-(uint32_t)(x)) | 874 | #define setboolV(o, x) ((o)->it = LJ_TFALSE-(uint32_t)(x)) |
875 | #define setpriV(o, i) (setitype((o), (i))) | ||
876 | #endif | ||
720 | 877 | ||
721 | static LJ_AINLINE void setlightudV(TValue *o, void *p) | 878 | static LJ_AINLINE void setrawlightudV(TValue *o, void *p) |
722 | { | 879 | { |
723 | #if LJ_64 | 880 | #if LJ_GC64 |
881 | o->u64 = (uint64_t)p | (((uint64_t)LJ_TLIGHTUD) << 47); | ||
882 | #elif LJ_64 | ||
724 | o->u64 = (uint64_t)p | (((uint64_t)0xffff) << 48); | 883 | o->u64 = (uint64_t)p | (((uint64_t)0xffff) << 48); |
725 | #else | 884 | #else |
726 | setgcrefp(o->gcr, p); setitype(o, LJ_TLIGHTUD); | 885 | setgcrefp(o->gcr, p); setitype(o, LJ_TLIGHTUD); |
727 | #endif | 886 | #endif |
728 | } | 887 | } |
729 | 888 | ||
730 | #if LJ_64 | 889 | #if LJ_FR2 || LJ_32 |
731 | #define checklightudptr(L, p) \ | 890 | #define contptr(f) ((void *)(f)) |
732 | (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) | 891 | #define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)contptr(f)) |
892 | #else | ||
893 | #define contptr(f) \ | ||
894 | ((void *)(uintptr_t)(uint32_t)((intptr_t)(f) - (intptr_t)lj_vm_asm_begin)) | ||
733 | #define setcont(o, f) \ | 895 | #define setcont(o, f) \ |
734 | ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin) | 896 | ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin) |
735 | #else | ||
736 | #define checklightudptr(L, p) (p) | ||
737 | #define setcont(o, f) setlightudV((o), (void *)(f)) | ||
738 | #endif | 897 | #endif |
739 | 898 | ||
740 | #define tvchecklive(L, o) \ | 899 | static LJ_AINLINE void checklivetv(lua_State *L, TValue *o, const char *msg) |
741 | UNUSED(L), lua_assert(!tvisgcv(o) || \ | 900 | { |
742 | ((~itype(o) == gcval(o)->gch.gct) && !isdead(G(L), gcval(o)))) | 901 | UNUSED(L); UNUSED(o); UNUSED(msg); |
902 | #if LUA_USE_ASSERT | ||
903 | if (tvisgcv(o)) { | ||
904 | lj_assertL(~itype(o) == gcval(o)->gch.gct, | ||
905 | "mismatch of TValue type %d vs GC type %d", | ||
906 | ~itype(o), gcval(o)->gch.gct); | ||
907 | /* Copy of isdead check from lj_gc.h to avoid circular include. */ | ||
908 | lj_assertL(!(gcval(o)->gch.marked & (G(L)->gc.currentwhite ^ 3) & 3), msg); | ||
909 | } | ||
910 | #endif | ||
911 | } | ||
912 | |||
913 | static LJ_AINLINE void setgcVraw(TValue *o, GCobj *v, uint32_t itype) | ||
914 | { | ||
915 | #if LJ_GC64 | ||
916 | setgcreft(o->gcr, v, itype); | ||
917 | #else | ||
918 | setgcref(o->gcr, v); setitype(o, itype); | ||
919 | #endif | ||
920 | } | ||
743 | 921 | ||
744 | static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t itype) | 922 | static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it) |
745 | { | 923 | { |
746 | setgcref(o->gcr, v); setitype(o, itype); tvchecklive(L, o); | 924 | setgcVraw(o, v, it); |
925 | checklivetv(L, o, "store to dead GC object"); | ||
747 | } | 926 | } |
748 | 927 | ||
749 | #define define_setV(name, type, tag) \ | 928 | #define define_setV(name, type, tag) \ |
750 | static LJ_AINLINE void name(lua_State *L, TValue *o, type *v) \ | 929 | static LJ_AINLINE void name(lua_State *L, TValue *o, const type *v) \ |
751 | { \ | 930 | { \ |
752 | setgcV(L, o, obj2gco(v), tag); \ | 931 | setgcV(L, o, obj2gco(v), tag); \ |
753 | } | 932 | } |
@@ -790,13 +969,17 @@ static LJ_AINLINE void setint64V(TValue *o, int64_t i) | |||
790 | /* Copy tagged values. */ | 969 | /* Copy tagged values. */ |
791 | static LJ_AINLINE void copyTV(lua_State *L, TValue *o1, const TValue *o2) | 970 | static LJ_AINLINE void copyTV(lua_State *L, TValue *o1, const TValue *o2) |
792 | { | 971 | { |
793 | *o1 = *o2; tvchecklive(L, o1); | 972 | *o1 = *o2; |
973 | checklivetv(L, o1, "copy of dead GC object"); | ||
794 | } | 974 | } |
795 | 975 | ||
796 | /* -- Number to integer conversion ---------------------------------------- */ | 976 | /* -- Number to integer conversion ---------------------------------------- */ |
797 | 977 | ||
798 | #if LJ_SOFTFP | 978 | #if LJ_SOFTFP |
799 | LJ_ASMF int32_t lj_vm_tobit(double x); | 979 | LJ_ASMF int32_t lj_vm_tobit(double x); |
980 | #if LJ_TARGET_MIPS64 | ||
981 | LJ_ASMF int32_t lj_vm_tointg(double x); | ||
982 | #endif | ||
800 | #endif | 983 | #endif |
801 | 984 | ||
802 | static LJ_AINLINE int32_t lj_num2bit(lua_Number n) | 985 | static LJ_AINLINE int32_t lj_num2bit(lua_Number n) |
@@ -810,11 +993,7 @@ static LJ_AINLINE int32_t lj_num2bit(lua_Number n) | |||
810 | #endif | 993 | #endif |
811 | } | 994 | } |
812 | 995 | ||
813 | #if LJ_TARGET_X86 && !defined(__SSE2__) | ||
814 | #define lj_num2int(n) lj_num2bit((n)) | ||
815 | #else | ||
816 | #define lj_num2int(n) ((int32_t)(n)) | 996 | #define lj_num2int(n) ((int32_t)(n)) |
817 | #endif | ||
818 | 997 | ||
819 | /* | 998 | /* |
820 | ** This must match the JIT backend behavior. In particular for archs | 999 | ** This must match the JIT backend behavior. In particular for archs |
@@ -859,6 +1038,7 @@ LJ_DATA const char *const lj_obj_itypename[~LJ_TNUMX+1]; | |||
859 | #define lj_typename(o) (lj_obj_itypename[itypemap(o)]) | 1038 | #define lj_typename(o) (lj_obj_itypename[itypemap(o)]) |
860 | 1039 | ||
861 | /* Compare two objects without calling metamethods. */ | 1040 | /* Compare two objects without calling metamethods. */ |
862 | LJ_FUNC int lj_obj_equal(cTValue *o1, cTValue *o2); | 1041 | LJ_FUNC int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2); |
1042 | LJ_FUNC const void * LJ_FASTCALL lj_obj_ptr(global_State *g, cTValue *o); | ||
863 | 1043 | ||
864 | #endif | 1044 | #endif |