aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2015-01-03 15:23:58 +0100
committerMike Pall <mike>2015-01-03 15:23:58 +0100
commitcb481ddc8f9d92913ba07d998f4274bbf9711077 (patch)
tree852ffb4dd7c3cfdcf5c1ca6ae1531e5f9436d064 /src
parent054e6abe37450344e20b373ec326055071029e9b (diff)
downloadluajit-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')
-rw-r--r--src/lj_alloc.c12
-rw-r--r--src/lj_api.c4
-rw-r--r--src/lj_arch.h13
-rw-r--r--src/lj_def.h15
-rw-r--r--src/lj_ffrecord.c2
-rw-r--r--src/lj_ir.c1
-rw-r--r--src/lj_ir.h11
-rw-r--r--src/lj_jit.h3
-rw-r--r--src/lj_lib.h5
-rw-r--r--src/lj_obj.h111
-rw-r--r--src/lj_snap.c1
-rw-r--r--src/lj_state.c2
-rw-r--r--src/lj_tab.c32
13 files changed, 183 insertions, 29 deletions
diff --git a/src/lj_alloc.c b/src/lj_alloc.c
index 7c7ec678..0aad826d 100644
--- a/src/lj_alloc.c
+++ b/src/lj_alloc.c
@@ -77,7 +77,7 @@
77#define WIN32_LEAN_AND_MEAN 77#define WIN32_LEAN_AND_MEAN
78#include <windows.h> 78#include <windows.h>
79 79
80#if LJ_64 80#if LJ_64 && !LJ_GC64
81 81
82/* Undocumented, but hey, that's what we all love so much about Windows. */ 82/* Undocumented, but hey, that's what we all love so much about Windows. */
83typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG zbits, 83typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG zbits,
@@ -174,8 +174,10 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size)
174#endif 174#endif
175#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) 175#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
176 176
177#if LJ_64 177#if LJ_64 && !LJ_GC64
178/* 64 bit mode needs special support for allocating memory in the lower 2GB. */ 178/* 64 bit mode with 32 bit pointers needs special support for allocating
179** memory in the lower 2GB.
180*/
179 181
180#if defined(MAP_32BIT) 182#if defined(MAP_32BIT)
181 183
@@ -258,7 +260,7 @@ static LJ_AINLINE void *CALL_MMAP(size_t size)
258 260
259#else 261#else
260 262
261/* 32 bit mode is easy. */ 263/* 32 bit mode and GC64 mode is easy. */
262static LJ_AINLINE void *CALL_MMAP(size_t size) 264static LJ_AINLINE void *CALL_MMAP(size_t size)
263{ 265{
264 int olderr = errno; 266 int olderr = errno;
@@ -294,7 +296,7 @@ static LJ_AINLINE void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz,
294#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv)) 296#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
295#define CALL_MREMAP_NOMOVE 0 297#define CALL_MREMAP_NOMOVE 0
296#define CALL_MREMAP_MAYMOVE 1 298#define CALL_MREMAP_MAYMOVE 1
297#if LJ_64 299#if LJ_64 && !LJ_GC64
298#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE 300#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE
299#else 301#else
300#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE 302#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE
diff --git a/src/lj_api.c b/src/lj_api.c
index 6ad09b9d..f1843723 100644
--- a/src/lj_api.c
+++ b/src/lj_api.c
@@ -189,7 +189,7 @@ LUA_API int lua_type(lua_State *L, int idx)
189 cTValue *o = index2adr(L, idx); 189 cTValue *o = index2adr(L, idx);
190 if (tvisnumber(o)) { 190 if (tvisnumber(o)) {
191 return LUA_TNUMBER; 191 return LUA_TNUMBER;
192#if LJ_64 192#if LJ_64 && !LJ_GC64
193 } else if (tvislightud(o)) { 193 } else if (tvislightud(o)) {
194 return LUA_TLIGHTUSERDATA; 194 return LUA_TLIGHTUSERDATA;
195#endif 195#endif
@@ -269,7 +269,7 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
269 return 0; 269 return 0;
270 } else if (tvispri(o1)) { 270 } else if (tvispri(o1)) {
271 return o1 != niltv(L) && o2 != niltv(L); 271 return o1 != niltv(L) && o2 != niltv(L);
272#if LJ_64 272#if LJ_64 && !LJ_GC64
273 } else if (tvislightud(o1)) { 273 } else if (tvislightud(o1)) {
274 return o1->u64 == o2->u64; 274 return o1->u64 == o2->u64;
275#endif 275#endif
diff --git a/src/lj_arch.h b/src/lj_arch.h
index 8f3796fc..18555b41 100644
--- a/src/lj_arch.h
+++ b/src/lj_arch.h
@@ -365,11 +365,22 @@
365#endif 365#endif
366#endif 366#endif
367 367
368/* 64 bit GC references. */
369#if LJ_TARGET_GC64
370#define LJ_GC64 1
371#else
372#define LJ_GC64 0
373#endif
374
368/* 2-slot frame info. */ 375/* 2-slot frame info. */
376#if LJ_GC64
377#define LJ_FR2 1
378#else
369#define LJ_FR2 0 379#define LJ_FR2 0
380#endif
370 381
371/* Disable or enable the JIT compiler. */ 382/* Disable or enable the JIT compiler. */
372#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT) || LJ_FR2 383#if defined(LUAJIT_DISABLE_JIT) || defined(LJ_ARCH_NOJIT) || defined(LJ_OS_NOJIT) || LJ_FR2 || LJ_GC64
373#define LJ_HASJIT 0 384#define LJ_HASJIT 0
374#else 385#else
375#define LJ_HASJIT 1 386#define LJ_HASJIT 1
diff --git a/src/lj_def.h b/src/lj_def.h
index 93420ba5..f4231239 100644
--- a/src/lj_def.h
+++ b/src/lj_def.h
@@ -47,7 +47,9 @@ typedef unsigned int uintptr_t;
47 47
48/* Various VM limits. */ 48/* Various VM limits. */
49#define LJ_MAX_MEM32 0x7fffff00 /* Max. 32 bit memory allocation. */ 49#define LJ_MAX_MEM32 0x7fffff00 /* Max. 32 bit memory allocation. */
50#define LJ_MAX_MEM LJ_MAX_MEM32 /* Max. total memory allocation. */ 50#define LJ_MAX_MEM64 ((uint64_t)1<<47) /* Max. 64 bit memory allocation. */
51/* Max. total memory allocation. */
52#define LJ_MAX_MEM (LJ_GC64 ? LJ_MAX_MEM64 : LJ_MAX_MEM32)
51#define LJ_MAX_ALLOC LJ_MAX_MEM /* Max. individual allocation length. */ 53#define LJ_MAX_ALLOC LJ_MAX_MEM /* Max. individual allocation length. */
52#define LJ_MAX_STR LJ_MAX_MEM32 /* Max. string length. */ 54#define LJ_MAX_STR LJ_MAX_MEM32 /* Max. string length. */
53#define LJ_MAX_BUF LJ_MAX_MEM32 /* Max. buffer length. */ 55#define LJ_MAX_BUF LJ_MAX_MEM32 /* Max. buffer length. */
@@ -67,7 +69,7 @@ typedef unsigned int uintptr_t;
67#define LJ_MAX_UPVAL 60 /* Max. # of upvalues. */ 69#define LJ_MAX_UPVAL 60 /* Max. # of upvalues. */
68 70
69#define LJ_MAX_IDXCHAIN 100 /* __index/__newindex chain limit. */ 71#define LJ_MAX_IDXCHAIN 100 /* __index/__newindex chain limit. */
70#define LJ_STACK_EXTRA 5 /* Extra stack space (metamethods). */ 72#define LJ_STACK_EXTRA (5+2*LJ_FR2) /* Extra stack space (metamethods). */
71 73
72#define LJ_NUM_CBPAGE 1 /* Number of FFI callback pages. */ 74#define LJ_NUM_CBPAGE 1 /* Number of FFI callback pages. */
73 75
@@ -101,7 +103,14 @@ typedef unsigned int uintptr_t;
101#define checki32(x) ((x) == (int32_t)(x)) 103#define checki32(x) ((x) == (int32_t)(x))
102#define checku32(x) ((x) == (uint32_t)(x)) 104#define checku32(x) ((x) == (uint32_t)(x))
103#define checkptr32(x) ((uintptr_t)(x) == (uint32_t)(uintptr_t)(x)) 105#define checkptr32(x) ((uintptr_t)(x) == (uint32_t)(uintptr_t)(x))
104#define checkptrGC(x) (checkptr32(x)) 106#define checkptr47(x) (((uint64_t)(x) >> 47) == 0)
107#if LJ_GC64
108#define checkptrGC(x) (checkptr47((x)))
109#elif LJ_64
110#define checkptrGC(x) (checkptr32((x)))
111#else
112#define checkptrGC(x) 1
113#endif
105 114
106/* Every half-decent C compiler transforms this into a rotate instruction. */ 115/* Every half-decent C compiler transforms this into a rotate instruction. */
107#define lj_rol(x, n) (((x)<<(n)) | ((x)>>(-(int)(n)&(8*sizeof(x)-1)))) 116#define lj_rol(x, n) (((x)<<(n)) | ((x)>>(-(int)(n)&(8*sizeof(x)-1))))
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
index 55cdc63e..6bf26070 100644
--- a/src/lj_ffrecord.c
+++ b/src/lj_ffrecord.c
@@ -196,7 +196,7 @@ static void LJ_FASTCALL recff_type(jit_State *J, RecordFFData *rd)
196 uint32_t t; 196 uint32_t t;
197 if (tvisnumber(&rd->argv[0])) 197 if (tvisnumber(&rd->argv[0]))
198 t = ~LJ_TNUMX; 198 t = ~LJ_TNUMX;
199 else if (LJ_64 && tvislightud(&rd->argv[0])) 199 else if (LJ_64 && !LJ_GC64 && tvislightud(&rd->argv[0]))
200 t = ~LJ_TLIGHTUD; 200 t = ~LJ_TLIGHTUD;
201 else 201 else
202 t = ~itype(&rd->argv[0]); 202 t = ~itype(&rd->argv[0]);
diff --git a/src/lj_ir.c b/src/lj_ir.c
index 0689bc22..12d38909 100644
--- a/src/lj_ir.c
+++ b/src/lj_ir.c
@@ -307,6 +307,7 @@ TRef lj_ir_kgc(jit_State *J, GCobj *o, IRType t)
307{ 307{
308 IRIns *ir, *cir = J->cur.ir; 308 IRIns *ir, *cir = J->cur.ir;
309 IRRef ref; 309 IRRef ref;
310 lua_assert(!LJ_GC64); /* TODO_GC64: major changes required. */
310 lua_assert(!isdead(J2G(J), o)); 311 lua_assert(!isdead(J2G(J), o));
311 for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev) 312 for (ref = J->chain[IR_KGC]; ref; ref = cir[ref].prev)
312 if (ir_kgc(&cir[ref]) == o) 313 if (ir_kgc(&cir[ref]) == o)
diff --git a/src/lj_ir.h b/src/lj_ir.h
index 14b86165..bc89edf9 100644
--- a/src/lj_ir.h
+++ b/src/lj_ir.h
@@ -320,6 +320,7 @@ IRTDEF(IRTENUM)
320 IRT_PTR = LJ_64 ? IRT_P64 : IRT_P32, 320 IRT_PTR = LJ_64 ? IRT_P64 : IRT_P32,
321 IRT_INTP = LJ_64 ? IRT_I64 : IRT_INT, 321 IRT_INTP = LJ_64 ? IRT_I64 : IRT_INT,
322 IRT_UINTP = LJ_64 ? IRT_U64 : IRT_U32, 322 IRT_UINTP = LJ_64 ? IRT_U64 : IRT_U32,
323 /* TODO_GC64: major changes required for all uses of IRT_P32. */
323 324
324 /* Additional flags. */ 325 /* Additional flags. */
325 IRT_MARK = 0x20, /* Marker for misc. purposes. */ 326 IRT_MARK = 0x20, /* Marker for misc. purposes. */
@@ -371,7 +372,12 @@ typedef struct IRType1 { uint8_t irt; } IRType1;
371#define irt_isaddr(t) (irt_typerange((t), IRT_LIGHTUD, IRT_UDATA)) 372#define irt_isaddr(t) (irt_typerange((t), IRT_LIGHTUD, IRT_UDATA))
372#define irt_isint64(t) (irt_typerange((t), IRT_I64, IRT_U64)) 373#define irt_isint64(t) (irt_typerange((t), IRT_I64, IRT_U64))
373 374
374#if LJ_64 375#if LJ_GC64
376#define IRT_IS64 \
377 ((1u<<IRT_NUM)|(1u<<IRT_I64)|(1u<<IRT_U64)|(1u<<IRT_P64)|\
378 (1u<<IRT_LIGHTUD)|(1u<<IRT_STR)|(1u<<IRT_THREAD)|(1u<<IRT_PROTO)|\
379 (1u<<IRT_FUNC)|(1u<<IRT_CDATA)|(1u<<IRT_TAB)|(1u<<IRT_UDATA))
380#elif LJ_64
375#define IRT_IS64 \ 381#define IRT_IS64 \
376 ((1u<<IRT_NUM)|(1u<<IRT_I64)|(1u<<IRT_U64)|(1u<<IRT_P64)|(1u<<IRT_LIGHTUD)) 382 ((1u<<IRT_NUM)|(1u<<IRT_I64)|(1u<<IRT_U64)|(1u<<IRT_P64)|(1u<<IRT_LIGHTUD))
377#else 383#else
@@ -392,7 +398,7 @@ static LJ_AINLINE IRType itype2irt(const TValue *tv)
392 return IRT_INT; 398 return IRT_INT;
393 else if (tvisnum(tv)) 399 else if (tvisnum(tv))
394 return IRT_NUM; 400 return IRT_NUM;
395#if LJ_64 401#if LJ_64 && !LJ_GC64
396 else if (tvislightud(tv)) 402 else if (tvislightud(tv))
397 return IRT_LIGHTUD; 403 return IRT_LIGHTUD;
398#endif 404#endif
@@ -547,6 +553,7 @@ typedef union IRIns {
547 MRef ptr; /* Pointer constant (overlaps op12). */ 553 MRef ptr; /* Pointer constant (overlaps op12). */
548} IRIns; 554} IRIns;
549 555
556/* TODO_GC64: major changes required. */
550#define ir_kgc(ir) check_exp((ir)->o == IR_KGC, gcref((ir)->gcr)) 557#define ir_kgc(ir) check_exp((ir)->o == IR_KGC, gcref((ir)->gcr))
551#define ir_kstr(ir) (gco2str(ir_kgc((ir)))) 558#define ir_kstr(ir) (gco2str(ir_kgc((ir))))
552#define ir_ktab(ir) (gco2tab(ir_kgc((ir)))) 559#define ir_ktab(ir) (gco2tab(ir_kgc((ir))))
diff --git a/src/lj_jit.h b/src/lj_jit.h
index 4246e9db..ed92f62d 100644
--- a/src/lj_jit.h
+++ b/src/lj_jit.h
@@ -213,6 +213,9 @@ typedef struct GCtrace {
213 uint8_t topslot; /* Top stack slot already checked to be allocated. */ 213 uint8_t topslot; /* Top stack slot already checked to be allocated. */
214 uint8_t linktype; /* Type of link. */ 214 uint8_t linktype; /* Type of link. */
215 IRRef nins; /* Next IR instruction. Biased with REF_BIAS. */ 215 IRRef nins; /* Next IR instruction. Biased with REF_BIAS. */
216#if LJ_GC64
217 uint32_t unused_gc64;
218#endif
216 GCRef gclist; 219 GCRef gclist;
217 IRIns *ir; /* IR instructions/constants. Biased with REF_BIAS. */ 220 IRIns *ir; /* IR instructions/constants. Biased with REF_BIAS. */
218 IRRef nk; /* Lowest IR constant. Biased with REF_BIAS. */ 221 IRRef nk; /* Lowest IR constant. Biased with REF_BIAS. */
diff --git a/src/lj_lib.h b/src/lj_lib.h
index dff99c09..95e4d4a6 100644
--- a/src/lj_lib.h
+++ b/src/lj_lib.h
@@ -47,7 +47,10 @@ LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg);
47LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); 47LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst);
48 48
49/* Avoid including lj_frame.h. */ 49/* Avoid including lj_frame.h. */
50#if LJ_FR2 50#if LJ_GC64
51#define lj_lib_upvalue(L, n) \
52 (&gcval(L->base-2)->fn.c.upvalue[(n)-1])
53#elif LJ_FR2
51#define lj_lib_upvalue(L, n) \ 54#define lj_lib_upvalue(L, n) \
52 (&gcref((L->base-2)->gcr)->fn.c.upvalue[(n)-1]) 55 (&gcref((L->base-2)->gcr)->fn.c.upvalue[(n)-1])
53#else 56#else
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. */
19typedef uint32_t MSize; 19typedef uint32_t MSize;
20#if LJ_GC64
21typedef uint64_t GCSize;
22#else
20typedef uint32_t GCSize; 23typedef uint32_t GCSize;
24#endif
21 25
22/* Memory reference */ 26/* Memory reference */
23typedef struct MRef { 27typedef 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 */
35typedef struct GCRef { 50typedef 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 {
138typedef LJ_ALIGN(8) union TValue { 172typedef 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
412LJ_STATIC_ASSERT(offsetof(Node, val) == 0); 475LJ_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
731static LJ_AINLINE void setlightudV(TValue *o, void *p) 822static 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
760static LJ_AINLINE void setgcVraw(TValue *o, GCobj *v, uint32_t itype) 853static 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
765static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it) 862static LJ_AINLINE void setgcV(lua_State *L, TValue *o, GCobj *v, uint32_t it)
diff --git a/src/lj_snap.c b/src/lj_snap.c
index 4bac2d28..abc943b7 100644
--- a/src/lj_snap.c
+++ b/src/lj_snap.c
@@ -602,6 +602,7 @@ static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex,
602 } 602 }
603 if (LJ_UNLIKELY(bloomtest(rfilt, ref))) 603 if (LJ_UNLIKELY(bloomtest(rfilt, ref)))
604 rs = snap_renameref(T, snapno, ref, rs); 604 rs = snap_renameref(T, snapno, ref, rs);
605 lua_assert(!LJ_GC64); /* TODO_GC64: handle 64 bit references. */
605 if (ra_hasspill(regsp_spill(rs))) { /* Restore from spill slot. */ 606 if (ra_hasspill(regsp_spill(rs))) { /* Restore from spill slot. */
606 int32_t *sps = &ex->spill[regsp_spill(rs)]; 607 int32_t *sps = &ex->spill[regsp_spill(rs)];
607 if (irt_isinteger(t)) { 608 if (irt_isinteger(t)) {
diff --git a/src/lj_state.c b/src/lj_state.c
index f7cdb8f3..2b19b747 100644
--- a/src/lj_state.c
+++ b/src/lj_state.c
@@ -207,7 +207,9 @@ LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
207 setnilV(registry(L)); 207 setnilV(registry(L));
208 setnilV(&g->nilnode.val); 208 setnilV(&g->nilnode.val);
209 setnilV(&g->nilnode.key); 209 setnilV(&g->nilnode.key);
210#if !LJ_GC64
210 setmref(g->nilnode.freetop, &g->nilnode); 211 setmref(g->nilnode.freetop, &g->nilnode);
212#endif
211 lj_buf_init(NULL, &g->tmpbuf); 213 lj_buf_init(NULL, &g->tmpbuf);
212 g->gc.state = GCSpause; 214 g->gc.state = GCSpause;
213 setgcref(g->gc.root, obj2gco(L)); 215 setgcref(g->gc.root, obj2gco(L));
diff --git a/src/lj_tab.c b/src/lj_tab.c
index ef19ba97..b6bb7805 100644
--- a/src/lj_tab.c
+++ b/src/lj_tab.c
@@ -29,7 +29,12 @@ static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash)
29#define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi))) 29#define hashlohi(t, lo, hi) hashmask((t), hashrot((lo), (hi)))
30#define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1)) 30#define hashnum(t, o) hashlohi((t), (o)->u32.lo, ((o)->u32.hi << 1))
31#define hashptr(t, p) hashlohi((t), u32ptr(p), u32ptr(p) + HASH_BIAS) 31#define hashptr(t, p) hashlohi((t), u32ptr(p), u32ptr(p) + HASH_BIAS)
32#if LJ_GC64
33#define hashgcref(t, r) \
34 hashlohi((t), (uint32_t)gcrefu(r), (uint32_t)(gcrefu(r) >> 32))
35#else
32#define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS) 36#define hashgcref(t, r) hashlohi((t), gcrefu(r), gcrefu(r) + HASH_BIAS)
37#endif
33 38
34/* Hash an arbitrary key and return its anchor position in the hash table. */ 39/* Hash an arbitrary key and return its anchor position in the hash table. */
35static Node *hashkey(const GCtab *t, cTValue *key) 40static Node *hashkey(const GCtab *t, cTValue *key)
@@ -58,8 +63,8 @@ static LJ_AINLINE void newhpart(lua_State *L, GCtab *t, uint32_t hbits)
58 lj_err_msg(L, LJ_ERR_TABOV); 63 lj_err_msg(L, LJ_ERR_TABOV);
59 hsize = 1u << hbits; 64 hsize = 1u << hbits;
60 node = lj_mem_newvec(L, hsize, Node); 65 node = lj_mem_newvec(L, hsize, Node);
61 setmref(node->freetop, &node[hsize]);
62 setmref(t->node, node); 66 setmref(t->node, node);
67 setfreetop(t, node, &node[hsize]);
63 t->hmask = hsize-1; 68 t->hmask = hsize-1;
64} 69}
65 70
@@ -98,6 +103,7 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
98 GCtab *t; 103 GCtab *t;
99 /* First try to colocate the array part. */ 104 /* First try to colocate the array part. */
100 if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) { 105 if (LJ_MAX_COLOSIZE != 0 && asize > 0 && asize <= LJ_MAX_COLOSIZE) {
106 Node *nilnode;
101 lua_assert((sizeof(GCtab) & 7) == 0); 107 lua_assert((sizeof(GCtab) & 7) == 0);
102 t = (GCtab *)lj_mem_newgco(L, sizetabcolo(asize)); 108 t = (GCtab *)lj_mem_newgco(L, sizetabcolo(asize));
103 t->gct = ~LJ_TTAB; 109 t->gct = ~LJ_TTAB;
@@ -107,8 +113,13 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
107 setgcrefnull(t->metatable); 113 setgcrefnull(t->metatable);
108 t->asize = asize; 114 t->asize = asize;
109 t->hmask = 0; 115 t->hmask = 0;
110 setmref(t->node, &G(L)->nilnode); 116 nilnode = &G(L)->nilnode;
117 setmref(t->node, nilnode);
118#if LJ_GC64
119 setmref(t->freetop, nilnode);
120#endif
111 } else { /* Otherwise separately allocate the array part. */ 121 } else { /* Otherwise separately allocate the array part. */
122 Node *nilnode;
112 t = lj_mem_newobj(L, GCtab); 123 t = lj_mem_newobj(L, GCtab);
113 t->gct = ~LJ_TTAB; 124 t->gct = ~LJ_TTAB;
114 t->nomm = (uint8_t)~0; 125 t->nomm = (uint8_t)~0;
@@ -117,7 +128,11 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
117 setgcrefnull(t->metatable); 128 setgcrefnull(t->metatable);
118 t->asize = 0; /* In case the array allocation fails. */ 129 t->asize = 0; /* In case the array allocation fails. */
119 t->hmask = 0; 130 t->hmask = 0;
120 setmref(t->node, &G(L)->nilnode); 131 nilnode = &G(L)->nilnode;
132 setmref(t->node, nilnode);
133#if LJ_GC64
134 setmref(t->freetop, nilnode);
135#endif
121 if (asize > 0) { 136 if (asize > 0) {
122 if (asize > LJ_MAX_ASIZE) 137 if (asize > LJ_MAX_ASIZE)
123 lj_err_msg(L, LJ_ERR_TABOV); 138 lj_err_msg(L, LJ_ERR_TABOV);
@@ -191,7 +206,7 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
191 Node *node = noderef(t->node); 206 Node *node = noderef(t->node);
192 Node *knode = noderef(kt->node); 207 Node *knode = noderef(kt->node);
193 ptrdiff_t d = (char *)node - (char *)knode; 208 ptrdiff_t d = (char *)node - (char *)knode;
194 setmref(node->freetop, (Node *)((char *)noderef(knode->freetop) + d)); 209 setfreetop(t, node, (Node *)((char *)getfreetop(kt, knode) + d));
195 for (i = 0; i <= hmask; i++) { 210 for (i = 0; i <= hmask; i++) {
196 Node *kn = &knode[i]; 211 Node *kn = &knode[i];
197 Node *n = &node[i]; 212 Node *n = &node[i];
@@ -210,7 +225,7 @@ void LJ_FASTCALL lj_tab_clear(GCtab *t)
210 clearapart(t); 225 clearapart(t);
211 if (t->hmask > 0) { 226 if (t->hmask > 0) {
212 Node *node = noderef(t->node); 227 Node *node = noderef(t->node);
213 setmref(node->freetop, &node[t->hmask+1]); 228 setfreetop(t, node, &node[t->hmask+1]);
214 clearhpart(t); 229 clearhpart(t);
215 } 230 }
216} 231}
@@ -264,6 +279,9 @@ static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
264 } else { 279 } else {
265 global_State *g = G(L); 280 global_State *g = G(L);
266 setmref(t->node, &g->nilnode); 281 setmref(t->node, &g->nilnode);
282#if LJ_GC64
283 setmref(t->freetop, &g->nilnode);
284#endif
267 t->hmask = 0; 285 t->hmask = 0;
268 } 286 }
269 if (asize < oldasize) { /* Array part shrinks? */ 287 if (asize < oldasize) { /* Array part shrinks? */
@@ -445,7 +463,7 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
445 Node *n = hashkey(t, key); 463 Node *n = hashkey(t, key);
446 if (!tvisnil(&n->val) || t->hmask == 0) { 464 if (!tvisnil(&n->val) || t->hmask == 0) {
447 Node *nodebase = noderef(t->node); 465 Node *nodebase = noderef(t->node);
448 Node *collide, *freenode = noderef(nodebase->freetop); 466 Node *collide, *freenode = getfreetop(t, nodebase);
449 lua_assert(freenode >= nodebase && freenode <= nodebase+t->hmask+1); 467 lua_assert(freenode >= nodebase && freenode <= nodebase+t->hmask+1);
450 do { 468 do {
451 if (freenode == nodebase) { /* No free node found? */ 469 if (freenode == nodebase) { /* No free node found? */
@@ -453,7 +471,7 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
453 return lj_tab_set(L, t, key); /* Retry key insertion. */ 471 return lj_tab_set(L, t, key); /* Retry key insertion. */
454 } 472 }
455 } while (!tvisnil(&(--freenode)->key)); 473 } while (!tvisnil(&(--freenode)->key));
456 setmref(nodebase->freetop, freenode); 474 setfreetop(t, nodebase, freenode);
457 lua_assert(freenode != &G(L)->nilnode); 475 lua_assert(freenode != &G(L)->nilnode);
458 collide = hashkey(t, &n->key); 476 collide = hashkey(t, &n->key);
459 if (collide != n) { /* Colliding node not the main node? */ 477 if (collide != n) { /* Colliding node not the main node? */