فهرست منبع

new version for INSTRUCTION formats

Roberto Ierusalimschy 25 سال پیش
والد
کامیت
3afe85b2ce
4فایلهای تغییر یافته به همراه293 افزوده شده و 433 حذف شده
  1. 11 5
      lobject.h
  2. 63 84
      lopcodes.h
  3. 122 210
      lparser.c
  4. 97 134
      lvm.c

+ 11 - 5
lobject.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lobject.h,v 1.45 2000/01/28 16:53:00 roberto Exp roberto $
+** $Id: lobject.h,v 1.46 2000/02/11 16:52:54 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -36,11 +36,14 @@
 #define LUA_NUM_TYPE double
 #define LUA_NUM_TYPE double
 #endif
 #endif
 
 
-
 typedef LUA_NUM_TYPE real;
 typedef LUA_NUM_TYPE real;
 
 
-#define Byte lua_Byte	/* some systems have Byte as a predefined type */
-typedef unsigned char  Byte;  /* unsigned 8 bits */
+
+/*
+** type for virtual-machine instructions
+** must be an unsigned with 4 bytes (see details in lopcodes.h)
+*/
+typedef unsigned long Instruction;
 
 
 
 
 #define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */
 #define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */
@@ -157,9 +160,12 @@ typedef struct TProtoFunc {
   int nknum;  /* size of `knum' */
   int nknum;  /* size of `knum' */
   struct TProtoFunc **kproto;  /* functions defined inside the function */
   struct TProtoFunc **kproto;  /* functions defined inside the function */
   int nkproto;  /* size of `kproto' */
   int nkproto;  /* size of `kproto' */
-  Byte *code;  /* ends with opcode ENDCODE */
+  Instruction *code;  /* ends with opcode ENDCODE */
   int lineDefined;
   int lineDefined;
   TaggedString  *source;
   TaggedString  *source;
+  short numparams;
+  short is_vararg;
+  short maxstacksize;
   struct LocVar *locvars;  /* ends with line = -1 */
   struct LocVar *locvars;  /* ends with line = -1 */
 } TProtoFunc;
 } TProtoFunc;
 
 

+ 63 - 84
lopcodes.h

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lopcodes.h,v 1.38 2000/01/28 16:53:00 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.39 2000/02/11 16:52:54 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -8,67 +8,79 @@
 #define lopcodes_h
 #define lopcodes_h
 
 
 
 
-/*
-** NOTICE: variants of the same opcode must be consecutive: First, those
-** with word parameter, then with byte parameter.
-*/
 
 
+/*===========================================================================
+  We assume that instructions are unsigned numbers with 4 bytes.
+  All instructions have an opcode in the lower byte. Moreover,
+  an instruction can have 0, 1, or 2 arguments. There are 4 types of
+  Instructions:
+  type 0: no arguments
+  type 1: 1 unsigned argument in the higher 24 bits (called `U')
+  type 2: 1 signed argument in the higher 24 bits          (`S')
+  type 3: 1st unsigned argument in the higher 16 bits      (`A')
+          2nd unsigned argument in the middle 8 bits       (`B')
 
 
-typedef enum {
-/* name          parm    before          after           side effect
------------------------------------------------------------------------------*/
-ENDCODE,/*	-	-		(return)			*/
-RETCODE,/*	b	-		(return)			*/
-
-CALL,/*		b c	v_n-v_1 f(at c)	r_b-r_1		f(v1,...,v_n)	*/
+  The signed argument is represented in excess 2^23; that is, the real value
+  is 2^23 minus the usigned value.
+===========================================================================*/
 
 
-TAILCALL,/*	b c	v_c-v_1 f	(return)	f(v1,...,v_c)	*/
+/*
+** the following macros help to manipulate instructions
+*/
 
 
-PUSHNIL,/*	b	-		nil_0-nil_b			*/
-POP,/*		b	a_b-a_1		-				*/
+#define MAXARG_U	((1<<24)-1)
+#define MAXARG_S	((1<<23)-1)
+#define MAXARG_A	((1<<16)-1)
+#define MAXARG_B	((1<<8)-1)
 
 
-PUSHINTW,/*	w	-		(float)w			*/
-PUSHINT,/*	b	-		(float)b			*/
+#define GET_OPCODE(i)	((OpCode)((i)&0xFF))
+#define GETARG_U(i)	((int)((i)>>8))
+#define GETARG_S(i)	((int)((i)>>8)-(1<<23))
+#define GETARG_A(i)	((int)((i)>>16))
+#define GETARG_B(i)	((int)(((i)>>8) & 0xFF))
 
 
-PUSHINTNEGW,/* w	-		(float)-w			*/
-PUSHINTNEG,/* b		-		(float)-b			*/
+#define SET_OPCODE(i,o)	(((i)&0xFFFFFF00u) | (Instruction)(o))
+#define SETARG_U(i,u)	(((i)&0x000000FFu) | ((Instruction)(u)<<8))
+#define SETARG_S(i,s)	(((i)&0x000000FFu) | ((Instruction)((s)+(1<<23))<<8))
+#define SETARG_A(i,a)	(((i)&0x0000FFFFu) | ((Instruction)(a)<<16))
+#define SETARG_B(i,b)	(((i)&0xFFFF00FFu) | ((Instruction)(b)<<8))
 
 
-PUSHSTRINGW,/*	w	-		KSTR[w]				*/
-PUSHSTRING,/*	b	-		KSTR[b]				*/
-PUSHNUMBERW,/*	w	-		KNUM[w]				*/
-PUSHNUMBER,/*	b	-		KNUM[b]				*/
 
 
-PUSHUPVALUE,/*	b	-		Closure[b]			*/
 
 
-PUSHLOCAL,/*	b	-		LOC[b]				*/
+typedef enum {
+/* name          parm    before          after           side effect
+-----------------------------------------------------------------------------*/
+ENDCODE,/*	-	-		(return)			*/
+RETCODE,/*	U	-		(return)			*/
 
 
-GETGLOBALW,/*	w	-		VAR[CNST[w]]			*/
-GETGLOBAL,/*	b	-		VAR[CNST[b]]			*/
+CALL,/*		A B	v_n-v_1 f(at a)	r_b-r_1		f(v1,...,v_n)	*/
+TAILCALL,/*	A B	v_a-v_1 f	(return)	f(v1,...,v_a)	*/
 
 
-GETTABLE,/*	-	i t		t[i]				*/
+PUSHNIL,/*	U	-		nil_0-nil_u			*/
+POP,/*		U	a_u-a_1		-				*/
 
 
-GETDOTTEDW,/*	w	t		t[CNST[w]]			*/
-GETDOTTED,/*	b	t		t[CNST[b]]			*/
+PUSHINT,/*	S	-		(real)s				*/
+PUSHSTRING,/*	U	-		KSTR[u]				*/
+PUSHNUMBER,/*	U	-		KNUM[u]				*/
 
 
-PUSHSELFW,/*	w	t		t t[CNST[w]]			*/
-PUSHSELF,/*	b	t		t t[CNST[b]]			*/
+PUSHUPVALUE,/*	U	-		Closure[u]			*/
 
 
-CREATEARRAYW,/*	w	-		newarray(size = w)		*/
-CREATEARRAY,/*	b	-		newarray(size = b)		*/
+PUSHLOCAL,/*	U	-		LOC[u]				*/
+GETGLOBAL,/*	U	-		VAR[CNST[u]]			*/
 
 
-SETLOCAL,/*	b	x		-		LOC[b]=x	*/
+GETTABLE,/*	-	i t		t[i]				*/
+GETDOTTED,/*	U	t		t[CNST[u]]			*/
+PUSHSELF,/*	U	t		t t[CNST[u]]			*/
 
 
-SETGLOBALW,/*	w	x		-		VAR[CNST[w]]=x	*/
-SETGLOBAL,/*	b	x		-		VAR[CNST[b]]=x	*/
+CREATETABLE,/*	U	-		newarray(size = u)		*/
 
 
+SETLOCAL,/*	U	x		-		LOC[u]=x	*/
+SETGLOBAL,/*	U	x		-		VAR[CNST[u]]=x	*/
 SETTABLEPOP,/*	-	v i t		-		t[i]=v		*/
 SETTABLEPOP,/*	-	v i t		-		t[i]=v		*/
+SETTABLE,/*	U	v a_u-a_1 i t	 a_u-a_1 i t	  t[i]=v	*/
 
 
-SETTABLE,/*	b	v a_b-a_1 i t	 a_b-a_1 i t	  t[i]=v	*/
-
-SETLISTW,/*	w c	v_c-v_1 t	t		t[i+w*FPF]=v_i	*/
-SETLIST,/*	b c	v_c-v_1 t	t		t[i+b*FPF]=v_i	*/
-
-SETMAP,/*	b	v_b k_b - v_0 k_0 t	t	t[k_i]=v_i	*/
+SETLIST,/*	A B	v_b-v_0 t	t		t[i+a*FPF]=v_i	*/
+SETMAP,/*	U	v_u k_u - v_0 k_0 t	t	t[k_i]=v_i	*/
 
 
 NEQOP,/*	-	y x		(x~=y)? 1 : nil			*/
 NEQOP,/*	-	y x		(x~=y)? 1 : nil			*/
 EQOP,/*		-	y x		(x==y)? 1 : nil			*/
 EQOP,/*		-	y x		(x==y)? 1 : nil			*/
@@ -85,54 +97,21 @@ CONCOP,/*	-	y x		x..y				*/
 MINUSOP,/*	-	x		-x				*/
 MINUSOP,/*	-	x		-x				*/
 NOTOP,/*	-	x		(x==nil)? 1 : nil		*/
 NOTOP,/*	-	x		(x==nil)? 1 : nil		*/
 
 
-ONTJMPW,/*	w	x		(x!=nil)? x : -	(x!=nil)? PC+=w	*/
-ONTJMP,/*	b	x		(x!=nil)? x : -	(x!=nil)? PC+=b	*/
-ONFJMPW,/*	w	x		(x==nil)? x : -	(x==nil)? PC+=w	*/
-ONFJMP,/*	b	x		(x==nil)? x : -	(x==nil)? PC+=b	*/
-JMPW,/*		w	-		-		PC+=w		*/
-JMP,/*		b	-		-		PC+=b		*/
-IFFJMPW,/*	w	x		-		(x==nil)? PC+=w	*/
-IFFJMP,/*	b	x		-		(x==nil)? PC+=b	*/
-IFTUPJMPW,/*	w	x		-		(x!=nil)? PC-=w	*/
-IFTUPJMP,/*	b	x		-		(x!=nil)? PC-=b	*/
-IFFUPJMPW,/*	w	x		-		(x==nil)? PC-=w	*/
-IFFUPJMP,/*	b	x		-		(x==nil)? PC-=b	*/
+ONTJMP,/*	S	x		(x!=nil)? x : -	(x!=nil)? PC+=s	*/
+ONFJMP,/*	S	x		(x==nil)? x : -	(x==nil)? PC+=s	*/
+JMP,/*		S	-		-		PC+=s		*/
+IFTJMP,/*	S	x		-		(x!=nil)? PC+=s	*/
+IFFJMP,/*	S	x		-		(x==nil)? PC+=s	*/
 
 
-CLOSUREW,/*	w c	v_c-v_1		closure(CNST[w], v_c-v_1)	*/
-CLOSURE,/*	b c	v_c-v_1		closure(CNST[b], v_c-v_1)	*/
+CLOSURE,/*	A B	v_b-v_1		closure(CNST[a], v_b-v_1)	*/
 
 
-SETLINEW,/*	w	-		-		LINE=w		*/
-SETLINE,/*	b	-		-		LINE=b		*/
-
-LONGARGW,/*	w	(add w*(1<<16) to arg of next instruction)	*/
-LONGARG /*	b	(add b*(1<<16) to arg of next instruction)	*/
+SETLINE/*	U	-		-		LINE=u		*/
 
 
 } OpCode;
 } OpCode;
 
 
 
 
 #define RFIELDS_PER_FLUSH 32	/* records (SETMAP) */
 #define RFIELDS_PER_FLUSH 32	/* records (SETMAP) */
-#define LFIELDS_PER_FLUSH 64    /* FPF - lists (SETLIST) */
-
-#define ZEROVARARG	128
-
-
-/* maximum value of an arg of 3 bytes; must fit in an "int" */
-#if MAX_INT < (1<<24)
-#define MAX_ARG	MAX_INT
-#else
-#define MAX_ARG	((1<<24)-1)
-#endif
-
-/* maximum value of a word of 2 bytes; cannot be larger than MAX_ARG */
-#if MAX_ARG < (1<<16)
-#define MAX_WORD	MAX_ARG
-#else
-#define MAX_WORD	((1<<16)-1)
-#endif
-
-
-/* maximum value of a byte */
-#define MAX_BYTE	((1<<8)-1)
+#define LFIELDS_PER_FLUSH 64    /* FPF - lists (SETLIST) (<MAXARG_B) */
 
 
 
 
 #endif
 #endif

+ 122 - 210
lparser.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lparser.c,v 1.57 2000/01/28 16:53:00 roberto Exp roberto $
+** $Id: lparser.c,v 1.58 2000/02/11 16:52:54 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -20,30 +20,27 @@
 
 
 
 
 
 
-/* size of a "normal" jump instruction: OpCode + 1 byte */
-#define JMPSIZE	2
-
 /* maximum number of local variables */
 /* maximum number of local variables */
 #ifndef MAXLOCALS
 #ifndef MAXLOCALS
-#define MAXLOCALS 200  /* arbitrary limit (<256) */
+#define MAXLOCALS 200  /* arbitrary limit (<MAXARG_B) */
 #endif
 #endif
 
 
 
 
 /* maximum number of upvalues */
 /* maximum number of upvalues */
 #ifndef MAXUPVALUES
 #ifndef MAXUPVALUES
-#define MAXUPVALUES 32  /* arbitrary limit (<256) */
+#define MAXUPVALUES 32  /* arbitrary limit (<MAXARG_B) */
 #endif
 #endif
 
 
 
 
 /* maximum number of variables in the left side of an assignment */
 /* maximum number of variables in the left side of an assignment */
 #ifndef MAXVARSLH
 #ifndef MAXVARSLH
-#define MAXVARSLH	100  /* arbitrary limit (<255) */
+#define MAXVARSLH	100  /* arbitrary limit (<MAXARG_B) */
 #endif
 #endif
 
 
 
 
 /* maximum number of parameters in a function */
 /* maximum number of parameters in a function */
 #ifndef MAXPARAMS
 #ifndef MAXPARAMS
-#define MAXPARAMS	100  /* arbitrary limit (<ZEROVARARG) */
+#define MAXPARAMS	100  /* arbitrary limit (<MAXLOCALS) */
 #endif
 #endif
 
 
 
 
@@ -57,7 +54,7 @@ typedef enum {
   VLOCAL,   /* info is stack index */
   VLOCAL,   /* info is stack index */
   VDOT,     /* info is constant index of index name */
   VDOT,     /* info is constant index of index name */
   VINDEXED, /* no info (table and index are on the stack) */
   VINDEXED, /* no info (table and index are on the stack) */
-  VEXP      /* info is pc index of `nparam' of a call (or 0 if exp is closed) */
+  VEXP      /* info is pc index of a call (or 0 if exp is closed) */
 } varkind;
 } varkind;
 
 
 typedef struct vardesc {
 typedef struct vardesc {
@@ -70,7 +67,7 @@ typedef struct vardesc {
 ** Expression List descriptor:
 ** Expression List descriptor:
 ** tells number of expressions in the list,
 ** tells number of expressions in the list,
 ** and, if last expression is open (a function call),
 ** and, if last expression is open (a function call),
-** where is its pc index of `nparam'
+** where is the call pc index.
 */
 */
 typedef struct listdesc {
 typedef struct listdesc {
   int n;
   int n;
@@ -96,7 +93,6 @@ typedef struct FuncState {
   struct FuncState *prev;  /* enclosing function */
   struct FuncState *prev;  /* enclosing function */
   int pc;  /* next position to code */
   int pc;  /* next position to code */
   int stacksize;  /* number of values on activation register */
   int stacksize;  /* number of values on activation register */
-  int maxstacksize;  /* maximum number of values on activation register */
   int nlocalvar;  /* number of active local variables */
   int nlocalvar;  /* number of active local variables */
   int nupvalues;  /* number of upvalues */
   int nupvalues;  /* number of upvalues */
   int nvars;  /* number of entries in f->locvars (-1 if no debug information) */
   int nvars;  /* number of entries in f->locvars (-1 if no debug information) */
@@ -131,89 +127,63 @@ static void checklimit (LexState *ls, int val, int limit, const char *msg) {
 }
 }
 
 
 
 
-static void check_pc (LexState *ls, int n) {
-  luaM_growvector(ls->L, ls->fs->f->code, ls->fs->pc, n,
-                  Byte, codeEM, MAX_INT);
+static int code_instruction (LexState *ls, Instruction i) {
+  FuncState *fs = ls->fs;
+  luaM_growvector(ls->L, fs->f->code, fs->pc, 1, Instruction, codeEM, MAXARG_S);
+  fs->f->code[fs->pc] = i;
+  return fs->pc++;
 }
 }
 
 
 
 
-static void code_byte (LexState *ls, Byte c) {
-  check_pc(ls, 1);
-  ls->fs->f->code[ls->fs->pc++] = c;
+static void fix_jump (LexState *ls, int pc, int dest) {
+  Instruction *jmp = &ls->fs->f->code[pc];
+  /* jump is relative to position following jump instruction */
+  *jmp = SETARG_S(*jmp, dest-(pc+1));
 }
 }
 
 
 
 
 static void deltastack (LexState *ls, int delta) {
 static void deltastack (LexState *ls, int delta) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   fs->stacksize += delta;
   fs->stacksize += delta;
-  if (fs->stacksize > fs->maxstacksize) {
-    if (fs->stacksize > MAX_BYTE)
-      luaY_error(ls, "function or expression too complex");
-    fs->maxstacksize = fs->stacksize;
+  if (delta > 0 && fs->stacksize > fs->f->maxstacksize) {
+    fs->f->maxstacksize = fs->stacksize;
   }
   }
 }
 }
 
 
 
 
-static void code_oparg_at (LexState *ls, int pc, OpCode op,
-                           int arg, int delta) {
-  Byte *code = ls->fs->f->code;
+static int aux_code (LexState *ls, OpCode op, Instruction i, int delta) {
   deltastack(ls, delta);
   deltastack(ls, delta);
-  if (arg <= MAX_BYTE) {
-    code[pc] = (Byte)op;
-    code[pc+1] = (Byte)arg;
-  }
-  else if (arg > MAX_ARG)
-    luaY_error(ls, "code too long");
-  else {  /* MAX_BYTE < arg < MAX_ARG */
-    if (arg > MAX_WORD) {
-      code[pc] = (Byte)LONGARG;
-      code[pc+1] = (Byte)(arg>>16);
-      pc += 2;
-    }
-    code[pc] = (Byte)(op-1);  /* opcode for word argument */
-    code[pc+1] = (Byte)((arg&0xFFFF)>>8);
-    code[pc+2] = (Byte)(arg&0xFF);
-  }
+  return code_instruction(ls, SET_OPCODE(i, op));
 }
 }
 
 
 
 
-static int codesize (int arg) {
-  if      (arg <= MAX_BYTE) return 2;  /* opcode + 1 byte */
-  else if (arg <= MAX_WORD) return 3;  /* opcode + 1 word (2 bytes) */
-  else return 5;    /* LONGARG + 1 byte + opcode + 1 word (2 bytes) */
+static int code_0 (LexState *ls, OpCode op, int delta) {
+  return aux_code(ls, op, 0, delta);
 }
 }
 
 
 
 
-static int fix_opcode (LexState *ls, int pc, OpCode op, int arg) {
-  int tomove = codesize(arg)-2;
-  if (tomove > 0) {  /* need to open space? */
-    FuncState *fs = ls->fs;
-    TProtoFunc *f = fs->f;
-    check_pc(ls, tomove);
-    luaO_memup(f->code+pc+tomove, f->code+pc, fs->pc-pc);
-    fs->pc += tomove;
-  }
-  code_oparg_at(ls, pc, op, arg, 0);
-  return tomove;
+
+static int code_U (LexState *ls, OpCode op, int u, int delta) {
+  Instruction i = SETARG_U(0, u);
+  return aux_code(ls, op, i, delta);
 }
 }
 
 
 
 
-static void code_oparg (LexState *ls, OpCode op, int arg, int delta) {
-  int size = codesize(arg);
-  check_pc(ls, size);
-  code_oparg_at(ls, ls->fs->pc, op, arg, delta);
-  ls->fs->pc += size;
+static int code_S (LexState *ls, OpCode op, int s, int delta) {
+  Instruction i = SETARG_S(0, s);
+  return aux_code(ls, op, i, delta);
 }
 }
 
 
 
 
-static void code_opcode (LexState *ls, OpCode op, int delta) {
-  deltastack(ls, delta);
-  code_byte(ls, (Byte)op);
+static int code_AB (LexState *ls, OpCode op, int a, int b, int delta) {
+  Instruction i = SETARG_A(0, a);
+  i = SETARG_B(i, b);
+  return aux_code(ls, op, i, delta);
 }
 }
 
 
 
 
 static void code_kstr (LexState *ls, int c) {
 static void code_kstr (LexState *ls, int c) {
-  code_oparg(ls, PUSHSTRING, c, 1);
+  code_U(ls, PUSHSTRING, c, 1);
 }
 }
 
 
 
 
@@ -226,8 +196,8 @@ static int string_constant (LexState *ls, FuncState *fs, TaggedString *s) {
   TProtoFunc *f = fs->f;
   TProtoFunc *f = fs->f;
   int c = s->constindex;
   int c = s->constindex;
   if (c >= f->nkstr || f->kstr[c] != s) {
   if (c >= f->nkstr || f->kstr[c] != s) {
-    luaM_growvector(ls->L, f->kstr, f->nkstr, 1,
-                    TaggedString *, constantEM, MAX_ARG);
+    luaM_growvector(ls->L, f->kstr, f->nkstr, 1, TaggedString *,
+                    constantEM, MAXARG_U);
     c = f->nkstr++;
     c = f->nkstr++;
     f->kstr[c] = s;
     f->kstr[c] = s;
     s->constindex = c;  /* hint for next time */
     s->constindex = c;  /* hint for next time */
@@ -250,8 +220,7 @@ static int real_constant (LexState *ls, real r) {
   while (--c >= lim)
   while (--c >= lim)
     if (f->knum[c] == r) return c;
     if (f->knum[c] == r) return c;
   /* not found; create a new entry */
   /* not found; create a new entry */
-  luaM_growvector(ls->L, f->knum, f->nknum, 1,
-                  real, constantEM, MAX_ARG);
+  luaM_growvector(ls->L, f->knum, f->nknum, 1, real, constantEM, MAXARG_U);
   c = f->nknum++;
   c = f->nknum++;
   f->knum[c] = r;
   f->knum[c] = r;
   return c;
   return c;
@@ -259,27 +228,10 @@ static int real_constant (LexState *ls, real r) {
 
 
 
 
 static void code_number (LexState *ls, real f) {
 static void code_number (LexState *ls, real f) {
-  real af = (f<0) ? -f : f;
-  if (0 <= af && af <= (real)MAX_WORD && (int)af == af) {
-    /* abs(f) has a short integer value */
-    code_oparg(ls, (f<0) ? PUSHINTNEG : PUSHINT, (int)af, 1);
-  }
+  if ((real)(-MAXARG_S) <= f && f <= (real)MAXARG_S && (int)f == f)
+    code_S(ls, PUSHINT, (int)f, 1);  /* f has a short integer value */
   else
   else
-    code_oparg(ls, PUSHNUMBER, real_constant(ls, f), 1);
-}
-
-
-static void flush_record (LexState *ls, int n) {
-  if (n > 0)
-    code_oparg(ls, SETMAP, n-1, -2*n);
-}
-
-
-static void flush_list (LexState *ls, int m, int n) {
-  if (n > 0) {
-    code_oparg(ls, SETLIST, m, -n);
-    code_byte(ls, (Byte)n);
-  }
+    code_U(ls, PUSHNUMBER, real_constant(ls, f), 1);
 }
 }
 
 
 
 
@@ -371,14 +323,14 @@ static void pushupvalue (LexState *ls, TaggedString *n) {
     luaX_syntaxerror(ls, "cannot access upvalue in main", n->str);
     luaX_syntaxerror(ls, "cannot access upvalue in main", n->str);
   if (aux_localname(ls->fs, n) >= 0)
   if (aux_localname(ls->fs, n) >= 0)
     luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str);
     luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str);
-  code_oparg(ls, PUSHUPVALUE, indexupvalue(ls, n), 1);
+  code_U(ls, PUSHUPVALUE, indexupvalue(ls, n), 1);
 }
 }
 
 
 
 
 
 
 static void check_debugline (LexState *ls) {
 static void check_debugline (LexState *ls) {
   if (ls->L->debug && ls->linenumber != ls->fs->lastsetline) {
   if (ls->L->debug && ls->linenumber != ls->fs->lastsetline) {
-    code_oparg(ls, SETLINE, ls->linenumber, 0);
+    code_U(ls, SETLINE, ls->linenumber, 0);
     ls->fs->lastsetline = ls->linenumber;
     ls->fs->lastsetline = ls->linenumber;
   }
   }
 }
 }
@@ -386,16 +338,16 @@ static void check_debugline (LexState *ls) {
 
 
 static void adjuststack (LexState *ls, int n) {
 static void adjuststack (LexState *ls, int n) {
   if (n > 0)
   if (n > 0)
-    code_oparg(ls, POP, n, -n);
+    code_U(ls, POP, n, -n);
   else if (n < 0)
   else if (n < 0)
-    code_oparg(ls, PUSHNIL, (-n)-1, -n);
+    code_U(ls, PUSHNIL, (-n)-1, -n);
 }
 }
 
 
 
 
 static void close_exp (LexState *ls, int pc, int nresults) {
 static void close_exp (LexState *ls, int pc, int nresults) {
   if (pc > 0) {  /* expression is an open function call? */
   if (pc > 0) {  /* expression is an open function call? */
-    Byte *code = ls->fs->f->code;
-    code[pc-1] = (Byte)nresults;  /* set nresults */
+    Instruction *i = &ls->fs->f->code[pc];
+    *i = SETARG_B(*i, nresults);  /* set nresults */
     if (nresults != MULT_RET)
     if (nresults != MULT_RET)
       deltastack(ls, nresults);  /* push results */
       deltastack(ls, nresults);  /* push results */
   }
   }
@@ -426,13 +378,12 @@ static void code_args (LexState *ls, int nparams, int dots) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   adjustlocalvars(ls, nparams, 0);
   adjustlocalvars(ls, nparams, 0);
   checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters");
   checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters");
-  nparams = fs->nlocalvar;
-  if (!dots) {
-    fs->f->code[1] = (Byte)nparams;  /* fill-in arg information */
+  nparams = fs->nlocalvar;  /* `self' could be there already */
+  fs->f->numparams = nparams;
+  fs->f->is_vararg = dots;
+  if (!dots)
     deltastack(ls, nparams);
     deltastack(ls, nparams);
-  }
   else {
   else {
-    fs->f->code[1] = (Byte)(nparams+ZEROVARARG);
     deltastack(ls, nparams+1);
     deltastack(ls, nparams+1);
     add_localvar(ls, luaS_newfixed(ls->L, "arg"));
     add_localvar(ls, luaS_newfixed(ls->L, "arg"));
   }
   }
@@ -451,17 +402,17 @@ static void unloaddot (LexState *ls, vardesc *v) {
 static void lua_pushvar (LexState *ls, vardesc *var) {
 static void lua_pushvar (LexState *ls, vardesc *var) {
   switch (var->k) {
   switch (var->k) {
     case VLOCAL:
     case VLOCAL:
-      code_oparg(ls, PUSHLOCAL, var->info, 1);
+      code_U(ls, PUSHLOCAL, var->info, 1);
       break;
       break;
     case VGLOBAL:
     case VGLOBAL:
-      code_oparg(ls, GETGLOBAL, var->info, 1);
+      code_U(ls, GETGLOBAL, var->info, 1);
       assertglobal(ls, var->info);  /* make sure that there is a global */
       assertglobal(ls, var->info);  /* make sure that there is a global */
       break;
       break;
     case VDOT:
     case VDOT:
-      code_oparg(ls, GETDOTTED, var->info, 0);
+      code_U(ls, GETDOTTED, var->info, 0);
       break;
       break;
     case VINDEXED:
     case VINDEXED:
-      code_opcode(ls, GETTABLE, -1);
+      code_0(ls, GETTABLE, -1);
       break;
       break;
     case VEXP:
     case VEXP:
       close_exp(ls, var->info, 1);  /* function must return 1 value */
       close_exp(ls, var->info, 1);  /* function must return 1 value */
@@ -475,14 +426,14 @@ static void lua_pushvar (LexState *ls, vardesc *var) {
 static void storevar (LexState *ls, const vardesc *var) {
 static void storevar (LexState *ls, const vardesc *var) {
   switch (var->k) {
   switch (var->k) {
     case VLOCAL:
     case VLOCAL:
-      code_oparg(ls, SETLOCAL, var->info, -1);
+      code_U(ls, SETLOCAL, var->info, -1);
       break;
       break;
     case VGLOBAL:
     case VGLOBAL:
-      code_oparg(ls, SETGLOBAL, var->info, -1);
+      code_U(ls, SETGLOBAL, var->info, -1);
       assertglobal(ls, var->info);  /* make sure that there is a global */
       assertglobal(ls, var->info);  /* make sure that there is a global */
       break;
       break;
     case VINDEXED:
     case VINDEXED:
-      code_opcode(ls, SETTABLEPOP, -3);
+      code_0(ls, SETTABLEPOP, -3);
       break;
       break;
     default:
     default:
       LUA_INTERNALERROR(ls->L, "invalid var kind to store");
       LUA_INTERNALERROR(ls->L, "invalid var kind to store");
@@ -490,43 +441,16 @@ static void storevar (LexState *ls, const vardesc *var) {
 }
 }
 
 
 
 
-static int fix_jump (LexState *ls, int pc, OpCode op, int n) {
-  /* jump is relative to position following jump instruction */
-  return fix_opcode(ls, pc, op, n-(pc+JMPSIZE));
-}
-
-
-static void fix_upjmp (LexState *ls, OpCode op, int pos) {
-  int delta = ls->fs->pc+JMPSIZE - pos;  /* jump is relative */
-  code_oparg(ls, op, delta+(codesize(delta)-2), 0);
-}
-
-
-static void codeIf (LexState *ls, int thenAdd, int elseAdd) {
-  FuncState *fs = ls->fs;
-  int elseinit = elseAdd+JMPSIZE;
-  if (fs->pc == elseinit) {  /* no else part? */
-    fs->pc -= JMPSIZE;
-    elseinit = fs->pc;
-  }
-  else
-    elseinit += fix_jump(ls, elseAdd, JMP, fs->pc);
-  fix_jump(ls, thenAdd, IFFJMP, elseinit);
-}
-
-
 static void func_onstack (LexState *ls, FuncState *func) {
 static void func_onstack (LexState *ls, FuncState *func) {
-  FuncState *fs = ls->fs;
-  TProtoFunc *f = fs->f;
+  TProtoFunc *f = ls->fs->f;
   int i;
   int i;
-  luaM_growvector(ls->L, f->kproto, f->nkproto, 1,
-                  TProtoFunc *, constantEM, MAX_ARG);
-  f->kproto[f->nkproto] = func->f;
   for (i=0; i<func->nupvalues; i++)
   for (i=0; i<func->nupvalues; i++)
     lua_pushvar(ls, &func->upvalues[i]);
     lua_pushvar(ls, &func->upvalues[i]);
+  luaM_growvector(ls->L, f->kproto, f->nkproto, 1, TProtoFunc *,
+                  constantEM, MAXARG_A);
+  f->kproto[f->nkproto++] = func->f;
   deltastack(ls, 1);  /* CLOSURE puts one extra element (before popping) */
   deltastack(ls, 1);  /* CLOSURE puts one extra element (before popping) */
-  code_oparg(ls, CLOSURE, f->nkproto++, -func->nupvalues);
-  code_byte(ls, (Byte)func->nupvalues);
+  code_AB(ls, CLOSURE, f->nkproto-1, func->nupvalues, -func->nupvalues);
 }
 }
 
 
 
 
@@ -536,7 +460,6 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) {
   fs->prev = ls->fs;  /* linked list of funcstates */
   fs->prev = ls->fs;  /* linked list of funcstates */
   ls->fs = fs;
   ls->fs = fs;
   fs->stacksize = 0;
   fs->stacksize = 0;
-  fs->maxstacksize = 0;
   fs->nlocalvar = 0;
   fs->nlocalvar = 0;
   fs->nupvalues = 0;
   fs->nupvalues = 0;
   fs->lastsetline = 0;
   fs->lastsetline = 0;
@@ -544,9 +467,10 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) {
   f->source = source;
   f->source = source;
   fs->pc = 0;
   fs->pc = 0;
   f->code = NULL;
   f->code = NULL;
+  f->maxstacksize = 0;
+  f->numparams = 0;  /* default for main chunk */
+  f->is_vararg = 0;  /* default for main chunk */
   fs->nvars = (L->debug) ? 0 : -1;  /* flag no debug information? */
   fs->nvars = (L->debug) ? 0 : -1;  /* flag no debug information? */
-  code_byte(ls, 0);  /* to be filled with maxstacksize */
-  code_byte(ls, 0);  /* to be filled with arg information */
   /* push function (to avoid GC) */
   /* push function (to avoid GC) */
   tfvalue(L->top) = f;
   tfvalue(L->top) = f;
   ttype(L->top) = LUA_T_LPROTO;
   ttype(L->top) = LUA_T_LPROTO;
@@ -557,9 +481,8 @@ static void init_state (LexState *ls, FuncState *fs, TaggedString *source) {
 static void close_func (LexState *ls) {
 static void close_func (LexState *ls) {
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
   TProtoFunc *f = fs->f;
   TProtoFunc *f = fs->f;
-  code_opcode(ls, ENDCODE, 0);
-  f->code[0] = (Byte)fs->maxstacksize;
-  luaM_reallocvector(ls->L, f->code, fs->pc, Byte);
+  code_0(ls, ENDCODE, 0);
+  luaM_reallocvector(ls->L, f->code, fs->pc, Instruction);
   luaM_reallocvector(ls->L, f->kstr, f->nkstr, TaggedString *);
   luaM_reallocvector(ls->L, f->kstr, f->nkstr, TaggedString *);
   luaM_reallocvector(ls->L, f->knum, f->nknum, real);
   luaM_reallocvector(ls->L, f->knum, f->nknum, real);
   luaM_reallocvector(ls->L, f->kproto, f->nkproto, TProtoFunc *);
   luaM_reallocvector(ls->L, f->kproto, f->nkproto, TProtoFunc *);
@@ -662,28 +585,6 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) {
 /*============================================================*/
 /*============================================================*/
 
 
 
 
-
-static int SaveWord (LexState *ls) {
-  int res = ls->fs->pc;
-  check_pc(ls, JMPSIZE);
-  ls->fs->pc += JMPSIZE;  /* open space */
-  return res;
-}
-
-
-static int SaveWordPop (LexState *ls) {
-  deltastack(ls, -1);  /* pop condition */
-  return SaveWord(ls);
-}
-
-
-static int cond (LexState *ls) {
-  /* cond -> exp1 */
-  exp1(ls);
-  return SaveWordPop(ls);
-}
-
-
 static void explist1 (LexState *ls, listdesc *d) {
 static void explist1 (LexState *ls, listdesc *d) {
   vardesc v;
   vardesc v;
   expr(ls, &v);
   expr(ls, &v);
@@ -744,11 +645,8 @@ static int funcparams (LexState *ls, int slf) {
       luaY_error(ls, "function arguments expected");
       luaY_error(ls, "function arguments expected");
       break;
       break;
   }
   }
-  code_byte(ls, CALL);
-  code_byte(ls, 0);  /* save space for nresult */
-  code_byte(ls, (Byte)slevel);
   fs->stacksize = slevel;  /* call will remove func and params */
   fs->stacksize = slevel;  /* call will remove func and params */
-  return fs->pc-1;
+  return code_AB(ls, CALL, slevel, 0, 0);
 }
 }
 
 
 
 
@@ -775,7 +673,7 @@ static void var_or_func_tail (LexState *ls, vardesc *v) {
         next(ls);
         next(ls);
         name = checkname(ls);
         name = checkname(ls);
         lua_pushvar(ls, v);  /* `v' must be on stack */
         lua_pushvar(ls, v);  /* `v' must be on stack */
-        code_oparg(ls, PUSHSELF, name, 1);
+        code_U(ls, PUSHSELF, name, 1);
         v->k = VEXP;
         v->k = VEXP;
         v->info = funcparams(ls, 1);
         v->info = funcparams(ls, 1);
         break;
         break;
@@ -836,16 +734,20 @@ static void recfield (LexState *ls) {
 static int recfields (LexState *ls) {
 static int recfields (LexState *ls) {
   /* recfields -> { ',' recfield } [','] */
   /* recfields -> { ',' recfield } [','] */
   int n = 1;  /* one has been read before */
   int n = 1;  /* one has been read before */
+  int mod_n = 1;  /* mod_n == n%RFIELDS_PER_FLUSH */
   while (ls->token == ',') {
   while (ls->token == ',') {
     next(ls);
     next(ls);
     if (ls->token == ';' || ls->token == '}')
     if (ls->token == ';' || ls->token == '}')
       break;
       break;
     recfield(ls);
     recfield(ls);
     n++;
     n++;
-    if (n%RFIELDS_PER_FLUSH == 0)
-      flush_record(ls, RFIELDS_PER_FLUSH);
+    if (++mod_n == RFIELDS_PER_FLUSH) {
+      code_U(ls, SETMAP, RFIELDS_PER_FLUSH-1, -2*RFIELDS_PER_FLUSH);
+      mod_n = 0;
+    }
   }
   }
-  flush_record(ls, n%RFIELDS_PER_FLUSH);
+  if (mod_n)
+    code_U(ls, SETMAP, mod_n-1, -2*mod_n);
   return n;
   return n;
 }
 }
 
 
@@ -853,16 +755,23 @@ static int recfields (LexState *ls) {
 static int listfields (LexState *ls) {
 static int listfields (LexState *ls) {
   /* listfields -> { ',' exp1 } [','] */
   /* listfields -> { ',' exp1 } [','] */
   int n = 1;  /* one has been read before */
   int n = 1;  /* one has been read before */
+  int mod_n = 1;  /* mod_n == n%LFIELDS_PER_FLUSH */
   while (ls->token == ',') {
   while (ls->token == ',') {
     next(ls);
     next(ls);
     if (ls->token == ';' || ls->token == '}')
     if (ls->token == ';' || ls->token == '}')
       break;
       break;
     exp1(ls);
     exp1(ls);
     n++;
     n++;
-    if (n%LFIELDS_PER_FLUSH == 0)
-      flush_list(ls, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH);
+    checklimit(ls, n, MAXARG_A*LFIELDS_PER_FLUSH,
+               "items in a list initializer");
+    if (++mod_n == LFIELDS_PER_FLUSH) {
+      code_AB(ls, SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH-1,
+              -LFIELDS_PER_FLUSH);
+      mod_n = 0;
+    }
   }
   }
-  flush_list(ls, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH);
+  if (mod_n > 0)
+    code_AB(ls, SETLIST, n/LFIELDS_PER_FLUSH, mod_n-1, -mod_n);
   return n;
   return n;
 }
 }
 
 
@@ -920,10 +829,9 @@ static void constructor_part (LexState *ls, constdesc *cd) {
 static void constructor (LexState *ls) {
 static void constructor (LexState *ls) {
   /* constructor -> '{' constructor_part [';' constructor_part] '}' */
   /* constructor -> '{' constructor_part [';' constructor_part] '}' */
   int line = ls->linenumber;
   int line = ls->linenumber;
-  int pc = SaveWord(ls);
+  int pc = code_U(ls, CREATETABLE, 0, 1);
   int nelems;
   int nelems;
   constdesc cd;
   constdesc cd;
-  deltastack(ls, 1);
   check(ls, '{');
   check(ls, '{');
   constructor_part(ls, &cd);
   constructor_part(ls, &cd);
   nelems = cd.n;
   nelems = cd.n;
@@ -936,7 +844,8 @@ static void constructor (LexState *ls) {
     nelems += other_cd.n;
     nelems += other_cd.n;
   }
   }
   check_match(ls, '}', '{', line);
   check_match(ls, '}', '{', line);
-  fix_opcode(ls, pc, CREATEARRAY, nelems);
+  /* set initial table size */
+  ls->fs->f->code[pc] = SETARG_U(ls->fs->f->code[pc], nelems);
 }
 }
 
 
 /* }====================================================================== */
 /* }====================================================================== */
@@ -1009,7 +918,7 @@ static void push (LexState *ls, stack_op *s, int op) {
 static void pop_to (LexState *ls, stack_op *s, int prio) {
 static void pop_to (LexState *ls, stack_op *s, int prio) {
   int op;
   int op;
   while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) {
   while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) {
-    code_opcode(ls, opcodes[op], op<FIRSTBIN?0:-1);
+    code_0(ls, opcodes[op], op<FIRSTBIN?0:-1);
     s->top--;
     s->top--;
   }
   }
 }
 }
@@ -1113,10 +1022,10 @@ static void expr (LexState *ls, vardesc *v) {
     int pc;
     int pc;
     lua_pushvar(ls, v);
     lua_pushvar(ls, v);
     next(ls);
     next(ls);
-    pc = SaveWordPop(ls);
+    pc = code_S(ls, op, 0, -1);
     arith_exp(ls, v);
     arith_exp(ls, v);
     lua_pushvar(ls, v);
     lua_pushvar(ls, v);
-    fix_jump(ls, pc, op, ls->fs->pc);
+    fix_jump(ls, pc, ls->fs->pc);
   }
   }
 }
 }
 
 
@@ -1167,7 +1076,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) {
     storevar(ls, v);
     storevar(ls, v);
   }
   }
   else {  /* indexed var with values in between*/
   else {  /* indexed var with values in between*/
-    code_oparg(ls, SETTABLE, left+(nvars-1), -1);
+    code_U(ls, SETTABLE, left+(nvars-1), -1);
     left += 2;  /* table&index are not popped, because they aren't on top */
     left += 2;  /* table&index are not popped, because they aren't on top */
   }
   }
   return left;
   return left;
@@ -1175,22 +1084,18 @@ static int assignment (LexState *ls, vardesc *v, int nvars) {
 
 
 
 
 static void whilestat (LexState *ls, int line) {
 static void whilestat (LexState *ls, int line) {
-  /* whilestat -> WHILE cond DO block END */
+  /* whilestat -> WHILE exp1 DO block END */
   FuncState *fs = ls->fs;
   FuncState *fs = ls->fs;
-  TProtoFunc *f = fs->f;
   int while_init = fs->pc;
   int while_init = fs->pc;
-  int cond_end, cond_size;
+  int j1;
   next(ls);
   next(ls);
-  cond_end = cond(ls);
+  exp1(ls);
+  j1 = code_U(ls, IFFJMP, 0, -1);  /* jump to exit loop */
   check(ls, DO);
   check(ls, DO);
   block(ls);
   block(ls);
   check_match(ls, END, WHILE, line);
   check_match(ls, END, WHILE, line);
-  cond_size = cond_end-while_init;
-  check_pc(ls, cond_size);
-  memcpy(f->code+fs->pc, f->code+while_init, cond_size);
-  luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init);
-  while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size);
-  fix_upjmp(ls, IFTUPJMP, while_init);
+  fix_jump(ls, code_U(ls, JMP, 0, 0), while_init);  /* jump to keep loop */
+  fix_jump(ls, j1, fs->pc);
 }
 }
 
 
 
 
@@ -1202,8 +1107,7 @@ static void repeatstat (LexState *ls, int line) {
   block(ls);
   block(ls);
   check_match(ls, UNTIL, REPEAT, line);
   check_match(ls, UNTIL, REPEAT, line);
   exp1(ls);
   exp1(ls);
-  fix_upjmp(ls, IFFUPJMP, repeat_init);
-  deltastack(ls, -1);  /* pops condition */
+  fix_jump(ls, code_U(ls, IFFJMP, 0, -1), repeat_init);
 }
 }
 
 
 
 
@@ -1295,21 +1199,29 @@ static void namestat (LexState *ls) {
 
 
 static void ifpart (LexState *ls, int line) {
 static void ifpart (LexState *ls, int line) {
   /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */
   /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */
+  FuncState *fs = ls->fs;
   int c;
   int c;
-  int e;
+  int je;
   next(ls);  /* skip IF or ELSEIF */
   next(ls);  /* skip IF or ELSEIF */
-  c = cond(ls);
+  exp1(ls);  /* cond */
+  c = code_U(ls, IFFJMP, 0, -1);  /* jump `then' if `cond' is false */
   check(ls, THEN);
   check(ls, THEN);
-  block(ls);
-  e = SaveWord(ls);
+  block(ls);  /* `then' part */
+  je = code_U(ls, JMP, 0, 0);  /* jump `else' part after `then' */
   if (ls->token == ELSEIF)
   if (ls->token == ELSEIF)
     ifpart(ls, line);
     ifpart(ls, line);
   else {
   else {
     if (optional(ls, ELSE))
     if (optional(ls, ELSE))
-      block(ls);
+      block(ls);  /* `else' part */
     check_match(ls, END, IF, line);
     check_match(ls, END, IF, line);
   }
   }
-  codeIf(ls, c, e);
+  if (fs->pc == je+1) {  /* `else' part empty? */
+    fs->pc--;  /* remove last jump */
+    je--;  /* first jump will be smaller */
+  }
+  else
+    fix_jump(ls, je, fs->pc);  /* fix last jump */
+  fix_jump(ls, c, je+1);  /* fix first jump to beginning of `else' part */
 }
 }
 
 
 
 
@@ -1395,9 +1307,9 @@ static void parlist (LexState *ls) {
 
 
 static void body (LexState *ls, int needself, int line) {
 static void body (LexState *ls, int needself, int line) {
   /* body ->  '(' parlist ')' chunk END */
   /* body ->  '(' parlist ')' chunk END */
-  FuncState newfs;
-  init_state(ls, &newfs, ls->fs->f->source);
-  newfs.f->lineDefined = line;
+  FuncState new_fs;
+  init_state(ls, &new_fs, ls->fs->f->source);
+  new_fs.f->lineDefined = line;
   check(ls, '(');
   check(ls, '(');
   if (needself)
   if (needself)
     add_localvar(ls, luaS_newfixed(ls->L, "self"));
     add_localvar(ls, luaS_newfixed(ls->L, "self"));
@@ -1406,7 +1318,7 @@ static void body (LexState *ls, int needself, int line) {
   chunk(ls);
   chunk(ls);
   check_match(ls, END, FUNCTION, line);
   check_match(ls, END, FUNCTION, line);
   close_func(ls);
   close_func(ls);
-  func_onstack(ls, &newfs);
+  func_onstack(ls, &new_fs);
 }
 }
 
 
 
 
@@ -1418,12 +1330,12 @@ static void ret (LexState *ls) {
     next(ls);
     next(ls);
     explist(ls, &e); 
     explist(ls, &e); 
     if (e.pc > 0) {  /* expression is an open function call? */
     if (e.pc > 0) {  /* expression is an open function call? */
-      Byte *code = ls->fs->f->code;
-      code[e.pc-2] = TAILCALL;  /* instead of a conventional CALL */
-      code[e.pc-1] = (Byte)ls->fs->nlocalvar;
+      Instruction *i = &ls->fs->f->code[e.pc];
+      *i = SET_OPCODE(*i, TAILCALL);  /* instead of a conventional CALL */
+      *i = SETARG_B(*i, ls->fs->nlocalvar);
     }
     }
     else
     else
-      code_oparg(ls, RETCODE, ls->fs->nlocalvar, 0);
+      code_U(ls, RETCODE, ls->fs->nlocalvar, 0);
     ls->fs->stacksize = ls->fs->nlocalvar;  /* removes all temp values */
     ls->fs->stacksize = ls->fs->nlocalvar;  /* removes all temp values */
     optional(ls, ';');
     optional(ls, ';');
   }
   }

+ 97 - 134
lvm.c

@@ -1,5 +1,5 @@
 /*
 /*
-** $Id: lvm.c,v 1.85 2000/02/08 16:39:42 roberto Exp roberto $
+** $Id: lvm.c,v 1.86 2000/02/11 16:52:54 roberto Exp roberto $
 ** Lua virtual machine
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 ** See Copyright Notice in lua.h
 */
 */
@@ -280,6 +280,11 @@ void luaV_comparison (lua_State *L) {
 }
 }
 
 
 
 
+#define setbool(o,cond) if (cond) { \
+                              ttype(o) = LUA_T_NUMBER; nvalue(o) = 1.0; } \
+                        else ttype(o) = LUA_T_NIL
+
+
 void luaV_pack (lua_State *L, StkId firstelem, int nvararg, TObject *tab) {
 void luaV_pack (lua_State *L, StkId firstelem, int nvararg, TObject *tab) {
   int i;
   int i;
   Hash *htab;
   Hash *htab;
@@ -313,90 +318,80 @@ static void adjust_varargs (lua_State *L, StkId base, int nfixargs) {
 StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf,
 StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf,
                     register StkId base) {
                     register StkId base) {
   register StkId top;  /* keep top local, for performance */
   register StkId top;  /* keep top local, for performance */
-  register const Byte *pc = tf->code;
+  register const Instruction *pc = tf->code;
   TaggedString **kstr = tf->kstr;
   TaggedString **kstr = tf->kstr;
   if (L->callhook)
   if (L->callhook)
     luaD_callHook(L, base-1, L->callhook, "call");
     luaD_callHook(L, base-1, L->callhook, "call");
-  luaD_checkstack(L, (*pc++)+EXTRA_STACK);
-  if (*pc < ZEROVARARG)
-    luaD_adjusttop(L, base, *(pc++));
-  else {  /* varargs */
-    adjust_varargs(L, base, (*pc++)-ZEROVARARG);
+  luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK);
+  if (tf->is_vararg) {  /* varargs? */
+    adjust_varargs(L, base, tf->numparams);
     luaC_checkGC(L);
     luaC_checkGC(L);
   }
   }
+  else
+    luaD_adjusttop(L, base, tf->numparams);
   top = L->top;
   top = L->top;
   for (;;) {
   for (;;) {
-    register int aux = 0;
-    switchentry:
-    switch ((OpCode)*pc++) {
+    register Instruction i = *pc++;
+    switch (GET_OPCODE(i)) {
 
 
       case ENDCODE:
       case ENDCODE:
         return L->top;  /* no results */
         return L->top;  /* no results */
 
 
       case RETCODE:
       case RETCODE:
         L->top = top;
         L->top = top;
-        return base+(*pc++);
+        return base+GETARG_U(i);
 
 
-      case CALL: aux = *pc++;
+      case CALL:
         L->top = top;
         L->top = top;
-        luaD_call(L, base+(*pc++), aux);
+        luaD_call(L, base+GETARG_A(i), GETARG_B(i));
         top = L->top;
         top = L->top;
         break;
         break;
 
 
-      case TAILCALL: aux = *pc++;
+      case TAILCALL:
         L->top = top;
         L->top = top;
-        luaD_call(L, base+(*pc++), MULT_RET);
-        return base+aux;
+        luaD_call(L, base+GETARG_A(i), MULT_RET);
+        return base+GETARG_B(i);
 
 
-      case PUSHNIL: aux = *pc++;
+      case PUSHNIL: {
+        register int n = GETARG_U(i);
         do {
         do {
           ttype(top++) = LUA_T_NIL;
           ttype(top++) = LUA_T_NIL;
-        } while (aux--);
-        break;
-
-      case POP: aux = *pc++;
-        top -= aux;
+        } while (n--);
         break;
         break;
+      }
 
 
-      case PUSHINTW: aux += highbyte(L, *pc++);
-      case PUSHINT:  aux += *pc++;
-        ttype(top) = LUA_T_NUMBER;
-        nvalue(top) = aux;
-        top++;
+      case POP:
+        top -= GETARG_U(i);
         break;
         break;
 
 
-      case PUSHINTNEGW: aux += highbyte(L, *pc++);
-      case PUSHINTNEG:  aux += *pc++;
+      case PUSHINT:
         ttype(top) = LUA_T_NUMBER;
         ttype(top) = LUA_T_NUMBER;
-        nvalue(top) = -aux;
+        nvalue(top) = (real)GETARG_S(i);
         top++;
         top++;
         break;
         break;
 
 
-      case PUSHSTRINGW: aux += highbyte(L, *pc++);
-      case PUSHSTRING:  aux += *pc++;
+      case PUSHSTRING:
         ttype(top) = LUA_T_STRING;
         ttype(top) = LUA_T_STRING;
-        tsvalue(top) = kstr[aux];
+        tsvalue(top) = kstr[GETARG_U(i)];
         top++;
         top++;
         break;
         break;
 
 
-      case PUSHNUMBERW: aux += highbyte(L, *pc++);
-      case PUSHNUMBER:  aux += *pc++;
+      case PUSHNUMBER:
         ttype(top) = LUA_T_NUMBER;
         ttype(top) = LUA_T_NUMBER;
-        nvalue(top) = tf->knum[aux];
+        nvalue(top) = tf->knum[GETARG_U(i)];
         top++;
         top++;
         break;
         break;
 
 
-      case PUSHUPVALUE: aux = *pc++;
-        *top++ = cl->consts[aux+1];
+      case PUSHUPVALUE:
+        *top++ = cl->consts[GETARG_U(i)+1];
         break;
         break;
 
 
-      case PUSHLOCAL: aux = *pc++;
-        *top++ = *(base+aux);
+      case PUSHLOCAL:
+        *top++ = *(base+GETARG_U(i));
         break;
         break;
 
 
-      case GETGLOBALW: aux += highbyte(L, *pc++);
-      case GETGLOBAL:  aux += *pc++;
-        luaV_getglobal(L, kstr[aux]->u.s.gv, top);
+      case GETGLOBAL:
+        luaV_getglobal(L, kstr[GETARG_U(i)]->u.s.gv, top);
         top++;
         top++;
         break;
         break;
 
 
@@ -405,41 +400,37 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf,
         top--;
         top--;
         break;
         break;
 
 
-      case GETDOTTEDW: aux += highbyte(L, *pc++);
-      case GETDOTTED:  aux += *pc++;
+      case GETDOTTED:
         ttype(top) = LUA_T_STRING;
         ttype(top) = LUA_T_STRING;
-        tsvalue(top++) = kstr[aux];
+        tsvalue(top++) = kstr[GETARG_U(i)];
         luaV_gettable(L, top);
         luaV_gettable(L, top);
         top--;
         top--;
         break;
         break;
 
 
-      case PUSHSELFW: aux += highbyte(L, *pc++);
-      case PUSHSELF:  aux += *pc++; {
+      case PUSHSELF: {
         TObject receiver;
         TObject receiver;
         receiver = *(top-1);
         receiver = *(top-1);
         ttype(top) = LUA_T_STRING;
         ttype(top) = LUA_T_STRING;
-        tsvalue(top++) = kstr[aux];
+        tsvalue(top++) = kstr[GETARG_U(i)];
         luaV_gettable(L, top);
         luaV_gettable(L, top);
         *(top-1) = receiver;
         *(top-1) = receiver;
         break;
         break;
       }
       }
 
 
-      case CREATEARRAYW: aux += highbyte(L, *pc++);
-      case CREATEARRAY:  aux += *pc++;
+      case CREATETABLE:
         L->top = top;
         L->top = top;
         luaC_checkGC(L);
         luaC_checkGC(L);
-        avalue(top) = luaH_new(L, aux);
+        avalue(top) = luaH_new(L, GETARG_U(i));
         ttype(top) = LUA_T_ARRAY;
         ttype(top) = LUA_T_ARRAY;
         top++;
         top++;
         break;
         break;
 
 
-      case SETLOCAL: aux = *pc++;
-        *(base+aux) = *(--top);
+      case SETLOCAL:
+        *(base+GETARG_U(i)) = *(--top);
         break;
         break;
 
 
-      case SETGLOBALW: aux += highbyte(L, *pc++);
-      case SETGLOBAL:  aux += *pc++;
-        luaV_setglobal(L, kstr[aux]->u.s.gv, top);
+      case SETGLOBAL:
+        luaV_setglobal(L, kstr[GETARG_U(i)]->u.s.gv, top);
         top--;
         top--;
         break;
         break;
 
 
@@ -449,91 +440,81 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf,
         break;
         break;
 
 
       case SETTABLE:
       case SETTABLE:
-        luaV_settable(L, top-3-(*pc++), top);
+        luaV_settable(L, top-3-GETARG_U(i), top);
         top--;  /* pop value */
         top--;  /* pop value */
         break;
         break;
 
 
-      case SETLISTW: aux += highbyte(L, *pc++);
-      case SETLIST:  aux += *pc++; {
-        int n = *(pc++);
+      case SETLIST: {
+        int aux = GETARG_A(i) * LFIELDS_PER_FLUSH;
+        int n = GETARG_B(i)+1;
         Hash *arr = avalue(top-n-1);
         Hash *arr = avalue(top-n-1);
         L->top = top-n;  /* final value of `top' (in case of errors) */
         L->top = top-n;  /* final value of `top' (in case of errors) */
-        aux *= LFIELDS_PER_FLUSH;
         for (; n; n--)
         for (; n; n--)
           luaH_setint(L, arr, n+aux, --top);
           luaH_setint(L, arr, n+aux, --top);
         break;
         break;
       }
       }
 
 
-      case SETMAP:  aux = *pc++; {
-        StkId finaltop = top-2*(aux+1);
+      case SETMAP: {
+        int n = GETARG_U(i);
+        StkId finaltop = top-2*(n+1);
         Hash *arr = avalue(finaltop-1);
         Hash *arr = avalue(finaltop-1);
         L->top = finaltop;  /* final value of `top' (in case of errors) */
         L->top = finaltop;  /* final value of `top' (in case of errors) */
         do {
         do {
           luaH_set(L, arr, top-2, top-1);
           luaH_set(L, arr, top-2, top-1);
           top-=2;
           top-=2;
-        } while (aux--);
+        } while (n--);
         break;
         break;
       }
       }
 
 
-      case NEQOP: aux = 1;
+      case NEQOP:
+        top--;
+        setbool(top-1, !luaO_equalObj(top-1, top));
+        break;
+
       case EQOP:
       case EQOP:
         top--;
         top--;
-        aux = (luaO_equalObj(top-1, top) != aux);
-      booleanresult:
-        if (aux) {
-          ttype(top-1) = LUA_T_NUMBER;
-          nvalue(top-1) = 1.0;
-        }
-        else ttype(top-1) = LUA_T_NIL;
+        setbool(top-1, luaO_equalObj(top-1, top));
         break;
         break;
 
 
       case LTOP:
       case LTOP:
         top--;
         top--;
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
-          aux = nvalue(top-1) < nvalue(top);
+          setbool(top-1, nvalue(top-1) < nvalue(top));
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
-          aux = luaV_strcomp(tsvalue(top-1), tsvalue(top)) < 0;
-        else {
+          setbool(top-1, luaV_strcomp(tsvalue(top-1), tsvalue(top)) < 0);
+        else
           call_binTM(L, top+1, IM_LT, "unexpected type in comparison");
           call_binTM(L, top+1, IM_LT, "unexpected type in comparison");
-          break;
-        }
-        goto booleanresult;
+        break;
 
 
       case LEOP:
       case LEOP:
         top--;
         top--;
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
-          aux = nvalue(top-1) <= nvalue(top);
+          setbool(top-1, nvalue(top-1) <= nvalue(top));
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
-          aux = luaV_strcomp(tsvalue(top-1), tsvalue(top)) <= 0;
-        else {
+          setbool(top-1, luaV_strcomp(tsvalue(top-1), tsvalue(top)) <= 0);
+        else
           call_binTM(L, top+1, IM_LE, "unexpected type in comparison");
           call_binTM(L, top+1, IM_LE, "unexpected type in comparison");
-          break;
-        }
-        goto booleanresult;
+        break;
 
 
       case GTOP:
       case GTOP:
         top--;
         top--;
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
-          aux = nvalue(top-1) > nvalue(top);
+          setbool(top-1, nvalue(top-1) > nvalue(top));
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
-          aux = luaV_strcomp(tsvalue(top-1), tsvalue(top)) > 0;
-        else {
+          setbool(top-1, luaV_strcomp(tsvalue(top-1), tsvalue(top)) > 0);
+        else
           call_binTM(L, top+1, IM_GT, "unexpected type in comparison");
           call_binTM(L, top+1, IM_GT, "unexpected type in comparison");
-          break;
-        }
-        goto booleanresult;
+        break;
 
 
       case GEOP:
       case GEOP:
         top--;
         top--;
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
         if (ttype(top-1) == LUA_T_NUMBER && ttype(top) == LUA_T_NUMBER)
-          aux = nvalue(top-1) >= nvalue(top);
+          setbool(top-1, nvalue(top-1) >= nvalue(top));
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
         else if (ttype(top-1) == LUA_T_STRING && ttype(top) == LUA_T_STRING)
-          aux = luaV_strcomp(tsvalue(top-1), tsvalue(top)) >= 0;
-        else {
+          setbool(top-1, luaV_strcomp(tsvalue(top-1), tsvalue(top)) >= 0);
+        else
           call_binTM(L, top+1, IM_GE, "unexpected type in comparison");
           call_binTM(L, top+1, IM_GE, "unexpected type in comparison");
-          break;
-        }
-        goto booleanresult;
+        break;
 
 
       case ADDOP:
       case ADDOP:
         if (tonumber(top-1) || tonumber(top-2))
         if (tonumber(top-1) || tonumber(top-2))
@@ -597,71 +578,53 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf,
         nvalue(top-1) = 1;
         nvalue(top-1) = 1;
         break;
         break;
 
 
-      case ONTJMPW: aux += highbyte(L, *pc++);
-      case ONTJMP:  aux += *pc++;
-        if (ttype(top-1) != LUA_T_NIL) pc += aux;
+      case ONTJMP:
+        if (ttype(top-1) != LUA_T_NIL) pc += GETARG_S(i);
         else top--;
         else top--;
         break;
         break;
 
 
-      case ONFJMPW: aux += highbyte(L, *pc++);
-      case ONFJMP:  aux += *pc++;
-        if (ttype(top-1) == LUA_T_NIL) pc += aux;
+      case ONFJMP:
+        if (ttype(top-1) == LUA_T_NIL) pc += GETARG_S(i);
         else top--;
         else top--;
         break;
         break;
 
 
-      case JMPW: aux += highbyte(L, *pc++);
-      case JMP:  aux += *pc++;
-        pc += aux;
+      case JMP:
+        pc += GETARG_S(i);
         break;
         break;
 
 
-      case IFFJMPW: aux += highbyte(L, *pc++);
-      case IFFJMP:  aux += *pc++;
-        if (ttype(--top) == LUA_T_NIL) pc += aux;
+      case IFTJMP:
+        if (ttype(--top) != LUA_T_NIL) pc += GETARG_S(i);
         break;
         break;
 
 
-      case IFTUPJMPW: aux += highbyte(L, *pc++);
-      case IFTUPJMP:  aux += *pc++;
-        if (ttype(--top) != LUA_T_NIL) pc -= aux;
+      case IFFJMP:
+        if (ttype(--top) == LUA_T_NIL) pc += GETARG_S(i);
         break;
         break;
 
 
-      case IFFUPJMPW: aux += highbyte(L, *pc++);
-      case IFFUPJMP:  aux += *pc++;
-        if (ttype(--top) == LUA_T_NIL) pc -= aux;
-        break;
-
-      case CLOSUREW: aux += highbyte(L, *pc++);
-      case CLOSURE:  aux += *pc++;
+      case CLOSURE:
         ttype(top) = LUA_T_LPROTO;
         ttype(top) = LUA_T_LPROTO;
-        tfvalue(top) = tf->kproto[aux];
+        tfvalue(top) = tf->kproto[GETARG_A(i)];
         L->top = ++top;
         L->top = ++top;
-        aux = *pc++;  /* number of upvalues */
-        luaV_closure(L, aux);
+        luaV_closure(L, GETARG_B(i));
+        top -= GETARG_B(i);
         luaC_checkGC(L);
         luaC_checkGC(L);
-        top -= aux;
         break;
         break;
 
 
-      case SETLINEW: aux += highbyte(L, *pc++);
-      case SETLINE:  aux += *pc++;
+      case SETLINE:
         if ((base-1)->ttype != LUA_T_LINE) {
         if ((base-1)->ttype != LUA_T_LINE) {
           /* open space for LINE value */
           /* open space for LINE value */
-          int i = top-base;
-          while (i--) base[i+1] = base[i];
+          int n = top-base;
+          while (n--) base[n+1] = base[n];
           base++;
           base++;
           top++;
           top++;
           (base-1)->ttype = LUA_T_LINE;
           (base-1)->ttype = LUA_T_LINE;
         }
         }
-        (base-1)->value.i = aux;
+        (base-1)->value.i = GETARG_U(i);
         if (L->linehook) {
         if (L->linehook) {
           L->top = top;
           L->top = top;
-          luaD_lineHook(L, base-2, aux);
+          luaD_lineHook(L, base-2, GETARG_U(i));
         }
         }
         break;
         break;
 
 
-      case LONGARGW: aux += highbyte(L, *pc++);
-      case LONGARG:  aux += *pc++;
-        aux = highbyte(L, highbyte(L, aux));
-        goto switchentry;  /* do not reset `aux' */
-
     }
     }
   }
   }
 }
 }