Browse Source

simpler implementation for line information

Roberto Ierusalimschy 23 years ago
parent
commit
801aaf37b1
15 changed files with 79 additions and 175 deletions
  1. 6 21
      lcode.c
  2. 22 63
      ldebug.c
  3. 1 2
      ldebug.h
  4. 4 5
      ldo.c
  5. 2 2
      ldo.h
  6. 2 3
      lfunc.c
  7. 1 2
      lobject.h
  8. 4 4
      lopcodes.c
  9. 2 3
      lopcodes.h
  10. 8 10
      lparser.c
  11. 1 3
      lparser.h
  12. 2 6
      lstate.h
  13. 2 2
      ltests.c
  14. 1 2
      lundump.c
  15. 21 47
      lvm.c

+ 6 - 21
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.91 2002/03/08 19:10:32 roberto Exp roberto $
+** $Id: lcode.c,v 1.92 2002/03/21 20:31:43 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -737,31 +737,16 @@ void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
 }
 
 
-static void codelineinfo (FuncState *fs) {
-  Proto *f = fs->f;
-  LexState *ls = fs->ls;
-  if (ls->lastline > fs->lastline) {
-    if (ls->lastline > fs->lastline+1) {
-      luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int,
-                      MAX_INT, "line info overflow");
-      f->lineinfo[fs->nlineinfo++] = -(ls->lastline - (fs->lastline+1));
-    }
-    luaM_growvector(fs->L, f->lineinfo, fs->nlineinfo, f->sizelineinfo, int,
-                    MAX_INT, "line info overflow");
-    f->lineinfo[fs->nlineinfo++] = fs->pc;
-    fs->lastline = ls->lastline;
-  }
-}
-
-
 static int luaK_code (FuncState *fs, Instruction i) {
-  Proto *f;
-  codelineinfo(fs);
-  f = fs->f;
+  Proto *f = fs->f;
+  int oldsize = f->sizecode;
   /* put new instruction in code array */
   luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
                   MAX_INT, "code size overflow");
   f->code[fs->pc] = i;
+  if (f->sizecode != oldsize)
+    luaM_reallocvector(fs->L, f->lineinfo, oldsize, f->sizecode, int);
+  f->lineinfo[fs->pc] = fs->ls->lastline;
   return fs->pc++;
 }
 

+ 22 - 63
ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 1.103 2002/03/19 12:45:25 roberto Exp roberto $
+** $Id: ldebug.c,v 1.104 2002/03/22 16:54:31 roberto Exp roberto $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */
@@ -34,6 +34,24 @@ static int isLmark (CallInfo *ci) {
 }
 
 
+static int currentpc (lua_State *L, CallInfo *ci) {
+  if (ci->pc == NULL) return -1;  /* function is not an active Lua function */
+  if (ci == L->ci || ci->pc != (ci+1)->pc)  /* no other function using `pc'? */
+    return (*ci->pc - ci_func(ci)->l.p->code) - 1;
+  else  /* function's pc is saved */
+    return (ci->savedpc - ci_func(ci)->l.p->code) - 1;
+}
+
+
+static int currentline (lua_State *L, CallInfo *ci) {
+  int pc = currentpc(L, ci);
+  if (pc < 0)
+    return -1;  /* only active lua functions have current-line information */
+  else
+    return ci_func(ci)->l.p->lineinfo[pc];
+}
+
+
 LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) {
   lua_Hook oldhook;
   lua_lock(L);
@@ -45,10 +63,13 @@ LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) {
 
 
 LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) {
+  CallInfo *ci;
   lua_Hook oldhook;
   lua_lock(L);
   oldhook = L->linehook;
   L->linehook = func;
+  for (ci = L->base_ci; ci <= L->ci; ci++)
+    ci->lastpc = currentpc(L, ci);
   lua_unlock(L);
   return oldhook;
 }
@@ -67,57 +88,6 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {
 }
 
 
-int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) {
-  int refi;
-  if (lineinfo == NULL) return -1;  /* no line info */
-  refi = prefi ? *prefi : 0;
-  if (lineinfo[refi] < 0)
-    refline += -lineinfo[refi++];
-  lua_assert(lineinfo[refi] >= 0);
-  while (lineinfo[refi] > pc) {
-    refline--;
-    refi--;
-    if (lineinfo[refi] < 0)
-      refline -= -lineinfo[refi--];
-    lua_assert(lineinfo[refi] >= 0);
-  }
-  for (;;) {
-    int nextline = refline + 1;
-    int nextref = refi + 1;
-    if (lineinfo[nextref] < 0)
-      nextline += -lineinfo[nextref++];
-    lua_assert(lineinfo[nextref] >= 0);
-    if (lineinfo[nextref] > pc)
-      break;
-    refline = nextline;
-    refi = nextref;
-  }
-  if (prefi) *prefi = refi;
-  return refline;
-}
-
-
-static int currentpc (lua_State *L, CallInfo *ci) {
-  lua_assert(isLmark(ci));
-  if (ci->pc == NULL) return 0;  /* function is not active */
-  if (ci == L->ci || ci->pc != (ci+1)->pc)  /* no other function using `pc'? */
-    return (*ci->pc - ci_func(ci)->l.p->code) - 1;
-  else  /* function's pc is saved */
-    return (ci->savedpc - ci_func(ci)->l.p->code) - 1;
-}
-
-
-static int currentline (lua_State *L, CallInfo *ci) {
-  if (!isLmark(ci))
-    return -1;  /* only active lua functions have current-line information */
-  else {
-    int *lineinfo = ci_func(ci)->l.p->lineinfo;
-    return luaG_getline(lineinfo, currentpc(L, ci), 1, NULL);
-  }
-}
-
-
-
 static Proto *getluaproto (CallInfo *ci) {
   return (isLmark(ci) ? ci_func(ci)->l.p : NULL);
 }
@@ -272,19 +242,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {
 #define checkreg(pt,reg)	check((reg) < (pt)->maxstacksize)
 
 
-static int checklineinfo (const Proto *pt) {
-  int *lineinfo = pt->lineinfo;
-  if (lineinfo == NULL) return 1;
-  check(pt->sizelineinfo >= 2 && lineinfo[pt->sizelineinfo-1] == MAX_INT);
-  lua_assert(luaG_getline(lineinfo, pt->sizecode-1, 1, NULL) < MAX_INT);
-  if (*lineinfo < 0) lineinfo++;
-  check(*lineinfo == 0);
-  return 1;
-}
-
 
 static int precheck (const Proto *pt) {
-  check(checklineinfo(pt));
   check(pt->maxstacksize <= MAXSTACK);
   lua_assert(pt->numparams+pt->is_vararg <= pt->maxstacksize);
   check(GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);

+ 1 - 2
ldebug.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.h,v 1.16 2001/11/28 20:13:13 roberto Exp roberto $
+** $Id: ldebug.h,v 1.17 2002/03/19 12:45:25 roberto Exp roberto $
 ** Auxiliary functions from Debug Interface module
 ** See Copyright Notice in lua.h
 */
@@ -15,7 +15,6 @@
 void luaG_typeerror (lua_State *L, const TObject *o, const char *opname);
 void luaG_concaterror (lua_State *L, StkId p1, StkId p2);
 void luaG_aritherror (lua_State *L, StkId p1, const TObject *p2);
-int luaG_getline (int *lineinfo, int pc, int refline, int *refi);
 void luaG_ordererror (lua_State *L, const TObject *p1, const TObject *p2);
 int luaG_checkcode (const Proto *pt);
 

+ 4 - 5
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.164 2002/03/15 17:17:16 roberto Exp roberto $
+** $Id: ldo.c,v 1.165 2002/03/20 12:52:32 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -122,13 +122,13 @@ static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) {
 }
 
 
-void luaD_lineHook (lua_State *L, int line, lua_Hook linehook) {
+void luaD_lineHook (lua_State *L, int line) {
   if (L->allowhooks) {
     lua_Debug ar;
     ar.event = "line";
     ar.i_ci = L->ci - L->base_ci;
     ar.currentline = line;
-    dohook(L, &ar, linehook);
+    dohook(L, &ar, L->linehook);
   }
 }
 
@@ -221,7 +221,6 @@ StkId luaD_precall (lua_State *L, StkId func) {
     if (p->is_vararg)  /* varargs? */
       adjust_varargs(L, p->numparams);
     luaD_checkstack(L, p->maxstacksize);
-    ci->line = 0;
     ci->top = ci->base + p->maxstacksize;
     while (L->top < ci->top)
       setnilvalue(L->top++);
@@ -250,7 +249,7 @@ void luaD_poscall (lua_State *L, int wanted, StkId firstResult) {
     luaD_callHook(L, L->callhook, "return");
     firstResult = restorestack(L, fr);
   }
-  res = L->ci->base - 1;  /* func == final position of 1st result */
+  res = L->ci->base - 1;  /* res == final position of 1st result */
   L->ci--;
   /* move results to correct place */
   while (wanted != 0 && firstResult < L->top) {

+ 2 - 2
ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 1.40 2002/01/30 17:27:53 roberto Exp roberto $
+** $Id: ldo.h,v 1.41 2002/03/20 12:52:32 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -27,7 +27,7 @@
 #define restorestack(L,n)	((TObject *)((char *)L->stack + (n)))
 
 
-void luaD_lineHook (lua_State *L, int line, lua_Hook linehook);
+void luaD_lineHook (lua_State *L, int line);
 StkId luaD_precall (lua_State *L, StkId func);
 void luaD_call (lua_State *L, StkId func, int nResults);
 void luaD_poscall (lua_State *L, int wanted, StkId firstResult);

+ 2 - 3
lfunc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lfunc.c,v 1.53 2001/12/21 17:31:35 roberto Exp roberto $
+** $Id: lfunc.c,v 1.54 2002/03/05 12:42:47 roberto Exp roberto $
 ** Auxiliary functions to manipulate prototypes and closures
 ** See Copyright Notice in lua.h
 */
@@ -87,7 +87,6 @@ Proto *luaF_newproto (lua_State *L) {
   f->marked = 0;
   f->lineinfo = NULL;
   f->sizelocvars = 0;
-  f->sizelineinfo = 0;
   f->locvars = NULL;
   f->lineDefined = 0;
   f->source = NULL;
@@ -99,10 +98,10 @@ Proto *luaF_newproto (lua_State *L) {
 
 void luaF_freeproto (lua_State *L, Proto *f) {
   luaM_freearray(L, f->code, f->sizecode, Instruction);
+  luaM_freearray(L, f->lineinfo, f->sizecode, int);
   luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);
   luaM_freearray(L, f->k, f->sizek, TObject);
   luaM_freearray(L, f->p, f->sizep, Proto *);
-  luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);
   luaM_freelem(L, f);
 }
 

+ 1 - 2
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.126 2002/03/11 12:45:00 roberto Exp roberto $
+** $Id: lobject.h,v 1.127 2002/03/18 18:16:16 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -129,7 +129,6 @@ typedef struct Proto {
   int sizek;  /* size of `k' */
   int sizecode;
   int sizep;  /* size of `p' */
-  int sizelineinfo;  /* size of `lineinfo' */
   int sizelocvars;
   int lineDefined;
   lu_byte nupvalues;

+ 4 - 4
lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.12 2002/03/08 19:10:32 roberto Exp roberto $
+** $Id: lopcodes.c,v 1.13 2002/03/21 20:32:22 roberto Exp roberto $
 ** extracted automatically from lopcodes.h by mkprint.lua
 ** DO NOT EDIT
 ** See Copyright Notice in lua.h
@@ -59,11 +59,11 @@ const char *const luaP_opnames[] = {
 
 #define opmode(t,x,b,c,sa,k,m) (((t)<<OpModeT) | \
    ((b)<<OpModeBreg) | ((c)<<OpModeCreg) | \
-   ((sa)<<OpModesetA) | ((k)<<OpModeK) | (x)<<OpModeNoTrace | (m))
+   ((sa)<<OpModesetA) | ((k)<<OpModeK) | (m))
 
 
 const lu_byte luaP_opmodes[NUM_OPCODES] = {
-/*       T n B C sA K mode		   opcode    */
+/*       T _ B C sA K mode		   opcode    */
   opmode(0,0,1,0, 1,0,iABC)		/* OP_MOVE */
  ,opmode(0,0,0,0, 1,1,iABc)		/* OP_LOADK */
  ,opmode(0,0,0,0, 1,0,iABC)		/* OP_LOADBOOL */
@@ -96,7 +96,7 @@ const lu_byte luaP_opmodes[NUM_OPCODES] = {
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_CALL */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_TAILCALL */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_RETURN */
- ,opmode(0,1,0,0, 0,0,iAsBc)		/* OP_FORLOOP */
+ ,opmode(0,0,0,0, 0,0,iAsBc)		/* OP_FORLOOP */
  ,opmode(0,0,0,0, 0,0,iABC)		/* OP_TFORLOOP */
  ,opmode(0,0,0,0, 0,0,iABc)		/* OP_SETLIST */
  ,opmode(0,0,0,0, 0,0,iABc)		/* OP_SETLISTO */

+ 2 - 3
lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.91 2002/03/18 14:49:46 roberto Exp roberto $
+** $Id: lopcodes.h,v 1.92 2002/03/21 20:32:22 roberto Exp roberto $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -207,8 +207,7 @@ enum OpModeMask {
   OpModeCreg,           /* C is a register/constant */
   OpModesetA,           /* instruction set register A */
   OpModeK,              /* Bc is a constant */
-  OpModeT,		/* operator is a test */
-  OpModeNoTrace		/* operator should not be traced */
+  OpModeT		/* operator is a test */
 };
 
 extern const lu_byte luaP_opmodes[NUM_OPCODES];

+ 8 - 10
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.171 2002/03/18 14:49:46 roberto Exp roberto $
+** $Id: lparser.c,v 1.172 2002/03/21 20:32:22 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -376,11 +376,9 @@ static void open_func (LexState *ls, FuncState *fs) {
   fs->nk = 0;
   fs->h = luaH_new(ls->L, 0, 0);
   fs->np = 0;
-  fs->nlineinfo = 0;
   fs->nlocvars = 0;
   fs->nactloc = 0;
   fs->nactvar = 0;
-  fs->lastline = 0;
   fs->defaultglob = NO_REG;  /* default is free globals */
   fs->bl = NULL;
   f->code = NULL;
@@ -402,6 +400,7 @@ static void close_func (LexState *ls) {
   G(L)->roottable = fs->h->next;
   luaH_free(L, fs->h);
   luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);
+  luaM_reallocvector(L, f->lineinfo, f->sizecode, fs->pc, int);
   f->sizecode = fs->pc;
   luaM_reallocvector(L, f->k, f->sizek, fs->nk, TObject);
   f->sizek = fs->nk;
@@ -409,9 +408,6 @@ static void close_func (LexState *ls) {
   f->sizep = fs->np;
   luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);
   f->sizelocvars = fs->nlocvars;
-  luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int);
-  f->lineinfo[fs->nlineinfo++] = MAX_INT;  /* end flag */
-  f->sizelineinfo = fs->nlineinfo;
   lua_assert(luaG_checkcode(f));
   lua_assert(fs->bl == NULL);
   ls->fs = fs->prev;
@@ -999,10 +995,10 @@ static int exp1 (LexState *ls) {
 }
 
 
-static void fornum (LexState *ls, TString *varname) {
+static void fornum (LexState *ls, TString *varname, int line) {
   /* fornum -> NAME = exp1,exp1[,exp1] DO body */
   FuncState *fs = ls->fs;
-  int prep;
+  int prep, endfor;
   int base = fs->freereg;
   new_localvar(ls, varname, 0);
   new_localvarstr(ls, "(for limit)", 1);
@@ -1024,7 +1020,9 @@ static void fornum (LexState *ls, TString *varname) {
   check(ls, TK_DO);
   block(ls);
   luaK_patchtohere(fs, prep-1);
-  luaK_patchlist(fs, luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP), prep);
+  endfor = luaK_codeAsBc(fs, OP_FORLOOP, base, NO_JUMP);
+  luaK_patchlist(fs, endfor, prep);
+  fs->f->lineinfo[endfor] = line;  /* pretend that `OP_FOR' starts the loop */
 }
 
 
@@ -1065,7 +1063,7 @@ static void forstat (LexState *ls, int line) {
   varname = str_checkname(ls);  /* first variable name */
   next(ls);  /* skip var name */
   switch (ls->t.token) {
-    case '=': fornum(ls, varname); break;
+    case '=': fornum(ls, varname, line); break;
     case ',': case TK_IN: forlist(ls, varname); break;
     default: luaK_error(ls, "`=' or `in' expected");
   }

+ 1 - 3
lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.39 2002/02/08 22:42:41 roberto Exp roberto $
+** $Id: lparser.h,v 1.40 2002/03/14 18:01:52 roberto Exp roberto $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */
@@ -68,11 +68,9 @@ typedef struct FuncState {
   int defaultglob;  /* where to look for non-declared globals */
   int nk;  /* number of elements in `k' */
   int np;  /* number of elements in `p' */
-  int nlineinfo;  /* number of elements in `lineinfo' */
   int nlocvars;  /* number of elements in `locvars' */
   int nactloc;  /* number of active local variables */
   int nactvar;  /* number of elements in array `actvar' */
-  int lastline;  /* line where last `lineinfo' was generated */
   expdesc upvalues[MAXUPVALUES];  /* upvalues */
   vardesc actvar[MAXVARS];  /* declared-variable stack */
 } FuncState;

+ 2 - 6
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.78 2002/03/07 18:11:51 roberto Exp roberto $
+** $Id: lstate.h,v 1.79 2002/03/11 12:45:00 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -91,16 +91,12 @@ typedef struct CallInfo {
   StkId	top;  /* top for this function (when it's a Lua function) */
   const Instruction **pc;  /* points to `pc' variable in `luaV_execute' */
   StkId *pb;  /* points to `base' variable in `luaV_execute' */
-  /* extra information for line tracing */
   int lastpc;  /* last pc traced */
-  int line;  /* current line */
-  int refi;  /* current index in `lineinfo' */
+  int yield_results;
 } CallInfo;
 
 #define ci_func(ci)	(clvalue((ci)->base - 1))
 
-#define yield_results	refi	/* reuse this field */
-
 
 /*
 ** `global state', shared by all threads of this state

+ 2 - 2
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.112 2002/03/14 18:01:52 roberto Exp roberto $
+** $Id: ltests.c,v 1.113 2002/03/20 12:54:08 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -144,7 +144,7 @@ static char *buildop (Proto *p, int pc, char *buff) {
   Instruction i = p->code[pc];
   OpCode o = GET_OPCODE(i);
   const char *name = luaP_opnames[o];
-  int line = luaG_getline(p->lineinfo, pc, 1, NULL);
+  int line = p->lineinfo[pc];
   sprintf(buff, "(%4d) %4d - ", line, pc);
   switch (getOpMode(o)) {  
     case iABC:

+ 1 - 2
lundump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 1.43 2001/07/24 21:57:19 roberto Exp $
+** $Id: lundump.c,v 1.44 2001/11/28 20:13:13 roberto Exp roberto $
 ** load pre-compiled Lua chunks
 ** See Copyright Notice in lua.h
 */
@@ -133,7 +133,6 @@ static void LoadLines (lua_State* L, Proto* f, ZIO* Z, int swap)
  int n;
  n=LoadInt(L,Z,swap);
  f->lineinfo=luaM_newvector(L,n,int);
- f->sizelineinfo=n;
  LoadVector(L,f->lineinfo,n,sizeof(*f->lineinfo),Z,swap);
 }
 

+ 21 - 47
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.221 2002/03/20 12:52:32 roberto Exp roberto $
+** $Id: lvm.c,v 1.222 2002/03/22 16:54:31 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -62,33 +62,17 @@ int luaV_tostring (lua_State *L, TObject *obj) {
 }
 
 
-static void traceexec (lua_State *L, lua_Hook linehook) {
+static void traceexec (lua_State *L) {
   CallInfo *ci = L->ci;
   int *lineinfo = ci_func(ci)->l.p->lineinfo;
   int pc = cast(int, *ci->pc - ci_func(ci)->l.p->code) - 1;
-  int newline;
-  if (testOpMode(GET_OPCODE(*(*ci->pc - 1)), OpModeNoTrace))
-    return;
-  if (ci->line == -1) return;  /* no linehooks for this function */
-  else if (ci->line == 0) {  /* first linehook? */
-    if (pc == 0) {  /* function is starting now? */
-      ci->line = 1;
-      ci->refi = 0;
-      ci->lastpc = pc+1;  /* make sure it will call linehook */
-    }
-    else {  /* function started without hooks: */
-      ci->line = -1;  /* keep it that way */
-      return;
-    }
-  }
-  newline = luaG_getline(lineinfo, pc, ci->line, &ci->refi);
+  int newline = lineinfo[pc];
+  if (pc == 0)  /* tracing may be starting now? */
+    ci->lastpc = 0;  /* initialize `lastpc' */
   /* calls linehook when enters a new line or jumps back (loop) */
-  if (newline != ci->line || pc <= ci->lastpc) {
-    ci->line = newline;
-    luaD_lineHook(L, newline, linehook);
-    ci = L->ci;  /* previous call may realocate `ci' */
-  }
-  ci->lastpc = pc;
+  if (pc <= ci->lastpc || newline != lineinfo[ci->lastpc])
+    luaD_lineHook(L, newline);
+  L->ci->lastpc = pc;
 }
 
 
@@ -316,21 +300,17 @@ static void powOp (lua_State *L, StkId ra, StkId rb, StkId rc) {
 
 #define dojump(pc, i)	((pc) += (i))
 
-/*
-** Executes current Lua function. Parameters are between [base,top).
-** Returns n such that the results are between [n,top).
-*/
+
 StkId luaV_execute (lua_State *L) {
   StkId base;
   LClosure *cl;
   TObject *k;
   const Instruction *pc;
-  lua_Hook linehook;
- reinit:
-  linehook = L->linehook;
+ callentry:  /* entry point when calling new functions */
   L->ci->pc = &pc;
-  pc = L->ci->savedpc;
   L->ci->pb = &base;
+  pc = L->ci->savedpc;
+ retentry:  /* entry point when returning to old functions */
   base = L->ci->base;
   cl = &clvalue(base - 1)->l;
   k = cl->p->k;
@@ -338,13 +318,13 @@ StkId luaV_execute (lua_State *L) {
   for (;;) {
     const Instruction i = *pc++;
     StkId ra;
-    if (linehook)
-      traceexec(L, linehook);
+    if (L->linehook)
+      traceexec(L);
     ra = RA(i);
     lua_assert(L->top <= L->stack + L->stacksize && L->top >= L->ci->base);
-    lua_assert(L->top == L->ci->top || GET_OPCODE(i) == OP_CALL ||
-         GET_OPCODE(i) == OP_TAILCALL || GET_OPCODE(i) == OP_RETURN ||
-         GET_OPCODE(i) == OP_SETLISTO);
+    lua_assert(L->top == L->ci->top ||
+         GET_OPCODE(i) == OP_CALL ||   GET_OPCODE(i) == OP_TAILCALL ||
+         GET_OPCODE(i) == OP_RETURN || GET_OPCODE(i) == OP_SETLISTO);
     switch (GET_OPCODE(i)) {
       case OP_MOVE: {
         setobj(ra, RB(i));
@@ -453,7 +433,6 @@ StkId luaV_execute (lua_State *L) {
         break;
       }
       case OP_JMP: {
-        linehook = L->linehook;
         dojump(pc, GETARG_sBc(i));
         break;
       }
@@ -511,7 +490,7 @@ StkId luaV_execute (lua_State *L) {
         }
         else {  /* it is a Lua function: `call' it */
           (L->ci-1)->savedpc = pc;
-          goto reinit;
+          goto callentry;
         }
         break;
       }
@@ -521,7 +500,7 @@ StkId luaV_execute (lua_State *L) {
         if (b != 0) L->top = ra+b;  /* else previous instruction set top */
         luaD_poscall(L, LUA_MULTRET, ra);  /* move down function and args. */
         ra = luaD_precall(L, base-1);
-        if (ra == NULL) goto reinit;  /* it is a Lua function */
+        if (ra == NULL) goto callentry;  /* it is a Lua function */
         else if (ra > L->top) return NULL;  /* yield??? */
         else goto ret;
       }
@@ -540,14 +519,12 @@ StkId luaV_execute (lua_State *L) {
         else {  /* yes: continue its execution */
           int nresults;
           lua_assert(ttype(ci->base-1) == LUA_TFUNCTION);
-          base = ci->base;  /* restore previous values */
-          cl = &clvalue(base - 1)->l;
-          k = cl->p->k;
           pc = ci->savedpc;
           lua_assert(GET_OPCODE(*(pc-1)) == OP_CALL);
           nresults = GETARG_C(*(pc-1)) - 1;
           luaD_poscall(L, nresults, ra);
           if (nresults >= 0) L->top = L->ci->top;
+          goto retentry;
         }
         break;
       }
@@ -556,7 +533,6 @@ StkId luaV_execute (lua_State *L) {
         int j = GETARG_sBc(i);
         const TObject *plimit = ra+1;
         const TObject *pstep = ra+2;
-        dojump(pc, j);  /* jump back before tests (for error messages) */
         if (ttype(ra) != LUA_TNUMBER)
           luaD_error(L, "`for' initial value must be a number");
         if (!tonumber(plimit, ra+1))
@@ -567,11 +543,9 @@ StkId luaV_execute (lua_State *L) {
         index = nvalue(ra) + step;  /* increment index */
         limit = nvalue(plimit);
         if (step > 0 ? index <= limit : index >= limit) {
+          dojump(pc, j);  /* jump back */
           chgnvalue(ra, index);  /* update index */
-          linehook = L->linehook;
         }
-        else
-          dojump(pc, -j);  /* undo jump */
         break;
       }
       case OP_TFORLOOP: {