~ubuntu-branches/ubuntu/quantal/luajit/quantal

« back to all changes in this revision

Viewing changes to .pc/beta9_hotfix1.patch/src/lj_bcwrite.c

  • Committer: Package Import Robot
  • Author(s): Enrico Tassi
  • Date: 2012-02-04 13:52:02 UTC
  • Revision ID: package-import@ubuntu.com-20120204135202-nuga57uzxg0x89i1
Tags: 2.0.0~beta9+dfsg-2
* Added patch beta9_hotfix1
* Update copyright file to adhere to DEP5 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** Bytecode writer.
 
3
** Copyright (C) 2005-2011 Mike Pall. See Copyright Notice in luajit.h
 
4
*/
 
5
 
 
6
#define lj_bcwrite_c
 
7
#define LUA_CORE
 
8
 
 
9
#include "lj_obj.h"
 
10
#include "lj_gc.h"
 
11
#include "lj_str.h"
 
12
#include "lj_bc.h"
 
13
#if LJ_HASFFI
 
14
#include "lj_ctype.h"
 
15
#endif
 
16
#if LJ_HASJIT
 
17
#include "lj_dispatch.h"
 
18
#include "lj_jit.h"
 
19
#endif
 
20
#include "lj_bcdump.h"
 
21
#include "lj_vm.h"
 
22
 
 
23
/* Context for bytecode writer. */
 
24
typedef struct BCWriteCtx {
 
25
  SBuf sb;                      /* Output buffer. */
 
26
  lua_State *L;                 /* Lua state. */
 
27
  GCproto *pt;                  /* Root prototype. */
 
28
  lua_Writer wfunc;             /* Writer callback. */
 
29
  void *wdata;                  /* Writer callback data. */
 
30
  int strip;                    /* Strip debug info. */
 
31
  int status;                   /* Status from writer callback. */
 
32
} BCWriteCtx;
 
33
 
 
34
/* -- Output buffer handling ---------------------------------------------- */
 
35
 
 
36
/* Resize buffer if needed. */
 
37
static LJ_NOINLINE void bcwrite_resize(BCWriteCtx *ctx, MSize len)
 
38
{
 
39
  MSize sz = ctx->sb.sz * 2;
 
40
  while (ctx->sb.n + len > sz) sz = sz * 2;
 
41
  lj_str_resizebuf(ctx->L, &ctx->sb, sz);
 
42
}
 
43
 
 
44
/* Need a certain amount of buffer space. */
 
45
static LJ_AINLINE void bcwrite_need(BCWriteCtx *ctx, MSize len)
 
46
{
 
47
  if (LJ_UNLIKELY(ctx->sb.n + len > ctx->sb.sz))
 
48
    bcwrite_resize(ctx, len);
 
49
}
 
50
 
 
51
/* Add memory block to buffer. */
 
52
static void bcwrite_block(BCWriteCtx *ctx, const void *p, MSize len)
 
53
{
 
54
  uint8_t *q = (uint8_t *)(ctx->sb.buf + ctx->sb.n);
 
55
  MSize i;
 
56
  ctx->sb.n += len;
 
57
  for (i = 0; i < len; i++) q[i] = ((uint8_t *)p)[i];
 
58
}
 
59
 
 
60
/* Add byte to buffer. */
 
61
static LJ_AINLINE void bcwrite_byte(BCWriteCtx *ctx, uint8_t b)
 
62
{
 
63
  ctx->sb.buf[ctx->sb.n++] = b;
 
64
}
 
65
 
 
66
/* Add ULEB128 value to buffer. */
 
67
static void bcwrite_uleb128(BCWriteCtx *ctx, uint32_t v)
 
68
{
 
69
  MSize n = ctx->sb.n;
 
70
  uint8_t *p = (uint8_t *)ctx->sb.buf;
 
71
  for (; v >= 0x80; v >>= 7)
 
72
    p[n++] = (uint8_t)((v & 0x7f) | 0x80);
 
73
  p[n++] = (uint8_t)v;
 
74
  ctx->sb.n = n;
 
75
}
 
76
 
 
77
/* -- Bytecode writer ----------------------------------------------------- */
 
78
 
 
79
/* Write a single constant key/value of a template table. */
 
80
static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
 
81
{
 
82
  bcwrite_need(ctx, 1+10);
 
83
  if (tvisstr(o)) {
 
84
    const GCstr *str = strV(o);
 
85
    MSize len = str->len;
 
86
    bcwrite_need(ctx, 5+len);
 
87
    bcwrite_uleb128(ctx, BCDUMP_KTAB_STR+len);
 
88
    bcwrite_block(ctx, strdata(str), len);
 
89
  } else if (tvisint(o)) {
 
90
    bcwrite_byte(ctx, BCDUMP_KTAB_INT);
 
91
    bcwrite_uleb128(ctx, intV(o));
 
92
  } else if (tvisnum(o)) {
 
93
    if (!LJ_DUALNUM && narrow) {  /* Narrow number constants to integers. */
 
94
      lua_Number num = numV(o);
 
95
      int32_t k = lj_num2int(num);
 
96
      if (num == (lua_Number)k) {  /* -0 is never a constant. */
 
97
        bcwrite_byte(ctx, BCDUMP_KTAB_INT);
 
98
        bcwrite_uleb128(ctx, k);
 
99
        return;
 
100
      }
 
101
    }
 
102
    bcwrite_byte(ctx, BCDUMP_KTAB_NUM);
 
103
    bcwrite_uleb128(ctx, o->u32.lo);
 
104
    bcwrite_uleb128(ctx, o->u32.hi);
 
105
  } else {
 
106
    lua_assert(tvispri(o));
 
107
    bcwrite_byte(ctx, BCDUMP_KTAB_NIL+~itype(o));
 
108
  }
 
109
}
 
110
 
 
111
/* Write a template table. */
 
112
static void bcwrite_ktab(BCWriteCtx *ctx, const GCtab *t)
 
113
{
 
114
  MSize narray = 0, nhash = 0;
 
115
  if (t->asize > 0) {  /* Determine max. length of array part. */
 
116
    ptrdiff_t i;
 
117
    TValue *array = tvref(t->array);
 
118
    for (i = (ptrdiff_t)t->asize-1; i >= 0; i--)
 
119
      if (!tvisnil(&array[i]))
 
120
        break;
 
121
    narray = (MSize)(i+1);
 
122
  }
 
123
  if (t->hmask > 0) {  /* Count number of used hash slots. */
 
124
    MSize i, hmask = t->hmask;
 
125
    Node *node = noderef(t->node);
 
126
    for (i = 0; i <= hmask; i++)
 
127
      nhash += !tvisnil(&node[i].val);
 
128
  }
 
129
  /* Write number of array slots and hash slots. */
 
130
  bcwrite_uleb128(ctx, narray);
 
131
  bcwrite_uleb128(ctx, nhash);
 
132
  if (narray) {  /* Write array entries (may contain nil). */
 
133
    MSize i;
 
134
    TValue *o = tvref(t->array);
 
135
    for (i = 0; i < narray; i++, o++)
 
136
      bcwrite_ktabk(ctx, o, 1);
 
137
  }
 
138
  if (nhash) {  /* Write hash entries. */
 
139
    MSize i = nhash;
 
140
    Node *node = noderef(t->node) + t->hmask;
 
141
    for (;; node--)
 
142
      if (!tvisnil(&node->val)) {
 
143
        bcwrite_ktabk(ctx, &node->key, 0);
 
144
        bcwrite_ktabk(ctx, &node->val, 1);
 
145
        if (--i == 0) break;
 
146
      }
 
147
  }
 
148
}
 
149
 
 
150
/* Write GC constants of a prototype. */
 
151
static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
 
152
{
 
153
  MSize i, sizekgc = pt->sizekgc;
 
154
  GCRef *kr = mref(pt->k, GCRef) - (ptrdiff_t)sizekgc;
 
155
  for (i = 0; i < sizekgc; i++, kr++) {
 
156
    GCobj *o = gcref(*kr);
 
157
    MSize tp, need = 1;
 
158
    /* Determine constant type and needed size. */
 
159
    if (o->gch.gct == ~LJ_TSTR) {
 
160
      tp = BCDUMP_KGC_STR + gco2str(o)->len;
 
161
      need = 5+gco2str(o)->len;
 
162
    } else if (o->gch.gct == ~LJ_TPROTO) {
 
163
      lua_assert((pt->flags & PROTO_CHILD));
 
164
      tp = BCDUMP_KGC_CHILD;
 
165
#if LJ_HASFFI
 
166
    } else if (o->gch.gct == ~LJ_TCDATA) {
 
167
      CTypeID id = gco2cd(o)->typeid;
 
168
      need = 1+4*5;
 
169
      if (id == CTID_INT64) {
 
170
        tp = BCDUMP_KGC_I64;
 
171
      } else if (id == CTID_UINT64) {
 
172
        tp = BCDUMP_KGC_U64;
 
173
      } else {
 
174
        lua_assert(id == CTID_COMPLEX_DOUBLE);
 
175
        tp = BCDUMP_KGC_COMPLEX;
 
176
      }
 
177
#endif
 
178
    } else {
 
179
      lua_assert(o->gch.gct == ~LJ_TTAB);
 
180
      tp = BCDUMP_KGC_TAB;
 
181
    }
 
182
    /* Write constant type. */
 
183
    bcwrite_need(ctx, need);
 
184
    bcwrite_uleb128(ctx, tp);
 
185
    /* Write constant data (if any). */
 
186
    if (tp >= BCDUMP_KGC_STR) {
 
187
      bcwrite_block(ctx, strdata(gco2str(o)), gco2str(o)->len);
 
188
    } else if (tp == BCDUMP_KGC_TAB) {
 
189
      bcwrite_ktab(ctx, gco2tab(o));
 
190
#if LJ_HASFFI
 
191
    } else if (tp != BCDUMP_KGC_CHILD) {
 
192
      cTValue *p = (TValue *)cdataptr(gco2cd(o));
 
193
      bcwrite_uleb128(ctx, p[0].u32.lo);
 
194
      bcwrite_uleb128(ctx, p[0].u32.hi);
 
195
      if (tp == BCDUMP_KGC_COMPLEX) {
 
196
        bcwrite_uleb128(ctx, p[1].u32.lo);
 
197
        bcwrite_uleb128(ctx, p[1].u32.hi);
 
198
      }
 
199
#endif
 
200
    }
 
201
  }
 
202
}
 
203
 
 
204
/* Write number constants of a prototype. */
 
205
static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt)
 
206
{
 
207
  MSize i, sizekn = pt->sizekn;
 
208
  cTValue *o = mref(pt->k, TValue);
 
209
  bcwrite_need(ctx, 10*sizekn);
 
210
  for (i = 0; i < sizekn; i++, o++) {
 
211
    int32_t k;
 
212
    if (tvisint(o)) {
 
213
      k = intV(o);
 
214
      goto save_int;
 
215
    } else {
 
216
      /* Write a 33 bit ULEB128 for the int (lsb=0) or loword (lsb=1). */
 
217
      if (!LJ_DUALNUM) {  /* Narrow number constants to integers. */
 
218
        lua_Number num = numV(o);
 
219
        k = lj_num2int(num);
 
220
        if (num == (lua_Number)k) {  /* -0 is never a constant. */
 
221
        save_int:
 
222
          bcwrite_uleb128(ctx, 2*(uint32_t)k);
 
223
          if (k < 0) ctx->sb.buf[ctx->sb.n-1] |= 0x10;
 
224
          continue;
 
225
        }
 
226
      }
 
227
      bcwrite_uleb128(ctx, 1+2*o->u32.lo);
 
228
      if (o->u32.lo >= 0x80000000u) ctx->sb.buf[ctx->sb.n-1] |= 0x10;
 
229
      bcwrite_uleb128(ctx, o->u32.hi);
 
230
    }
 
231
  }
 
232
}
 
233
 
 
234
/* Write bytecode instructions. */
 
235
static void bcwrite_bytecode(BCWriteCtx *ctx, GCproto *pt)
 
236
{
 
237
  MSize nbc = pt->sizebc-1;  /* Omit the [JI]FUNC* header. */
 
238
#if LJ_HASJIT
 
239
  uint8_t *p = (uint8_t *)&ctx->sb.buf[ctx->sb.n];
 
240
#endif
 
241
  bcwrite_block(ctx, proto_bc(pt)+1, nbc*(MSize)sizeof(BCIns));
 
242
#if LJ_HASJIT
 
243
  /* Unpatch modified bytecode containing ILOOP/JLOOP etc. */
 
244
  if ((pt->flags & PROTO_ILOOP) || pt->trace) {
 
245
    jit_State *J = L2J(ctx->L);
 
246
    MSize i;
 
247
    for (i = 0; i < nbc; i++, p += sizeof(BCIns)) {
 
248
      BCOp op = (BCOp)p[LJ_ENDIAN_SELECT(0, 3)];
 
249
      if (op == BC_IFORL || op == BC_IITERL || op == BC_ILOOP ||
 
250
          op == BC_JFORI) {
 
251
        p[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_IFORL+BC_FORL);
 
252
      } else if (op == BC_JFORL || op == BC_JITERL || op == BC_JLOOP) {
 
253
        BCReg rd = p[LJ_ENDIAN_SELECT(2, 1)] + (p[LJ_ENDIAN_SELECT(3, 0)] << 8);
 
254
        BCIns ins = traceref(J, rd)->startins;
 
255
        p[LJ_ENDIAN_SELECT(0, 3)] = (uint8_t)(op-BC_JFORL+BC_FORL);
 
256
        p[LJ_ENDIAN_SELECT(2, 1)] = bc_c(ins);
 
257
        p[LJ_ENDIAN_SELECT(3, 0)] = bc_b(ins);
 
258
      }
 
259
    }
 
260
  }
 
261
#endif
 
262
}
 
263
 
 
264
/* Write prototype. */
 
265
static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
 
266
{
 
267
  MSize sizedbg = 0;
 
268
 
 
269
  /* Recursively write children of prototype. */
 
270
  if ((pt->flags & PROTO_CHILD)) {
 
271
    ptrdiff_t i, n = pt->sizekgc;
 
272
    GCRef *kr = mref(pt->k, GCRef) - 1;
 
273
    for (i = 0; i < n; i++, kr--) {
 
274
      GCobj *o = gcref(*kr);
 
275
      if (o->gch.gct == ~LJ_TPROTO)
 
276
        bcwrite_proto(ctx, gco2pt(o));
 
277
    }
 
278
  }
 
279
 
 
280
  /* Start writing the prototype info to a buffer. */
 
281
  lj_str_resetbuf(&ctx->sb);
 
282
  ctx->sb.n = 5;  /* Leave room for final size. */
 
283
  bcwrite_need(ctx, 4+6*5+(pt->sizebc-1)*(MSize)sizeof(BCIns)+pt->sizeuv*2);
 
284
 
 
285
  /* Write prototype header. */
 
286
  bcwrite_byte(ctx, (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI)));
 
287
  bcwrite_byte(ctx, pt->numparams);
 
288
  bcwrite_byte(ctx, pt->framesize);
 
289
  bcwrite_byte(ctx, pt->sizeuv);
 
290
  bcwrite_uleb128(ctx, pt->sizekgc);
 
291
  bcwrite_uleb128(ctx, pt->sizekn);
 
292
  bcwrite_uleb128(ctx, pt->sizebc-1);
 
293
  if (!ctx->strip) {
 
294
    if (proto_lineinfo(pt))
 
295
      sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt);
 
296
    bcwrite_uleb128(ctx, sizedbg);
 
297
    if (sizedbg) {
 
298
      bcwrite_uleb128(ctx, pt->firstline);
 
299
      bcwrite_uleb128(ctx, pt->numline);
 
300
    }
 
301
  }
 
302
 
 
303
  /* Write bytecode instructions and upvalue refs. */
 
304
  bcwrite_bytecode(ctx, pt);
 
305
  bcwrite_block(ctx, proto_uv(pt), pt->sizeuv*2);
 
306
 
 
307
  /* Write constants. */
 
308
  bcwrite_kgc(ctx, pt);
 
309
  bcwrite_knum(ctx, pt);
 
310
 
 
311
  /* Write debug info, if not stripped. */
 
312
  if (sizedbg) {
 
313
    bcwrite_need(ctx, sizedbg);
 
314
    bcwrite_block(ctx, proto_lineinfo(pt), sizedbg);
 
315
  }
 
316
 
 
317
  /* Pass buffer to writer function. */
 
318
  if (ctx->status == 0) {
 
319
    MSize n = ctx->sb.n - 5;
 
320
    MSize nn = 1 + lj_fls(n)/7;
 
321
    ctx->sb.n = 5 - nn;
 
322
    bcwrite_uleb128(ctx, n);  /* Fill in final size. */
 
323
    lua_assert(ctx->sb.n == 5);
 
324
    ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf+5-nn, nn+n, ctx->wdata);
 
325
  }
 
326
}
 
327
 
 
328
/* Write header of bytecode dump. */
 
329
static void bcwrite_header(BCWriteCtx *ctx)
 
330
{
 
331
  GCstr *chunkname = proto_chunkname(ctx->pt);
 
332
  const char *name = strdata(chunkname);
 
333
  MSize len = chunkname->len;
 
334
  lj_str_resetbuf(&ctx->sb);
 
335
  bcwrite_need(ctx, 5+5+len);
 
336
  bcwrite_byte(ctx, BCDUMP_HEAD1);
 
337
  bcwrite_byte(ctx, BCDUMP_HEAD2);
 
338
  bcwrite_byte(ctx, BCDUMP_HEAD3);
 
339
  bcwrite_byte(ctx, BCDUMP_VERSION);
 
340
  bcwrite_byte(ctx, (ctx->strip ? BCDUMP_F_STRIP : 0) +
 
341
                   (LJ_BE ? BCDUMP_F_BE : 0) +
 
342
                   ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0));
 
343
  if (!ctx->strip) {
 
344
    bcwrite_uleb128(ctx, len);
 
345
    bcwrite_block(ctx, name, len);
 
346
  }
 
347
  ctx->status = ctx->wfunc(ctx->L, ctx->sb.buf, ctx->sb.n, ctx->wdata);
 
348
}
 
349
 
 
350
/* Write footer of bytecode dump. */
 
351
static void bcwrite_footer(BCWriteCtx *ctx)
 
352
{
 
353
  if (ctx->status == 0) {
 
354
    uint8_t zero = 0;
 
355
    ctx->status = ctx->wfunc(ctx->L, &zero, 1, ctx->wdata);
 
356
  }
 
357
}
 
358
 
 
359
/* Protected callback for bytecode writer. */
 
360
static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud)
 
361
{
 
362
  BCWriteCtx *ctx = (BCWriteCtx *)ud;
 
363
  UNUSED(dummy);
 
364
  lj_str_resizebuf(L, &ctx->sb, 1024);  /* Avoids resize for most prototypes. */
 
365
  bcwrite_header(ctx);
 
366
  bcwrite_proto(ctx, ctx->pt);
 
367
  bcwrite_footer(ctx);
 
368
  return NULL;
 
369
}
 
370
 
 
371
/* Write bytecode for a prototype. */
 
372
int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data,
 
373
              int strip)
 
374
{
 
375
  BCWriteCtx ctx;
 
376
  int status;
 
377
  ctx.L = L;
 
378
  ctx.pt = pt;
 
379
  ctx.wfunc = writer;
 
380
  ctx.wdata = data;
 
381
  ctx.strip = strip;
 
382
  ctx.status = 0;
 
383
  lj_str_initbuf(&ctx.sb);
 
384
  status = lj_vm_cpcall(L, NULL, &ctx, cpwriter);
 
385
  if (status == 0) status = ctx.status;
 
386
  lj_str_freebuf(G(ctx.L), &ctx.sb);
 
387
  return status;
 
388
}
 
389