aboutsummaryrefslogtreecommitdiff
path: root/src/lj_bcwrite.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_bcwrite.c109
1 files changed, 94 insertions, 15 deletions
diff --git a/src/lj_bcwrite.c b/src/lj_bcwrite.c
index dd969413..c062dc49 100644
--- a/src/lj_bcwrite.c
+++ b/src/lj_bcwrite.c
@@ -27,7 +27,9 @@ typedef struct BCWriteCtx {
27 GCproto *pt; /* Root prototype. */ 27 GCproto *pt; /* Root prototype. */
28 lua_Writer wfunc; /* Writer callback. */ 28 lua_Writer wfunc; /* Writer callback. */
29 void *wdata; /* Writer callback data. */ 29 void *wdata; /* Writer callback data. */
30 int strip; /* Strip debug info. */ 30 TValue **heap; /* Heap used for deterministic sorting. */
31 uint32_t heapsz; /* Size of heap. */
32 uint32_t flags; /* BCDUMP_F_* flags. */
31 int status; /* Status from writer callback. */ 33 int status; /* Status from writer callback. */
32#ifdef LUA_USE_ASSERT 34#ifdef LUA_USE_ASSERT
33 global_State *g; 35 global_State *g;
@@ -76,6 +78,75 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
76 ctx->sb.w = p; 78 ctx->sb.w = p;
77} 79}
78 80
81/* Compare two template table keys. */
82static LJ_AINLINE int bcwrite_ktabk_lt(TValue *a, TValue *b)
83{
84 uint32_t at = itype(a), bt = itype(b);
85 if (at != bt) { /* This also handles false and true keys. */
86 return at < bt;
87 } else if (at == LJ_TSTR) {
88 return lj_str_cmp(strV(a), strV(b)) < 0;
89 } else {
90 return a->u64 < b->u64; /* This works for numbers and integers. */
91 }
92}
93
94/* Insert key into a sorted heap. */
95static void bcwrite_ktabk_heap_insert(TValue **heap, MSize idx, MSize end,
96 TValue *key)
97{
98 MSize child;
99 while ((child = idx * 2 + 1) < end) {
100 /* Find lower of the two children. */
101 TValue *c0 = heap[child];
102 if (child + 1 < end) {
103 TValue *c1 = heap[child + 1];
104 if (bcwrite_ktabk_lt(c1, c0)) {
105 c0 = c1;
106 child++;
107 }
108 }
109 if (bcwrite_ktabk_lt(key, c0)) break; /* Key lower? Found our position. */
110 heap[idx] = c0; /* Move lower child up. */
111 idx = child; /* Descend. */
112 }
113 heap[idx] = key; /* Insert key here. */
114}
115
116/* Resize heap, dropping content. */
117static void bcwrite_heap_resize(BCWriteCtx *ctx, uint32_t nsz)
118{
119 lua_State *L = sbufL(&ctx->sb);
120 if (ctx->heapsz) {
121 lj_mem_freevec(G(L), ctx->heap, ctx->heapsz, TValue *);
122 ctx->heapsz = 0;
123 }
124 if (nsz) {
125 ctx->heap = lj_mem_newvec(L, nsz, TValue *);
126 ctx->heapsz = nsz;
127 }
128}
129
130/* Write hash part of template table in sorted order. */
131static void bcwrite_ktab_sorted_hash(BCWriteCtx *ctx, Node *node, MSize nhash)
132{
133 TValue **heap = ctx->heap;
134 MSize i = nhash;
135 for (;; node--) { /* Build heap. */
136 if (!tvisnil(&node->val)) {
137 bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key);
138 if (i == 0) break;
139 }
140 }
141 do { /* Drain heap. */
142 TValue *key = heap[0]; /* Output lowest key from top. */
143 bcwrite_ktabk(ctx, key, 0);
144 bcwrite_ktabk(ctx, (TValue *)((char *)key - offsetof(Node, key)), 1);
145 key = heap[--nhash]; /* Remove last key. */
146 bcwrite_ktabk_heap_insert(heap, 0, nhash, key); /* Re-insert. */
147 } while (nhash);
148}
149
79/* Write a template table. */ 150/* Write a template table. */
80static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) 151static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
81{ 152{
@@ -105,14 +176,20 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
105 bcwrite_ktabk(ctx, o, 1); 176 bcwrite_ktabk(ctx, o, 1);
106 } 177 }
107 if (nhash) { /* Write hash entries. */ 178 if (nhash) { /* Write hash entries. */
108 MSize i = nhash;
109 Node *node = noderef(t->node) + t->hmask; 179 Node *node = noderef(t->node) + t->hmask;
110 for (;; node--) 180 if ((ctx->flags & BCDUMP_F_DETERMINISTIC) && nhash > 1) {
111 if (!tvisnil(&node->val)) { 181 if (ctx->heapsz < nhash)
112 bcwrite_ktabk(ctx, &node->key, 0); 182 bcwrite_heap_resize(ctx, t->hmask + 1);
113 bcwrite_ktabk(ctx, &node->val, 1); 183 bcwrite_ktab_sorted_hash(ctx, node, nhash);
114 if (--i == 0) break; 184 } else {
115 } 185 MSize i = nhash;
186 for (;; node--)
187 if (!tvisnil(&node->val)) {
188 bcwrite_ktabk(ctx, &node->key, 0);
189 bcwrite_ktabk(ctx, &node->val, 1);
190 if (--i == 0) break;
191 }
192 }
116 } 193 }
117} 194}
118 195
@@ -269,7 +346,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
269 p = lj_strfmt_wuleb128(p, pt->sizekgc); 346 p = lj_strfmt_wuleb128(p, pt->sizekgc);
270 p = lj_strfmt_wuleb128(p, pt->sizekn); 347 p = lj_strfmt_wuleb128(p, pt->sizekn);
271 p = lj_strfmt_wuleb128(p, pt->sizebc-1); 348 p = lj_strfmt_wuleb128(p, pt->sizebc-1);
272 if (!ctx->strip) { 349 if (!(ctx->flags & BCDUMP_F_STRIP)) {
273 if (proto_lineinfo(pt)) 350 if (proto_lineinfo(pt))
274 sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); 351 sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt);
275 p = lj_strfmt_wuleb128(p, sizedbg); 352 p = lj_strfmt_wuleb128(p, sizedbg);
@@ -317,11 +394,10 @@ static void bcwrite_header(BCWriteCtx *ctx)
317 *p++ = BCDUMP_HEAD2; 394 *p++ = BCDUMP_HEAD2;
318 *p++ = BCDUMP_HEAD3; 395 *p++ = BCDUMP_HEAD3;
319 *p++ = BCDUMP_VERSION; 396 *p++ = BCDUMP_VERSION;
320 *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) + 397 *p++ = (ctx->flags & (BCDUMP_F_STRIP | BCDUMP_F_FR2)) +
321 LJ_BE*BCDUMP_F_BE + 398 LJ_BE*BCDUMP_F_BE +
322 ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0) + 399 ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0);
323 LJ_FR2*BCDUMP_F_FR2; 400 if (!(ctx->flags & BCDUMP_F_STRIP)) {
324 if (!ctx->strip) {
325 p = lj_strfmt_wuleb128(p, len); 401 p = lj_strfmt_wuleb128(p, len);
326 p = lj_buf_wmem(p, name, len); 402 p = lj_buf_wmem(p, name, len);
327 } 403 }
@@ -352,14 +428,16 @@ static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud)
352 428
353/* Write bytecode for a prototype. */ 429/* Write bytecode for a prototype. */
354int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data, 430int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data,
355 int strip) 431 uint32_t flags)
356{ 432{
357 BCWriteCtx ctx; 433 BCWriteCtx ctx;
358 int status; 434 int status;
359 ctx.pt = pt; 435 ctx.pt = pt;
360 ctx.wfunc = writer; 436 ctx.wfunc = writer;
361 ctx.wdata = data; 437 ctx.wdata = data;
362 ctx.strip = strip; 438 ctx.heapsz = 0;
439 if ((bc_op(proto_bc(pt)[0]) != BC_NOT) == LJ_FR2) flags |= BCDUMP_F_FR2;
440 ctx.flags = flags;
363 ctx.status = 0; 441 ctx.status = 0;
364#ifdef LUA_USE_ASSERT 442#ifdef LUA_USE_ASSERT
365 ctx.g = G(L); 443 ctx.g = G(L);
@@ -368,6 +446,7 @@ int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data,
368 status = lj_vm_cpcall(L, NULL, &ctx, cpwriter); 446 status = lj_vm_cpcall(L, NULL, &ctx, cpwriter);
369 if (status == 0) status = ctx.status; 447 if (status == 0) status = ctx.status;
370 lj_buf_free(G(sbufL(&ctx.sb)), &ctx.sb); 448 lj_buf_free(G(sbufL(&ctx.sb)), &ctx.sb);
449 bcwrite_heap_resize(&ctx, 0);
371 return status; 450 return status;
372} 451}
373 452