diff options
author | Mike Pall <mike> | 2015-01-03 15:23:58 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2015-01-03 15:23:58 +0100 |
commit | cb481ddc8f9d92913ba07d998f4274bbf9711077 (patch) | |
tree | 852ffb4dd7c3cfdcf5c1ca6ae1531e5f9436d064 /src/lj_obj.h | |
parent | 054e6abe37450344e20b373ec326055071029e9b (diff) | |
download | luajit-cb481ddc8f9d92913ba07d998f4274bbf9711077.tar.gz luajit-cb481ddc8f9d92913ba07d998f4274bbf9711077.tar.bz2 luajit-cb481ddc8f9d92913ba07d998f4274bbf9711077.zip |
Add LJ_GC64 mode: 64 bit GC object references.
Actually NaN tagging with 47 bit pointers and 13+4 bit tags.
Diffstat (limited to 'src/lj_obj.h')
-rw-r--r-- | src/lj_obj.h | 111 |
1 files changed, 104 insertions, 7 deletions
diff --git a/src/lj_obj.h b/src/lj_obj.h index 438c83d4..d5809229 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
@@ -17,39 +17,73 @@ | |||
17 | 17 | ||
18 | /* Memory and GC object sizes. */ | 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 | ||
20 | typedef uint32_t GCSize; | 23 | typedef uint32_t GCSize; |
24 | #endif | ||
21 | 25 | ||
22 | /* Memory reference */ | 26 | /* Memory reference */ |
23 | typedef struct MRef { | 27 | typedef struct MRef { |
28 | #if LJ_GC64 | ||
29 | uint64_t ptr64; /* True 64 bit pointer. */ | ||
30 | #else | ||
24 | uint32_t ptr32; /* Pseudo 32 bit pointer. */ | 31 | uint32_t ptr32; /* Pseudo 32 bit pointer. */ |
32 | #endif | ||
25 | } MRef; | 33 | } MRef; |
26 | 34 | ||
35 | #if LJ_GC64 | ||
36 | #define mref(r, t) ((t *)(void *)(r).ptr64) | ||
37 | |||
38 | #define setmref(r, p) ((r).ptr64 = (uint64_t)(void *)(p)) | ||
39 | #define setmrefr(r, v) ((r).ptr64 = (v).ptr64) | ||
40 | #else | ||
27 | #define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32) | 41 | #define mref(r, t) ((t *)(void *)(uintptr_t)(r).ptr32) |
28 | 42 | ||
29 | #define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p)) | 43 | #define setmref(r, p) ((r).ptr32 = (uint32_t)(uintptr_t)(void *)(p)) |
30 | #define setmrefr(r, v) ((r).ptr32 = (v).ptr32) | 44 | #define setmrefr(r, v) ((r).ptr32 = (v).ptr32) |
45 | #endif | ||
31 | 46 | ||
32 | /* -- GC object references (32 bit address space) ------------------------- */ | 47 | /* -- GC object references (32 bit address space) ------------------------- */ |
33 | 48 | ||
34 | /* GCobj reference */ | 49 | /* GCobj reference */ |
35 | typedef struct GCRef { | 50 | typedef struct GCRef { |
51 | #if LJ_GC64 | ||
52 | uint64_t gcptr64; /* True 64 bit pointer. */ | ||
53 | #else | ||
36 | uint32_t gcptr32; /* Pseudo 32 bit pointer. */ | 54 | uint32_t gcptr32; /* Pseudo 32 bit pointer. */ |
55 | #endif | ||
37 | } GCRef; | 56 | } GCRef; |
38 | 57 | ||
39 | /* Common GC header for all collectable objects. */ | 58 | /* Common GC header for all collectable objects. */ |
40 | #define GCHeader GCRef nextgc; uint8_t marked; uint8_t gct | 59 | #define GCHeader GCRef nextgc; uint8_t marked; uint8_t gct |
41 | /* This occupies 6 bytes, so use the next 2 bytes for non-32 bit fields. */ | 60 | /* This occupies 6 bytes, so use the next 2 bytes for non-32 bit fields. */ |
42 | 61 | ||
62 | #if LJ_GC64 | ||
63 | #define gcref(r) ((GCobj *)(r).gcptr64) | ||
64 | #define gcrefp(r, t) ((t *)(void *)(r).gcptr64) | ||
65 | #define gcrefu(r) ((r).gcptr64) | ||
66 | #define gcrefeq(r1, r2) ((r1).gcptr64 == (r2).gcptr64) | ||
67 | |||
68 | #define setgcref(r, gc) ((r).gcptr64 = (uint64_t)&(gc)->gch) | ||
69 | #define setgcreft(r, gc, it) \ | ||
70 | (r).gcptr64 = (uint64_t)&(gc)->gch | (((uint64_t)(it)) << 47) | ||
71 | #define setgcrefp(r, p) ((r).gcptr64 = (uint64_t)(p)) | ||
72 | #define setgcrefnull(r) ((r).gcptr64 = 0) | ||
73 | #define setgcrefr(r, v) ((r).gcptr64 = (v).gcptr64) | ||
74 | #else | ||
43 | #define gcref(r) ((GCobj *)(uintptr_t)(r).gcptr32) | 75 | #define gcref(r) ((GCobj *)(uintptr_t)(r).gcptr32) |
44 | #define gcrefp(r, t) ((t *)(void *)(uintptr_t)(r).gcptr32) | 76 | #define gcrefp(r, t) ((t *)(void *)(uintptr_t)(r).gcptr32) |
45 | #define gcrefu(r) ((r).gcptr32) | 77 | #define gcrefu(r) ((r).gcptr32) |
46 | #define gcrefeq(r1, r2) ((r1).gcptr32 == (r2).gcptr32) | 78 | #define gcrefeq(r1, r2) ((r1).gcptr32 == (r2).gcptr32) |
47 | #define gcnext(gc) (gcref((gc)->gch.nextgc)) | ||
48 | 79 | ||
49 | #define setgcref(r, gc) ((r).gcptr32 = (uint32_t)(uintptr_t)&(gc)->gch) | 80 | #define setgcref(r, gc) ((r).gcptr32 = (uint32_t)(uintptr_t)&(gc)->gch) |
50 | #define setgcrefp(r, p) ((r).gcptr32 = (uint32_t)(uintptr_t)(p)) | 81 | #define setgcrefp(r, p) ((r).gcptr32 = (uint32_t)(uintptr_t)(p)) |
51 | #define setgcrefnull(r) ((r).gcptr32 = 0) | 82 | #define setgcrefnull(r) ((r).gcptr32 = 0) |
52 | #define setgcrefr(r, v) ((r).gcptr32 = (v).gcptr32) | 83 | #define setgcrefr(r, v) ((r).gcptr32 = (v).gcptr32) |
84 | #endif | ||
85 | |||
86 | #define gcnext(gc) (gcref((gc)->gch.nextgc)) | ||
53 | 87 | ||
54 | /* IMPORTANT NOTE: | 88 | /* IMPORTANT NOTE: |
55 | ** | 89 | ** |
@@ -138,10 +172,16 @@ typedef union { | |||
138 | typedef LJ_ALIGN(8) union TValue { | 172 | typedef LJ_ALIGN(8) union TValue { |
139 | uint64_t u64; /* 64 bit pattern overlaps number. */ | 173 | uint64_t u64; /* 64 bit pattern overlaps number. */ |
140 | lua_Number n; /* Number object overlaps split tag/value object. */ | 174 | lua_Number n; /* Number object overlaps split tag/value object. */ |
175 | #if LJ_GC64 | ||
176 | GCRef gcr; /* GCobj reference with tag. */ | ||
177 | int64_t it64; | ||
178 | #endif | ||
141 | struct { | 179 | struct { |
142 | LJ_ENDIAN_LOHI( | 180 | LJ_ENDIAN_LOHI( |
143 | union { | 181 | union { |
182 | #if !LJ_GC64 | ||
144 | GCRef gcr; /* GCobj reference (if any). */ | 183 | GCRef gcr; /* GCobj reference (if any). */ |
184 | #endif | ||
145 | int32_t i; /* Integer value. */ | 185 | int32_t i; /* Integer value. */ |
146 | }; | 186 | }; |
147 | , uint32_t it; /* Internal object tag. Must overlap MSW of number. */ | 187 | , uint32_t it; /* Internal object tag. Must overlap MSW of number. */ |
@@ -176,6 +216,8 @@ typedef const TValue cTValue; | |||
176 | 216 | ||
177 | /* Internal object tags. | 217 | /* Internal object tags. |
178 | ** | 218 | ** |
219 | ** Format for 32 bit GC references (!LJ_GC64): | ||
220 | ** | ||
179 | ** Internal tags overlap the MSW of a number object (must be a double). | 221 | ** Internal tags overlap the MSW of a number object (must be a double). |
180 | ** Interpreted as a double these are special NaNs. The FPU only generates | 222 | ** Interpreted as a double these are special NaNs. The FPU only generates |
181 | ** one type of NaN (0xfff8_0000_0000_0000). So MSWs > 0xfff80000 are available | 223 | ** one type of NaN (0xfff8_0000_0000_0000). So MSWs > 0xfff80000 are available |
@@ -190,6 +232,18 @@ typedef const TValue cTValue; | |||
190 | ** int (LJ_DUALNUM)| itype | int | | 232 | ** int (LJ_DUALNUM)| itype | int | |
191 | ** number -------double------ | 233 | ** number -------double------ |
192 | ** | 234 | ** |
235 | ** Format for 64 bit GC references (LJ_GC64): | ||
236 | ** | ||
237 | ** The upper 13 bits must be 1 (0xfff8...) for a special NaN. The next | ||
238 | ** 4 bits hold the internal tag. The lowest 47 bits either hold a pointer, | ||
239 | ** a zero-extended 32 bit integer or all bits set to 1 for primitive types. | ||
240 | ** | ||
241 | ** ------MSW------.------LSW------ | ||
242 | ** primitive types |1..1|itype|1..................1| | ||
243 | ** GC objects/lightud |1..1|itype|-------GCRef--------| | ||
244 | ** int (LJ_DUALNUM) |1..1|itype|0..0|-----int-------| | ||
245 | ** number ------------double------------- | ||
246 | ** | ||
193 | ** ORDER LJ_T | 247 | ** ORDER LJ_T |
194 | ** Primitive types nil/false/true must be first, lightuserdata next. | 248 | ** Primitive types nil/false/true must be first, lightuserdata next. |
195 | ** GC objects are at the end, table/userdata must be lowest. | 249 | ** GC objects are at the end, table/userdata must be lowest. |
@@ -212,7 +266,7 @@ typedef const TValue cTValue; | |||
212 | #define LJ_TNUMX (~13u) | 266 | #define LJ_TNUMX (~13u) |
213 | 267 | ||
214 | /* Integers have itype == LJ_TISNUM doubles have itype < LJ_TISNUM */ | 268 | /* Integers have itype == LJ_TISNUM doubles have itype < LJ_TISNUM */ |
215 | #if LJ_64 | 269 | #if LJ_64 && !LJ_GC64 |
216 | #define LJ_TISNUM 0xfffeffffu | 270 | #define LJ_TISNUM 0xfffeffffu |
217 | #else | 271 | #else |
218 | #define LJ_TISNUM LJ_TNUMX | 272 | #define LJ_TISNUM LJ_TNUMX |
@@ -222,6 +276,10 @@ typedef const TValue cTValue; | |||
222 | #define LJ_TISGCV (LJ_TSTR+1) | 276 | #define LJ_TISGCV (LJ_TSTR+1) |
223 | #define LJ_TISTABUD LJ_TTAB | 277 | #define LJ_TISTABUD LJ_TTAB |
224 | 278 | ||
279 | #if LJ_GC64 | ||
280 | #define LJ_GCVMASK (((uint64_t)1 << 47) - 1) | ||
281 | #endif | ||
282 | |||
225 | /* -- String object ------------------------------------------------------- */ | 283 | /* -- String object ------------------------------------------------------- */ |
226 | 284 | ||
227 | /* String object header. String payload follows. */ | 285 | /* String object header. String payload follows. */ |
@@ -295,6 +353,9 @@ typedef struct GCproto { | |||
295 | uint8_t numparams; /* Number of parameters. */ | 353 | uint8_t numparams; /* Number of parameters. */ |
296 | uint8_t framesize; /* Fixed frame size. */ | 354 | uint8_t framesize; /* Fixed frame size. */ |
297 | MSize sizebc; /* Number of bytecode instructions. */ | 355 | MSize sizebc; /* Number of bytecode instructions. */ |
356 | #if LJ_GC64 | ||
357 | uint32_t unused_gc64; | ||
358 | #endif | ||
298 | GCRef gclist; | 359 | GCRef gclist; |
299 | MRef k; /* Split constant array (points to the middle). */ | 360 | MRef k; /* Split constant array (points to the middle). */ |
300 | MRef uv; /* Upvalue list. local slot|0x8000 or parent uv idx. */ | 361 | MRef uv; /* Upvalue list. local slot|0x8000 or parent uv idx. */ |
@@ -406,7 +467,9 @@ typedef struct Node { | |||
406 | TValue val; /* Value object. Must be first field. */ | 467 | TValue val; /* Value object. Must be first field. */ |
407 | TValue key; /* Key object. */ | 468 | TValue key; /* Key object. */ |
408 | MRef next; /* Hash chain. */ | 469 | MRef next; /* Hash chain. */ |
470 | #if !LJ_GC64 | ||
409 | MRef freetop; /* Top of free elements (stored in t->node[0]). */ | 471 | MRef freetop; /* Top of free elements (stored in t->node[0]). */ |
472 | #endif | ||
410 | } Node; | 473 | } Node; |
411 | 474 | ||
412 | LJ_STATIC_ASSERT(offsetof(Node, val) == 0); | 475 | LJ_STATIC_ASSERT(offsetof(Node, val) == 0); |
@@ -421,12 +484,22 @@ typedef struct GCtab { | |||
421 | MRef node; /* Hash part. */ | 484 | MRef node; /* Hash part. */ |
422 | uint32_t asize; /* Size of array part (keys [0, asize-1]). */ | 485 | uint32_t asize; /* Size of array part (keys [0, asize-1]). */ |
423 | uint32_t hmask; /* Hash part mask (size of hash part - 1). */ | 486 | uint32_t hmask; /* Hash part mask (size of hash part - 1). */ |
487 | #if LJ_GC64 | ||
488 | MRef freetop; /* Top of free elements. */ | ||
489 | #endif | ||
424 | } GCtab; | 490 | } GCtab; |
425 | 491 | ||
426 | #define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab)) | 492 | #define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab)) |
427 | #define tabref(r) (&gcref((r))->tab) | 493 | #define tabref(r) (&gcref((r))->tab) |
428 | #define noderef(r) (mref((r), Node)) | 494 | #define noderef(r) (mref((r), Node)) |
429 | #define nextnode(n) (mref((n)->next, Node)) | 495 | #define nextnode(n) (mref((n)->next, Node)) |
496 | #if LJ_GC64 | ||
497 | #define getfreetop(t, n) (noderef((t)->freetop)) | ||
498 | #define setfreetop(t, n, v) (setmref((t)->freetop, (v))) | ||
499 | #else | ||
500 | #define getfreetop(t, n) (noderef((n)->freetop)) | ||
501 | #define setfreetop(t, n, v) (setmref((n)->freetop, (v))) | ||
502 | #endif | ||
430 | 503 | ||
431 | /* -- State objects ------------------------------------------------------- */ | 504 | /* -- State objects ------------------------------------------------------- */ |
432 | 505 | ||
@@ -588,7 +661,9 @@ struct lua_State { | |||
588 | #define registry(L) (&G(L)->registrytv) | 661 | #define registry(L) (&G(L)->registrytv) |
589 | 662 | ||
590 | /* Macros to access the currently executing (Lua) function. */ | 663 | /* Macros to access the currently executing (Lua) function. */ |
591 | #if LJ_FR2 | 664 | #if LJ_GC64 |
665 | #define curr_func(L) (&gcval(L->base-2)->fn) | ||
666 | #elif LJ_FR2 | ||
592 | #define curr_func(L) (&gcref((L->base-2)->gcr)->fn) | 667 | #define curr_func(L) (&gcref((L->base-2)->gcr)->fn) |
593 | #else | 668 | #else |
594 | #define curr_func(L) (&gcref((L->base-1)->fr.func)->fn) | 669 | #define curr_func(L) (&gcref((L->base-1)->fr.func)->fn) |
@@ -656,12 +731,17 @@ typedef union GCobj { | |||
656 | #endif | 731 | #endif |
657 | 732 | ||
658 | /* Macros to test types. */ | 733 | /* Macros to test types. */ |
734 | #if LJ_GC64 | ||
735 | #define itype(o) ((uint32_t)((o)->it64 >> 47)) | ||
736 | #define tvisnil(o) ((o)->it64 == -1) | ||
737 | #else | ||
659 | #define itype(o) ((o)->it) | 738 | #define itype(o) ((o)->it) |
660 | #define tvisnil(o) (itype(o) == LJ_TNIL) | 739 | #define tvisnil(o) (itype(o) == LJ_TNIL) |
740 | #endif | ||
661 | #define tvisfalse(o) (itype(o) == LJ_TFALSE) | 741 | #define tvisfalse(o) (itype(o) == LJ_TFALSE) |
662 | #define tvistrue(o) (itype(o) == LJ_TTRUE) | 742 | #define tvistrue(o) (itype(o) == LJ_TTRUE) |
663 | #define tvisbool(o) (tvisfalse(o) || tvistrue(o)) | 743 | #define tvisbool(o) (tvisfalse(o) || tvistrue(o)) |
664 | #if LJ_64 | 744 | #if LJ_64 && !LJ_GC64 |
665 | #define tvislightud(o) (((int32_t)itype(o) >> 15) == -2) | 745 | #define tvislightud(o) (((int32_t)itype(o) >> 15) == -2) |
666 | #else | 746 | #else |
667 | #define tvislightud(o) (itype(o) == LJ_TLIGHTUD) | 747 | #define tvislightud(o) (itype(o) == LJ_TLIGHTUD) |
@@ -695,7 +775,7 @@ typedef union GCobj { | |||
695 | #define rawnumequal(o1, o2) ((o1)->u64 == (o2)->u64) | 775 | #define rawnumequal(o1, o2) ((o1)->u64 == (o2)->u64) |
696 | 776 | ||
697 | /* Macros to convert type ids. */ | 777 | /* Macros to convert type ids. */ |
698 | #if LJ_64 | 778 | #if LJ_64 && !LJ_GC64 |
699 | #define itypemap(o) \ | 779 | #define itypemap(o) \ |
700 | (tvisnumber(o) ? ~LJ_TNUMX : tvislightud(o) ? ~LJ_TLIGHTUD : ~itype(o)) | 780 | (tvisnumber(o) ? ~LJ_TNUMX : tvislightud(o) ? ~LJ_TLIGHTUD : ~itype(o)) |
701 | #else | 781 | #else |
@@ -703,8 +783,12 @@ typedef union GCobj { | |||
703 | #endif | 783 | #endif |
704 | 784 | ||
705 | /* Macros to get tagged values. */ | 785 | /* Macros to get tagged values. */ |
786 | #if LJ_GC64 | ||
787 | #define gcval(o) ((GCobj *)(gcrefu((o)->gcr) & LJ_GCVMASK)) | ||
788 | #else | ||
706 | #define gcval(o) (gcref((o)->gcr)) | 789 | #define gcval(o) (gcref((o)->gcr)) |
707 | #define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - (o)->it)) | 790 | #endif |
791 | #define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - itype(o))) | ||
708 | #if LJ_64 | 792 | #if LJ_64 |
709 | #define lightudV(o) \ | 793 | #define lightudV(o) \ |
710 | check_exp(tvislightud(o), (void *)((o)->u64 & U64x(00007fff,ffffffff))) | 794 | check_exp(tvislightud(o), (void *)((o)->u64 & U64x(00007fff,ffffffff))) |
@@ -723,14 +807,23 @@ typedef union GCobj { | |||
723 | #define intV(o) check_exp(tvisint(o), (int32_t)(o)->i) | 807 | #define intV(o) check_exp(tvisint(o), (int32_t)(o)->i) |
724 | 808 | ||
725 | /* Macros to set tagged values. */ | 809 | /* Macros to set tagged values. */ |
810 | #if LJ_GC64 | ||
811 | #define setitype(o, i) ((o)->it = ((i) << 15)) | ||
812 | #define setnilV(o) ((o)->it64 = -1) | ||
813 | #define setpriV(o, x) ((o)->it64 = (int64_t)~((uint64_t)~(x)<<47)) | ||
814 | #define setboolV(o, x) ((o)->it64 = (int64_t)~((uint64_t)((x)+1)<<47)) | ||
815 | #else | ||
726 | #define setitype(o, i) ((o)->it = (i)) | 816 | #define setitype(o, i) ((o)->it = (i)) |
727 | #define setnilV(o) ((o)->it = LJ_TNIL) | 817 | #define setnilV(o) ((o)->it = LJ_TNIL) |
728 | #define setboolV(o, x) ((o)->it = LJ_TFALSE-(uint32_t)(x)) | 818 | #define setboolV(o, x) ((o)->it = LJ_TFALSE-(uint32_t)(x)) |
729 | #define setpriV(o, i) (setitype((o), (i))) | 819 | #define setpriV(o, i) (setitype((o), (i))) |
820 | #endif | ||
730 | 821 | ||
731 | static LJ_AINLINE void setlightudV(TValue *o, void *p) | 822 | static LJ_AINLINE void setlightudV(TValue *o, void *p) |
732 | { | 823 | { |
733 | #if LJ_64 | 824 | #if LJ_GC64 |
825 | o->u64 = (uint64_t)p | (((uint64_t)LJ_TLIGHTUD) << 47); | ||
826 | #elif LJ_64 | ||
734 | o->u64 = (uint64_t)p | (((uint64_t)0xffff) << 48); | 827 | o->u64 = (uint64_t)p | (((uint64_t)0xffff) << 48); |
735 | #else | 828 | #else |
736 | setgcrefp(o->gcr, p); setitype(o, LJ_TLIGHTUD); | 829 | setgcrefp(o->gcr, p); setitype(o, LJ_TLIGHTUD); |
@@ -759,7 +852,11 @@ static LJ_AINLINE void setlightudV(TValue *o, void *p) | |||
759 | 852 | ||
760 | static LJ_AINLINE void setgcVraw(TValue *o, GCobj *v, uint32_t itype) | 853 | static LJ_AINLINE void setgcVraw(TValue *o, GCobj *v, uint32_t itype) |
761 | { | 854 | { |
855 | #if LJ_GC64 | ||
856 | setgcreft(o->gcr, v, itype); | ||
857 | #else | ||
762 | setgcref(o->gcr, v); setitype(o, itype); | 858 | setgcref(o->gcr, v); setitype(o, itype); |
859 | #endif | ||
763 | } | 860 | } |
764 | 861 | ||
765 | static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it) | 862 | static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it) |