lua/lvm.c
author Ryan C. Gordon <icculus@icculus.org>
Sun, 18 Jun 2017 19:50:43 -0400
changeset 57 4974e5368a29
parent 0 d7ee4e2ed49d
permissions -rw-r--r--
Minor type cleanup ("unsigned char" -> "uint8_t").
icculus@0
     1
/*
icculus@0
     2
** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 roberto Exp $
icculus@0
     3
** Lua virtual machine
icculus@0
     4
** See Copyright Notice in lua.h
icculus@0
     5
*/
icculus@0
     6
icculus@0
     7
icculus@0
     8
#include <stdio.h>
icculus@0
     9
#include <stdlib.h>
icculus@0
    10
#include <string.h>
icculus@0
    11
icculus@0
    12
#define lvm_c
icculus@0
    13
#define LUA_CORE
icculus@0
    14
icculus@0
    15
#include "lua.h"
icculus@0
    16
icculus@0
    17
#include "ldebug.h"
icculus@0
    18
#include "ldo.h"
icculus@0
    19
#include "lfunc.h"
icculus@0
    20
#include "lgc.h"
icculus@0
    21
#include "lobject.h"
icculus@0
    22
#include "lopcodes.h"
icculus@0
    23
#include "lstate.h"
icculus@0
    24
#include "lstring.h"
icculus@0
    25
#include "ltable.h"
icculus@0
    26
#include "ltm.h"
icculus@0
    27
#include "lvm.h"
icculus@0
    28
icculus@0
    29
icculus@0
    30
icculus@0
    31
/* limit for table tag-method chains (to avoid loops) */
icculus@0
    32
#define MAXTAGLOOP	100
icculus@0
    33
icculus@0
    34
icculus@0
    35
const TValue *luaV_tonumber (const TValue *obj, TValue *n) {
icculus@0
    36
  lua_Number num;
icculus@0
    37
  if (ttisnumber(obj)) return obj;
icculus@0
    38
  if (ttisstring(obj) && luaO_str2d(svalue(obj), tsvalue(obj)->len, &num)) {
icculus@0
    39
    setnvalue(n, num);
icculus@0
    40
    return n;
icculus@0
    41
  }
icculus@0
    42
  else
icculus@0
    43
    return NULL;
icculus@0
    44
}
icculus@0
    45
icculus@0
    46
icculus@0
    47
int luaV_tostring (lua_State *L, StkId obj) {
icculus@0
    48
  if (!ttisnumber(obj))
icculus@0
    49
    return 0;
icculus@0
    50
  else {
icculus@0
    51
    char s[LUAI_MAXNUMBER2STR];
icculus@0
    52
    lua_Number n = nvalue(obj);
icculus@0
    53
    int l = lua_number2str(s, n);
icculus@0
    54
    setsvalue2s(L, obj, luaS_newlstr(L, s, l));
icculus@0
    55
    return 1;
icculus@0
    56
  }
icculus@0
    57
}
icculus@0
    58
icculus@0
    59
icculus@0
    60
static void traceexec (lua_State *L) {
icculus@0
    61
  CallInfo *ci = L->ci;
icculus@0
    62
  lu_byte mask = L->hookmask;
icculus@0
    63
  int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0);
icculus@0
    64
  if (counthook)
icculus@0
    65
    resethookcount(L);  /* reset count */
icculus@0
    66
  if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
icculus@0
    67
    ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
icculus@0
    68
    return;  /* do not call hook again (VM yielded, so it did not move) */
icculus@0
    69
  }
icculus@0
    70
  if (counthook)
icculus@0
    71
    luaD_hook(L, LUA_HOOKCOUNT, -1);  /* call count hook */
icculus@0
    72
  if (mask & LUA_MASKLINE) {
icculus@0
    73
    Proto *p = ci_func(ci)->p;
icculus@0
    74
    int npc = pcRel(ci->u.l.savedpc, p);
icculus@0
    75
    int newline = getfuncline(p, npc);
icculus@0
    76
    if (npc == 0 ||  /* call linehook when enter a new function, */
icculus@0
    77
        ci->u.l.savedpc <= L->oldpc ||  /* when jump back (loop), or when */
icculus@0
    78
        newline != getfuncline(p, pcRel(L->oldpc, p)))  /* enter a new line */
icculus@0
    79
      luaD_hook(L, LUA_HOOKLINE, newline);  /* call line hook */
icculus@0
    80
  }
icculus@0
    81
  L->oldpc = ci->u.l.savedpc;
icculus@0
    82
  if (L->status == LUA_YIELD) {  /* did hook yield? */
icculus@0
    83
    if (counthook)
icculus@0
    84
      L->hookcount = 1;  /* undo decrement to zero */
icculus@0
    85
    ci->u.l.savedpc--;  /* undo increment (resume will increment it again) */
icculus@0
    86
    ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
icculus@0
    87
    ci->func = L->top - 1;  /* protect stack below results */
icculus@0
    88
    luaD_throw(L, LUA_YIELD);
icculus@0
    89
  }
icculus@0
    90
}
icculus@0
    91
icculus@0
    92
icculus@0
    93
static void callTM (lua_State *L, const TValue *f, const TValue *p1,
icculus@0
    94
                    const TValue *p2, TValue *p3, int hasres) {
icculus@0
    95
  ptrdiff_t result = savestack(L, p3);
icculus@0
    96
  setobj2s(L, L->top++, f);  /* push function */
icculus@0
    97
  setobj2s(L, L->top++, p1);  /* 1st argument */
icculus@0
    98
  setobj2s(L, L->top++, p2);  /* 2nd argument */
icculus@0
    99
  if (!hasres)  /* no result? 'p3' is third argument */
icculus@0
   100
    setobj2s(L, L->top++, p3);  /* 3rd argument */
icculus@0
   101
  /* metamethod may yield only when called from Lua code */
icculus@0
   102
  luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci));
icculus@0
   103
  if (hasres) {  /* if has result, move it to its place */
icculus@0
   104
    p3 = restorestack(L, result);
icculus@0
   105
    setobjs2s(L, p3, --L->top);
icculus@0
   106
  }
icculus@0
   107
}
icculus@0
   108
icculus@0
   109
icculus@0
   110
void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {
icculus@0
   111
  int loop;
icculus@0
   112
  for (loop = 0; loop < MAXTAGLOOP; loop++) {
icculus@0
   113
    const TValue *tm;
icculus@0
   114
    if (ttistable(t)) {  /* `t' is a table? */
icculus@0
   115
      Table *h = hvalue(t);
icculus@0
   116
      const TValue *res = luaH_get(h, key); /* do a primitive get */
icculus@0
   117
      if (!ttisnil(res) ||  /* result is not nil? */
icculus@0
   118
          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */
icculus@0
   119
        setobj2s(L, val, res);
icculus@0
   120
        return;
icculus@0
   121
      }
icculus@0
   122
      /* else will try the tag method */
icculus@0
   123
    }
icculus@0
   124
    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))
icculus@0
   125
      luaG_typeerror(L, t, "index");
icculus@0
   126
    if (ttisfunction(tm)) {
icculus@0
   127
      callTM(L, tm, t, key, val, 1);
icculus@0
   128
      return;
icculus@0
   129
    }
icculus@0
   130
    t = tm;  /* else repeat with 'tm' */
icculus@0
   131
  }
icculus@0
   132
  luaG_runerror(L, "loop in gettable");
icculus@0
   133
}
icculus@0
   134
icculus@0
   135
icculus@0
   136
void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
icculus@0
   137
  int loop;
icculus@0
   138
  for (loop = 0; loop < MAXTAGLOOP; loop++) {
icculus@0
   139
    const TValue *tm;
icculus@0
   140
    if (ttistable(t)) {  /* `t' is a table? */
icculus@0
   141
      Table *h = hvalue(t);
icculus@0
   142
      TValue *oldval = cast(TValue *, luaH_get(h, key));
icculus@0
   143
      /* if previous value is not nil, there must be a previous entry
icculus@0
   144
         in the table; moreover, a metamethod has no relevance */
icculus@0
   145
      if (!ttisnil(oldval) ||
icculus@0
   146
         /* previous value is nil; must check the metamethod */
icculus@0
   147
         ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
icculus@0
   148
         /* no metamethod; is there a previous entry in the table? */
icculus@0
   149
         (oldval != luaO_nilobject ||
icculus@0
   150
         /* no previous entry; must create one. (The next test is
icculus@0
   151
            always true; we only need the assignment.) */
icculus@0
   152
         (oldval = luaH_newkey(L, h, key), 1)))) {
icculus@0
   153
        /* no metamethod and (now) there is an entry with given key */
icculus@0
   154
        setobj2t(L, oldval, val);  /* assign new value to that entry */
icculus@0
   155
        invalidateTMcache(h);
icculus@0
   156
        luaC_barrierback(L, obj2gco(h), val);
icculus@0
   157
        return;
icculus@0
   158
      }
icculus@0
   159
      /* else will try the metamethod */
icculus@0
   160
    }
icculus@0
   161
    else  /* not a table; check metamethod */
icculus@0
   162
      if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
icculus@0
   163
        luaG_typeerror(L, t, "index");
icculus@0
   164
    /* there is a metamethod */
icculus@0
   165
    if (ttisfunction(tm)) {
icculus@0
   166
      callTM(L, tm, t, key, val, 0);
icculus@0
   167
      return;
icculus@0
   168
    }
icculus@0
   169
    t = tm;  /* else repeat with 'tm' */
icculus@0
   170
  }
icculus@0
   171
  luaG_runerror(L, "loop in settable");
icculus@0
   172
}
icculus@0
   173
icculus@0
   174
icculus@0
   175
static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,
icculus@0
   176
                       StkId res, TMS event) {
icculus@0
   177
  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
icculus@0
   178
  if (ttisnil(tm))
icculus@0
   179
    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
icculus@0
   180
  if (ttisnil(tm)) return 0;
icculus@0
   181
  callTM(L, tm, p1, p2, res, 1);
icculus@0
   182
  return 1;
icculus@0
   183
}
icculus@0
   184
icculus@0
   185
icculus@0
   186
static const TValue *get_equalTM (lua_State *L, Table *mt1, Table *mt2,
icculus@0
   187
                                  TMS event) {
icculus@0
   188
  const TValue *tm1 = fasttm(L, mt1, event);
icculus@0
   189
  const TValue *tm2;
icculus@0
   190
  if (tm1 == NULL) return NULL;  /* no metamethod */
icculus@0
   191
  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */
icculus@0
   192
  tm2 = fasttm(L, mt2, event);
icculus@0
   193
  if (tm2 == NULL) return NULL;  /* no metamethod */
icculus@0
   194
  if (luaV_rawequalobj(tm1, tm2))  /* same metamethods? */
icculus@0
   195
    return tm1;
icculus@0
   196
  return NULL;
icculus@0
   197
}
icculus@0
   198
icculus@0
   199
icculus@0
   200
static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,
icculus@0
   201
                         TMS event) {
icculus@0
   202
  if (!call_binTM(L, p1, p2, L->top, event))
icculus@0
   203
    return -1;  /* no metamethod */
icculus@0
   204
  else
icculus@0
   205
    return !l_isfalse(L->top);
icculus@0
   206
}
icculus@0
   207
icculus@0
   208
icculus@0
   209
static int l_strcmp (const TString *ls, const TString *rs) {
icculus@0
   210
  const char *l = getstr(ls);
icculus@0
   211
  size_t ll = ls->tsv.len;
icculus@0
   212
  const char *r = getstr(rs);
icculus@0
   213
  size_t lr = rs->tsv.len;
icculus@0
   214
  for (;;) {
icculus@0
   215
    int temp = strcoll(l, r);
icculus@0
   216
    if (temp != 0) return temp;
icculus@0
   217
    else {  /* strings are equal up to a `\0' */
icculus@0
   218
      size_t len = strlen(l);  /* index of first `\0' in both strings */
icculus@0
   219
      if (len == lr)  /* r is finished? */
icculus@0
   220
        return (len == ll) ? 0 : 1;
icculus@0
   221
      else if (len == ll)  /* l is finished? */
icculus@0
   222
        return -1;  /* l is smaller than r (because r is not finished) */
icculus@0
   223
      /* both strings longer than `len'; go on comparing (after the `\0') */
icculus@0
   224
      len++;
icculus@0
   225
      l += len; ll -= len; r += len; lr -= len;
icculus@0
   226
    }
icculus@0
   227
  }
icculus@0
   228
}
icculus@0
   229
icculus@0
   230
icculus@0
   231
int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {
icculus@0
   232
  int res;
icculus@0
   233
  if (ttisnumber(l) && ttisnumber(r))
icculus@0
   234
    return luai_numlt(L, nvalue(l), nvalue(r));
icculus@0
   235
  else if (ttisstring(l) && ttisstring(r))
icculus@0
   236
    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;
icculus@0
   237
  else if ((res = call_orderTM(L, l, r, TM_LT)) < 0)
icculus@0
   238
    luaG_ordererror(L, l, r);
icculus@0
   239
  return res;
icculus@0
   240
}
icculus@0
   241
icculus@0
   242
icculus@0
   243
int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) {
icculus@0
   244
  int res;
icculus@0
   245
  if (ttisnumber(l) && ttisnumber(r))
icculus@0
   246
    return luai_numle(L, nvalue(l), nvalue(r));
icculus@0
   247
  else if (ttisstring(l) && ttisstring(r))
icculus@0
   248
    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;
icculus@0
   249
  else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0)  /* first try `le' */
icculus@0
   250
    return res;
icculus@0
   251
  else if ((res = call_orderTM(L, r, l, TM_LT)) < 0)  /* else try `lt' */
icculus@0
   252
    luaG_ordererror(L, l, r);
icculus@0
   253
  return !res;
icculus@0
   254
}
icculus@0
   255
icculus@0
   256
icculus@0
   257
/*
icculus@0
   258
** equality of Lua values. L == NULL means raw equality (no metamethods)
icculus@0
   259
*/
icculus@0
   260
int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) {
icculus@0
   261
  const TValue *tm;
icculus@0
   262
  lua_assert(ttisequal(t1, t2));
icculus@0
   263
  switch (ttype(t1)) {
icculus@0
   264
    case LUA_TNIL: return 1;
icculus@0
   265
    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));
icculus@0
   266
    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
icculus@0
   267
    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
icculus@0
   268
    case LUA_TLCF: return fvalue(t1) == fvalue(t2);
icculus@0
   269
    case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2));
icculus@0
   270
    case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2));
icculus@0
   271
    case LUA_TUSERDATA: {
icculus@0
   272
      if (uvalue(t1) == uvalue(t2)) return 1;
icculus@0
   273
      else if (L == NULL) return 0;
icculus@0
   274
      tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ);
icculus@0
   275
      break;  /* will try TM */
icculus@0
   276
    }
icculus@0
   277
    case LUA_TTABLE: {
icculus@0
   278
      if (hvalue(t1) == hvalue(t2)) return 1;
icculus@0
   279
      else if (L == NULL) return 0;
icculus@0
   280
      tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);
icculus@0
   281
      break;  /* will try TM */
icculus@0
   282
    }
icculus@0
   283
    default:
icculus@0
   284
      lua_assert(iscollectable(t1));
icculus@0
   285
      return gcvalue(t1) == gcvalue(t2);
icculus@0
   286
  }
icculus@0
   287
  if (tm == NULL) return 0;  /* no TM? */
icculus@0
   288
  callTM(L, tm, t1, t2, L->top, 1);  /* call TM */
icculus@0
   289
  return !l_isfalse(L->top);
icculus@0
   290
}
icculus@0
   291
icculus@0
   292
icculus@0
   293
void luaV_concat (lua_State *L, int total) {
icculus@0
   294
  lua_assert(total >= 2);
icculus@0
   295
  do {
icculus@0
   296
    StkId top = L->top;
icculus@0
   297
    int n = 2;  /* number of elements handled in this pass (at least 2) */
icculus@0
   298
    if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
icculus@0
   299
      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
icculus@0
   300
        luaG_concaterror(L, top-2, top-1);
icculus@0
   301
    }
icculus@0
   302
    else if (tsvalue(top-1)->len == 0)  /* second operand is empty? */
icculus@0
   303
      (void)tostring(L, top - 2);  /* result is first operand */
icculus@0
   304
    else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) {
icculus@0
   305
      setobjs2s(L, top - 2, top - 1);  /* result is second op. */
icculus@0
   306
    }
icculus@0
   307
    else {
icculus@0
   308
      /* at least two non-empty string values; get as many as possible */
icculus@0
   309
      size_t tl = tsvalue(top-1)->len;
icculus@0
   310
      char *buffer;
icculus@0
   311
      int i;
icculus@0
   312
      /* collect total length */
icculus@0
   313
      for (i = 1; i < total && tostring(L, top-i-1); i++) {
icculus@0
   314
        size_t l = tsvalue(top-i-1)->len;
icculus@0
   315
        if (l >= (MAX_SIZET/sizeof(char)) - tl)
icculus@0
   316
          luaG_runerror(L, "string length overflow");
icculus@0
   317
        tl += l;
icculus@0
   318
      }
icculus@0
   319
      buffer = luaZ_openspace(L, &G(L)->buff, tl);
icculus@0
   320
      tl = 0;
icculus@0
   321
      n = i;
icculus@0
   322
      do {  /* concat all strings */
icculus@0
   323
        size_t l = tsvalue(top-i)->len;
icculus@0
   324
        memcpy(buffer+tl, svalue(top-i), l * sizeof(char));
icculus@0
   325
        tl += l;
icculus@0
   326
      } while (--i > 0);
icculus@0
   327
      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));
icculus@0
   328
    }
icculus@0
   329
    total -= n-1;  /* got 'n' strings to create 1 new */
icculus@0
   330
    L->top -= n-1;  /* popped 'n' strings and pushed one */
icculus@0
   331
  } while (total > 1);  /* repeat until only 1 result left */
icculus@0
   332
}
icculus@0
   333
icculus@0
   334
icculus@0
   335
void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
icculus@0
   336
  const TValue *tm;
icculus@0
   337
  switch (ttypenv(rb)) {
icculus@0
   338
    case LUA_TTABLE: {
icculus@0
   339
      Table *h = hvalue(rb);
icculus@0
   340
      tm = fasttm(L, h->metatable, TM_LEN);
icculus@0
   341
      if (tm) break;  /* metamethod? break switch to call it */
icculus@0
   342
      setnvalue(ra, cast_num(luaH_getn(h)));  /* else primitive len */
icculus@0
   343
      return;
icculus@0
   344
    }
icculus@0
   345
    case LUA_TSTRING: {
icculus@0
   346
      setnvalue(ra, cast_num(tsvalue(rb)->len));
icculus@0
   347
      return;
icculus@0
   348
    }
icculus@0
   349
    default: {  /* try metamethod */
icculus@0
   350
      tm = luaT_gettmbyobj(L, rb, TM_LEN);
icculus@0
   351
      if (ttisnil(tm))  /* no metamethod? */
icculus@0
   352
        luaG_typeerror(L, rb, "get length of");
icculus@0
   353
      break;
icculus@0
   354
    }
icculus@0
   355
  }
icculus@0
   356
  callTM(L, tm, rb, rb, ra, 1);
icculus@0
   357
}
icculus@0
   358
icculus@0
   359
icculus@0
   360
void luaV_arith (lua_State *L, StkId ra, const TValue *rb,
icculus@0
   361
                 const TValue *rc, TMS op) {
icculus@0
   362
  TValue tempb, tempc;
icculus@0
   363
  const TValue *b, *c;
icculus@0
   364
  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&
icculus@0
   365
      (c = luaV_tonumber(rc, &tempc)) != NULL) {
icculus@0
   366
    lua_Number res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c));
icculus@0
   367
    setnvalue(ra, res);
icculus@0
   368
  }
icculus@0
   369
  else if (!call_binTM(L, rb, rc, ra, op))
icculus@0
   370
    luaG_aritherror(L, rb, rc);
icculus@0
   371
}
icculus@0
   372
icculus@0
   373
icculus@0
   374
/*
icculus@0
   375
** check whether cached closure in prototype 'p' may be reused, that is,
icculus@0
   376
** whether there is a cached closure with the same upvalues needed by
icculus@0
   377
** new closure to be created.
icculus@0
   378
*/
icculus@0
   379
static Closure *getcached (Proto *p, UpVal **encup, StkId base) {
icculus@0
   380
  Closure *c = p->cache;
icculus@0
   381
  if (c != NULL) {  /* is there a cached closure? */
icculus@0
   382
    int nup = p->sizeupvalues;
icculus@0
   383
    Upvaldesc *uv = p->upvalues;
icculus@0
   384
    int i;
icculus@0
   385
    for (i = 0; i < nup; i++) {  /* check whether it has right upvalues */
icculus@0
   386
      TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v;
icculus@0
   387
      if (c->l.upvals[i]->v != v)
icculus@0
   388
        return NULL;  /* wrong upvalue; cannot reuse closure */
icculus@0
   389
    }
icculus@0
   390
  }
icculus@0
   391
  return c;  /* return cached closure (or NULL if no cached closure) */
icculus@0
   392
}
icculus@0
   393
icculus@0
   394
icculus@0
   395
/*
icculus@0
   396
** create a new Lua closure, push it in the stack, and initialize
icculus@0
   397
** its upvalues. Note that the call to 'luaC_barrierproto' must come
icculus@0
   398
** before the assignment to 'p->cache', as the function needs the
icculus@0
   399
** original value of that field.
icculus@0
   400
*/
icculus@0
   401
static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
icculus@0
   402
                         StkId ra) {
icculus@0
   403
  int nup = p->sizeupvalues;
icculus@0
   404
  Upvaldesc *uv = p->upvalues;
icculus@0
   405
  int i;
icculus@0
   406
  Closure *ncl = luaF_newLclosure(L, nup);
icculus@0
   407
  ncl->l.p = p;
icculus@0
   408
  setclLvalue(L, ra, ncl);  /* anchor new closure in stack */
icculus@0
   409
  for (i = 0; i < nup; i++) {  /* fill in its upvalues */
icculus@0
   410
    if (uv[i].instack)  /* upvalue refers to local variable? */
icculus@0
   411
      ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx);
icculus@0
   412
    else  /* get upvalue from enclosing function */
icculus@0
   413
      ncl->l.upvals[i] = encup[uv[i].idx];
icculus@0
   414
  }
icculus@0
   415
  luaC_barrierproto(L, p, ncl);
icculus@0
   416
  p->cache = ncl;  /* save it on cache for reuse */
icculus@0
   417
}
icculus@0
   418
icculus@0
   419
icculus@0
   420
/*
icculus@0
   421
** finish execution of an opcode interrupted by an yield
icculus@0
   422
*/
icculus@0
   423
void luaV_finishOp (lua_State *L) {
icculus@0
   424
  CallInfo *ci = L->ci;
icculus@0
   425
  StkId base = ci->u.l.base;
icculus@0
   426
  Instruction inst = *(ci->u.l.savedpc - 1);  /* interrupted instruction */
icculus@0
   427
  OpCode op = GET_OPCODE(inst);
icculus@0
   428
  switch (op) {  /* finish its execution */
icculus@0
   429
    case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV:
icculus@0
   430
    case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN:
icculus@0
   431
    case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: {
icculus@0
   432
      setobjs2s(L, base + GETARG_A(inst), --L->top);
icculus@0
   433
      break;
icculus@0
   434
    }
icculus@0
   435
    case OP_LE: case OP_LT: case OP_EQ: {
icculus@0
   436
      int res = !l_isfalse(L->top - 1);
icculus@0
   437
      L->top--;
icculus@0
   438
      /* metamethod should not be called when operand is K */
icculus@0
   439
      lua_assert(!ISK(GETARG_B(inst)));
icculus@0
   440
      if (op == OP_LE &&  /* "<=" using "<" instead? */
icculus@0
   441
          ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE)))
icculus@0
   442
        res = !res;  /* invert result */
icculus@0
   443
      lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP);
icculus@0
   444
      if (res != GETARG_A(inst))  /* condition failed? */
icculus@0
   445
        ci->u.l.savedpc++;  /* skip jump instruction */
icculus@0
   446
      break;
icculus@0
   447
    }
icculus@0
   448
    case OP_CONCAT: {
icculus@0
   449
      StkId top = L->top - 1;  /* top when 'call_binTM' was called */
icculus@0
   450
      int b = GETARG_B(inst);      /* first element to concatenate */
icculus@0
   451
      int total = cast_int(top - 1 - (base + b));  /* yet to concatenate */
icculus@0
   452
      setobj2s(L, top - 2, top);  /* put TM result in proper position */
icculus@0
   453
      if (total > 1) {  /* are there elements to concat? */
icculus@0
   454
        L->top = top - 1;  /* top is one after last element (at top-2) */
icculus@0
   455
        luaV_concat(L, total);  /* concat them (may yield again) */
icculus@0
   456
      }
icculus@0
   457
      /* move final result to final position */
icculus@0
   458
      setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1);
icculus@0
   459
      L->top = ci->top;  /* restore top */
icculus@0
   460
      break;
icculus@0
   461
    }
icculus@0
   462
    case OP_TFORCALL: {
icculus@0
   463
      lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP);
icculus@0
   464
      L->top = ci->top;  /* correct top */
icculus@0
   465
      break;
icculus@0
   466
    }
icculus@0
   467
    case OP_CALL: {
icculus@0
   468
      if (GETARG_C(inst) - 1 >= 0)  /* nresults >= 0? */
icculus@0
   469
        L->top = ci->top;  /* adjust results */
icculus@0
   470
      break;
icculus@0
   471
    }
icculus@0
   472
    case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE:
icculus@0
   473
      break;
icculus@0
   474
    default: lua_assert(0);
icculus@0
   475
  }
icculus@0
   476
}
icculus@0
   477
icculus@0
   478
icculus@0
   479
icculus@0
   480
/*
icculus@0
   481
** some macros for common tasks in `luaV_execute'
icculus@0
   482
*/
icculus@0
   483
icculus@0
   484
#if !defined luai_runtimecheck
icculus@0
   485
#define luai_runtimecheck(L, c)		/* void */
icculus@0
   486
#endif
icculus@0
   487
icculus@0
   488
icculus@0
   489
#define RA(i)	(base+GETARG_A(i))
icculus@0
   490
/* to be used after possible stack reallocation */
icculus@0
   491
#define RB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))
icculus@0
   492
#define RC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))
icculus@0
   493
#define RKB(i)	check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \
icculus@0
   494
	ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))
icculus@0
   495
#define RKC(i)	check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \
icculus@0
   496
	ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))
icculus@0
   497
#define KBx(i)  \
icculus@0
   498
  (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++)))
icculus@0
   499
icculus@0
   500
icculus@0
   501
/* execute a jump instruction */
icculus@0
   502
#define dojump(ci,i,e) \
icculus@0
   503
  { int a = GETARG_A(i); \
icculus@0
   504
    if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \
icculus@0
   505
    ci->u.l.savedpc += GETARG_sBx(i) + e; }
icculus@0
   506
icculus@0
   507
/* for test instructions, execute the jump instruction that follows it */
icculus@0
   508
#define donextjump(ci)	{ i = *ci->u.l.savedpc; dojump(ci, i, 1); }
icculus@0
   509
icculus@0
   510
icculus@0
   511
#define Protect(x)	{ {x;}; base = ci->u.l.base; }
icculus@0
   512
icculus@0
   513
#define checkGC(L,c)  \
icculus@0
   514
  Protect( luaC_condGC(L,{L->top = (c);  /* limit of live values */ \
icculus@0
   515
                          luaC_step(L); \
icculus@0
   516
                          L->top = ci->top;})  /* restore top */ \
icculus@0
   517
           luai_threadyield(L); )
icculus@0
   518
icculus@0
   519
icculus@0
   520
#define arith_op(op,tm) { \
icculus@0
   521
        TValue *rb = RKB(i); \
icculus@0
   522
        TValue *rc = RKC(i); \
icculus@0
   523
        if (ttisnumber(rb) && ttisnumber(rc)) { \
icculus@0
   524
          lua_Number nb = nvalue(rb), nc = nvalue(rc); \
icculus@0
   525
          setnvalue(ra, op(L, nb, nc)); \
icculus@0
   526
        } \
icculus@0
   527
        else { Protect(luaV_arith(L, ra, rb, rc, tm)); } }
icculus@0
   528
icculus@0
   529
icculus@0
   530
#define vmdispatch(o)	switch(o)
icculus@0
   531
#define vmcase(l,b)	case l: {b}  break;
icculus@0
   532
#define vmcasenb(l,b)	case l: {b}		/* nb = no break */
icculus@0
   533
icculus@0
   534
void luaV_execute (lua_State *L) {
icculus@0
   535
  CallInfo *ci = L->ci;
icculus@0
   536
  LClosure *cl;
icculus@0
   537
  TValue *k;
icculus@0
   538
  StkId base;
icculus@0
   539
 newframe:  /* reentry point when frame changes (call/return) */
icculus@0
   540
  lua_assert(ci == L->ci);
icculus@0
   541
  cl = clLvalue(ci->func);
icculus@0
   542
  k = cl->p->k;
icculus@0
   543
  base = ci->u.l.base;
icculus@0
   544
  /* main loop of interpreter */
icculus@0
   545
  for (;;) {
icculus@0
   546
    Instruction i = *(ci->u.l.savedpc++);
icculus@0
   547
    StkId ra;
icculus@0
   548
    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
icculus@0
   549
        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
icculus@0
   550
      Protect(traceexec(L));
icculus@0
   551
    }
icculus@0
   552
    /* WARNING: several calls may realloc the stack and invalidate `ra' */
icculus@0
   553
    ra = RA(i);
icculus@0
   554
    lua_assert(base == ci->u.l.base);
icculus@0
   555
    lua_assert(base <= L->top && L->top < L->stack + L->stacksize);
icculus@0
   556
    vmdispatch (GET_OPCODE(i)) {
icculus@0
   557
      vmcase(OP_MOVE,
icculus@0
   558
        setobjs2s(L, ra, RB(i));
icculus@0
   559
      )
icculus@0
   560
      vmcase(OP_LOADK,
icculus@0
   561
        TValue *rb = k + GETARG_Bx(i);
icculus@0
   562
        setobj2s(L, ra, rb);
icculus@0
   563
      )
icculus@0
   564
      vmcase(OP_LOADKX,
icculus@0
   565
        TValue *rb;
icculus@0
   566
        lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
icculus@0
   567
        rb = k + GETARG_Ax(*ci->u.l.savedpc++);
icculus@0
   568
        setobj2s(L, ra, rb);
icculus@0
   569
      )
icculus@0
   570
      vmcase(OP_LOADBOOL,
icculus@0
   571
        setbvalue(ra, GETARG_B(i));
icculus@0
   572
        if (GETARG_C(i)) ci->u.l.savedpc++;  /* skip next instruction (if C) */
icculus@0
   573
      )
icculus@0
   574
      vmcase(OP_LOADNIL,
icculus@0
   575
        int b = GETARG_B(i);
icculus@0
   576
        do {
icculus@0
   577
          setnilvalue(ra++);
icculus@0
   578
        } while (b--);
icculus@0
   579
      )
icculus@0
   580
      vmcase(OP_GETUPVAL,
icculus@0
   581
        int b = GETARG_B(i);
icculus@0
   582
        setobj2s(L, ra, cl->upvals[b]->v);
icculus@0
   583
      )
icculus@0
   584
      vmcase(OP_GETTABUP,
icculus@0
   585
        int b = GETARG_B(i);
icculus@0
   586
        Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra));
icculus@0
   587
      )
icculus@0
   588
      vmcase(OP_GETTABLE,
icculus@0
   589
        Protect(luaV_gettable(L, RB(i), RKC(i), ra));
icculus@0
   590
      )
icculus@0
   591
      vmcase(OP_SETTABUP,
icculus@0
   592
        int a = GETARG_A(i);
icculus@0
   593
        Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i)));
icculus@0
   594
      )
icculus@0
   595
      vmcase(OP_SETUPVAL,
icculus@0
   596
        UpVal *uv = cl->upvals[GETARG_B(i)];
icculus@0
   597
        setobj(L, uv->v, ra);
icculus@0
   598
        luaC_barrier(L, uv, ra);
icculus@0
   599
      )
icculus@0
   600
      vmcase(OP_SETTABLE,
icculus@0
   601
        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
icculus@0
   602
      )
icculus@0
   603
      vmcase(OP_NEWTABLE,
icculus@0
   604
        int b = GETARG_B(i);
icculus@0
   605
        int c = GETARG_C(i);
icculus@0
   606
        Table *t = luaH_new(L);
icculus@0
   607
        sethvalue(L, ra, t);
icculus@0
   608
        if (b != 0 || c != 0)
icculus@0
   609
          luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
icculus@0
   610
        checkGC(L, ra + 1);
icculus@0
   611
      )
icculus@0
   612
      vmcase(OP_SELF,
icculus@0
   613
        StkId rb = RB(i);
icculus@0
   614
        setobjs2s(L, ra+1, rb);
icculus@0
   615
        Protect(luaV_gettable(L, rb, RKC(i), ra));
icculus@0
   616
      )
icculus@0
   617
      vmcase(OP_ADD,
icculus@0
   618
        arith_op(luai_numadd, TM_ADD);
icculus@0
   619
      )
icculus@0
   620
      vmcase(OP_SUB,
icculus@0
   621
        arith_op(luai_numsub, TM_SUB);
icculus@0
   622
      )
icculus@0
   623
      vmcase(OP_MUL,
icculus@0
   624
        arith_op(luai_nummul, TM_MUL);
icculus@0
   625
      )
icculus@0
   626
      vmcase(OP_DIV,
icculus@0
   627
        arith_op(luai_numdiv, TM_DIV);
icculus@0
   628
      )
icculus@0
   629
      vmcase(OP_MOD,
icculus@0
   630
        arith_op(luai_nummod, TM_MOD);
icculus@0
   631
      )
icculus@0
   632
      vmcase(OP_POW,
icculus@0
   633
        arith_op(luai_numpow, TM_POW);
icculus@0
   634
      )
icculus@0
   635
      vmcase(OP_UNM,
icculus@0
   636
        TValue *rb = RB(i);
icculus@0
   637
        if (ttisnumber(rb)) {
icculus@0
   638
          lua_Number nb = nvalue(rb);
icculus@0
   639
          setnvalue(ra, luai_numunm(L, nb));
icculus@0
   640
        }
icculus@0
   641
        else {
icculus@0
   642
          Protect(luaV_arith(L, ra, rb, rb, TM_UNM));
icculus@0
   643
        }
icculus@0
   644
      )
icculus@0
   645
      vmcase(OP_NOT,
icculus@0
   646
        TValue *rb = RB(i);
icculus@0
   647
        int res = l_isfalse(rb);  /* next assignment may change this value */
icculus@0
   648
        setbvalue(ra, res);
icculus@0
   649
      )
icculus@0
   650
      vmcase(OP_LEN,
icculus@0
   651
        Protect(luaV_objlen(L, ra, RB(i)));
icculus@0
   652
      )
icculus@0
   653
      vmcase(OP_CONCAT,
icculus@0
   654
        int b = GETARG_B(i);
icculus@0
   655
        int c = GETARG_C(i);
icculus@0
   656
        StkId rb;
icculus@0
   657
        L->top = base + c + 1;  /* mark the end of concat operands */
icculus@0
   658
        Protect(luaV_concat(L, c - b + 1));
icculus@0
   659
        ra = RA(i);  /* 'luav_concat' may invoke TMs and move the stack */
icculus@0
   660
        rb = b + base;
icculus@0
   661
        setobjs2s(L, ra, rb);
icculus@0
   662
        checkGC(L, (ra >= rb ? ra + 1 : rb));
icculus@0
   663
        L->top = ci->top;  /* restore top */
icculus@0
   664
      )
icculus@0
   665
      vmcase(OP_JMP,
icculus@0
   666
        dojump(ci, i, 0);
icculus@0
   667
      )
icculus@0
   668
      vmcase(OP_EQ,
icculus@0
   669
        TValue *rb = RKB(i);
icculus@0
   670
        TValue *rc = RKC(i);
icculus@0
   671
        Protect(
icculus@0
   672
          if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i))
icculus@0
   673
            ci->u.l.savedpc++;
icculus@0
   674
          else
icculus@0
   675
            donextjump(ci);
icculus@0
   676
        )
icculus@0
   677
      )
icculus@0
   678
      vmcase(OP_LT,
icculus@0
   679
        Protect(
icculus@0
   680
          if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i))
icculus@0
   681
            ci->u.l.savedpc++;
icculus@0
   682
          else
icculus@0
   683
            donextjump(ci);
icculus@0
   684
        )
icculus@0
   685
      )
icculus@0
   686
      vmcase(OP_LE,
icculus@0
   687
        Protect(
icculus@0
   688
          if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i))
icculus@0
   689
            ci->u.l.savedpc++;
icculus@0
   690
          else
icculus@0
   691
            donextjump(ci);
icculus@0
   692
        )
icculus@0
   693
      )
icculus@0
   694
      vmcase(OP_TEST,
icculus@0
   695
        if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra))
icculus@0
   696
            ci->u.l.savedpc++;
icculus@0
   697
          else
icculus@0
   698
          donextjump(ci);
icculus@0
   699
      )
icculus@0
   700
      vmcase(OP_TESTSET,
icculus@0
   701
        TValue *rb = RB(i);
icculus@0
   702
        if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb))
icculus@0
   703
          ci->u.l.savedpc++;
icculus@0
   704
        else {
icculus@0
   705
          setobjs2s(L, ra, rb);
icculus@0
   706
          donextjump(ci);
icculus@0
   707
        }
icculus@0
   708
      )
icculus@0
   709
      vmcase(OP_CALL,
icculus@0
   710
        int b = GETARG_B(i);
icculus@0
   711
        int nresults = GETARG_C(i) - 1;
icculus@0
   712
        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
icculus@0
   713
        if (luaD_precall(L, ra, nresults)) {  /* C function? */
icculus@0
   714
          if (nresults >= 0) L->top = ci->top;  /* adjust results */
icculus@0
   715
          base = ci->u.l.base;
icculus@0
   716
        }
icculus@0
   717
        else {  /* Lua function */
icculus@0
   718
          ci = L->ci;
icculus@0
   719
          ci->callstatus |= CIST_REENTRY;
icculus@0
   720
          goto newframe;  /* restart luaV_execute over new Lua function */
icculus@0
   721
        }
icculus@0
   722
      )
icculus@0
   723
      vmcase(OP_TAILCALL,
icculus@0
   724
        int b = GETARG_B(i);
icculus@0
   725
        if (b != 0) L->top = ra+b;  /* else previous instruction set top */
icculus@0
   726
        lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
icculus@0
   727
        if (luaD_precall(L, ra, LUA_MULTRET))  /* C function? */
icculus@0
   728
          base = ci->u.l.base;
icculus@0
   729
        else {
icculus@0
   730
          /* tail call: put called frame (n) in place of caller one (o) */
icculus@0
   731
          CallInfo *nci = L->ci;  /* called frame */
icculus@0
   732
          CallInfo *oci = nci->previous;  /* caller frame */
icculus@0
   733
          StkId nfunc = nci->func;  /* called function */
icculus@0
   734
          StkId ofunc = oci->func;  /* caller function */
icculus@0
   735
          /* last stack slot filled by 'precall' */
icculus@0
   736
          StkId lim = nci->u.l.base + getproto(nfunc)->numparams;
icculus@0
   737
          int aux;
icculus@0
   738
          /* close all upvalues from previous call */
icculus@0
   739
          if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base);
icculus@0
   740
          /* move new frame into old one */
icculus@0
   741
          for (aux = 0; nfunc + aux < lim; aux++)
icculus@0
   742
            setobjs2s(L, ofunc + aux, nfunc + aux);
icculus@0
   743
          oci->u.l.base = ofunc + (nci->u.l.base - nfunc);  /* correct base */
icculus@0
   744
          oci->top = L->top = ofunc + (L->top - nfunc);  /* correct top */
icculus@0
   745
          oci->u.l.savedpc = nci->u.l.savedpc;
icculus@0
   746
          oci->callstatus |= CIST_TAIL;  /* function was tail called */
icculus@0
   747
          ci = L->ci = oci;  /* remove new frame */
icculus@0
   748
          lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize);
icculus@0
   749
          goto newframe;  /* restart luaV_execute over new Lua function */
icculus@0
   750
        }
icculus@0
   751
      )
icculus@0
   752
      vmcasenb(OP_RETURN,
icculus@0
   753
        int b = GETARG_B(i);
icculus@0
   754
        if (b != 0) L->top = ra+b-1;
icculus@0
   755
        if (cl->p->sizep > 0) luaF_close(L, base);
icculus@0
   756
        b = luaD_poscall(L, ra);
icculus@0
   757
        if (!(ci->callstatus & CIST_REENTRY))  /* 'ci' still the called one */
icculus@0
   758
          return;  /* external invocation: return */
icculus@0
   759
        else {  /* invocation via reentry: continue execution */
icculus@0
   760
          ci = L->ci;
icculus@0
   761
          if (b) L->top = ci->top;
icculus@0
   762
          lua_assert(isLua(ci));
icculus@0
   763
          lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL);
icculus@0
   764
          goto newframe;  /* restart luaV_execute over new Lua function */
icculus@0
   765
        }
icculus@0
   766
      )
icculus@0
   767
      vmcase(OP_FORLOOP,
icculus@0
   768
        lua_Number step = nvalue(ra+2);
icculus@0
   769
        lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */
icculus@0
   770
        lua_Number limit = nvalue(ra+1);
icculus@0
   771
        if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit)
icculus@0
   772
                                   : luai_numle(L, limit, idx)) {
icculus@0
   773
          ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
icculus@0
   774
          setnvalue(ra, idx);  /* update internal index... */
icculus@0
   775
          setnvalue(ra+3, idx);  /* ...and external index */
icculus@0
   776
        }
icculus@0
   777
      )
icculus@0
   778
      vmcase(OP_FORPREP,
icculus@0
   779
        const TValue *init = ra;
icculus@0
   780
        const TValue *plimit = ra+1;
icculus@0
   781
        const TValue *pstep = ra+2;
icculus@0
   782
        if (!tonumber(init, ra))
icculus@0
   783
          luaG_runerror(L, LUA_QL("for") " initial value must be a number");
icculus@0
   784
        else if (!tonumber(plimit, ra+1))
icculus@0
   785
          luaG_runerror(L, LUA_QL("for") " limit must be a number");
icculus@0
   786
        else if (!tonumber(pstep, ra+2))
icculus@0
   787
          luaG_runerror(L, LUA_QL("for") " step must be a number");
icculus@0
   788
        setnvalue(ra, luai_numsub(L, nvalue(ra), nvalue(pstep)));
icculus@0
   789
        ci->u.l.savedpc += GETARG_sBx(i);
icculus@0
   790
      )
icculus@0
   791
      vmcasenb(OP_TFORCALL,
icculus@0
   792
        StkId cb = ra + 3;  /* call base */
icculus@0
   793
        setobjs2s(L, cb+2, ra+2);
icculus@0
   794
        setobjs2s(L, cb+1, ra+1);
icculus@0
   795
        setobjs2s(L, cb, ra);
icculus@0
   796
        L->top = cb + 3;  /* func. + 2 args (state and index) */
icculus@0
   797
        Protect(luaD_call(L, cb, GETARG_C(i), 1));
icculus@0
   798
        L->top = ci->top;
icculus@0
   799
        i = *(ci->u.l.savedpc++);  /* go to next instruction */
icculus@0
   800
        ra = RA(i);
icculus@0
   801
        lua_assert(GET_OPCODE(i) == OP_TFORLOOP);
icculus@0
   802
        goto l_tforloop;
icculus@0
   803
      )
icculus@0
   804
      vmcase(OP_TFORLOOP,
icculus@0
   805
        l_tforloop:
icculus@0
   806
        if (!ttisnil(ra + 1)) {  /* continue loop? */
icculus@0
   807
          setobjs2s(L, ra, ra + 1);  /* save control variable */
icculus@0
   808
           ci->u.l.savedpc += GETARG_sBx(i);  /* jump back */
icculus@0
   809
        }
icculus@0
   810
      )
icculus@0
   811
      vmcase(OP_SETLIST,
icculus@0
   812
        int n = GETARG_B(i);
icculus@0
   813
        int c = GETARG_C(i);
icculus@0
   814
        int last;
icculus@0
   815
        Table *h;
icculus@0
   816
        if (n == 0) n = cast_int(L->top - ra) - 1;
icculus@0
   817
        if (c == 0) {
icculus@0
   818
          lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
icculus@0
   819
          c = GETARG_Ax(*ci->u.l.savedpc++);
icculus@0
   820
        }
icculus@0
   821
        luai_runtimecheck(L, ttistable(ra));
icculus@0
   822
        h = hvalue(ra);
icculus@0
   823
        last = ((c-1)*LFIELDS_PER_FLUSH) + n;
icculus@0
   824
        if (last > h->sizearray)  /* needs more space? */
icculus@0
   825
          luaH_resizearray(L, h, last);  /* pre-allocate it at once */
icculus@0
   826
        for (; n > 0; n--) {
icculus@0
   827
          TValue *val = ra+n;
icculus@0
   828
          luaH_setint(L, h, last--, val);
icculus@0
   829
          luaC_barrierback(L, obj2gco(h), val);
icculus@0
   830
        }
icculus@0
   831
        L->top = ci->top;  /* correct top (in case of previous open call) */
icculus@0
   832
      )
icculus@0
   833
      vmcase(OP_CLOSURE,
icculus@0
   834
        Proto *p = cl->p->p[GETARG_Bx(i)];
icculus@0
   835
        Closure *ncl = getcached(p, cl->upvals, base);  /* cached closure */
icculus@0
   836
        if (ncl == NULL)  /* no match? */
icculus@0
   837
          pushclosure(L, p, cl->upvals, base, ra);  /* create a new one */
icculus@0
   838
        else
icculus@0
   839
          setclLvalue(L, ra, ncl);  /* push cashed closure */
icculus@0
   840
        checkGC(L, ra + 1);
icculus@0
   841
      )
icculus@0
   842
      vmcase(OP_VARARG,
icculus@0
   843
        int b = GETARG_B(i) - 1;
icculus@0
   844
        int j;
icculus@0
   845
        int n = cast_int(base - ci->func) - cl->p->numparams - 1;
icculus@0
   846
        if (b < 0) {  /* B == 0? */
icculus@0
   847
          b = n;  /* get all var. arguments */
icculus@0
   848
          Protect(luaD_checkstack(L, n));
icculus@0
   849
          ra = RA(i);  /* previous call may change the stack */
icculus@0
   850
          L->top = ra + n;
icculus@0
   851
        }
icculus@0
   852
        for (j = 0; j < b; j++) {
icculus@0
   853
          if (j < n) {
icculus@0
   854
            setobjs2s(L, ra + j, base - n + j);
icculus@0
   855
          }
icculus@0
   856
          else {
icculus@0
   857
            setnilvalue(ra + j);
icculus@0
   858
          }
icculus@0
   859
        }
icculus@0
   860
      )
icculus@0
   861
      vmcase(OP_EXTRAARG,
icculus@0
   862
        lua_assert(0);
icculus@0
   863
      )
icculus@0
   864
    }
icculus@0
   865
  }
icculus@0
   866
}
icculus@0
   867