lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Mon, Sep 07, 2009 at 09:18:41PM -0400, Jim Pryor wrote:
> Wow, terrific, thanks for the amazingly quick fix for Coco.
> 
> I'm also trying to build and try out the RVM patch. It doesn't patch
> cleanly against the Lua 5.1.4 sources, so I'm going and cleaning it up
> by hand. Mostly this is straightforward. There are a few spots where I'm
> stuck though: the Lua 5.1.4 sources have changed
> from what the RVM patch is trying to replace. I'm not familiar with
> these sources yet, so don't know what's the right merge.
> 
> The wiki says that Greg Falcon aka VeLoSo has taken over maintenance of
> the RVM patch. Is there any version floating around against the current
> Lua sources? Is noone using this patch anymore? From what I've seen on
> the mailing list it looks that, though there's no development happening
> on it, it's still regarded as a solid and viable option?

OK, I've done the grunt work of updating the Resumable VM patch against the
Lua5.1.4 sources. What I've ended up with compiles and runs the test/
directory in the Lua5.1.4 sources without crashing. But it needs some
code review! I'm new to Lua and in some places I had to make an educated
guess about how to merge the rvm patch against the Lua5.1->Lua5.1.4
changes. Someone who really understands the source should look this
over.

I've made it easy for you. Attached are three patches _against the
Lua5.1 rvm patch on the wiki_. That's right, they're patches against the
patch file at
http://lua-users.org/files/wiki_insecure/users/VeLoSo/lua5.1-rvm.patch.

The first patch just changes some line numbers. I'm sure this is
harmless.

The second patch, (*-safe.patch) are changes that I'm pretty sure are fine. Someone should look at this too, but it's probably ok.

The third patch are the changes that I feel less certain about. There's
one largish patch that I'm least certain of, and the others are probably
ok, but I put them here to be sure someone looks at them.

Pretty please?

-- 
Jim Pryor
jim@jimpryor.net
--- lua5.1-rvm.patch	2009-09-08 08:46:51.974477085 -0400
+++ lua5.1.4-rvm-renumbered	2009-09-08 08:43:38.454503248 -0400
@@ -1,7 +1,7 @@
-diff -ruN oldsrc/lapi.c newsrc/lapi.c
---- oldsrc/lapi.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lapi.c	2006-04-15 23:44:03.000000000 -0500
-@@ -283,7 +283,9 @@
+diff -ruN lua-5.1.4/src/lapi.c lua-5.1.4.new/src/lapi.c
+--- lua-5.1.4/src/lapi.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lapi.c	2009-09-08 05:40:44.045591292 -0400
+@@ -290,7 +290,9 @@
    lua_lock(L);  /* may call tag method */
    o1 = index2adr(L, index1);
    o2 = index2adr(L, index2);
@@ -12,7 +12,7 @@
    lua_unlock(L);
    return i;
  }
-@@ -295,8 +297,10 @@
+@@ -302,8 +304,10 @@
    lua_lock(L);  /* may call tag method */
    o1 = index2adr(L, index1);
    o2 = index2adr(L, index2);
@@ -25,7 +25,7 @@
    lua_unlock(L);
    return i;
  }
-@@ -529,7 +533,9 @@
+@@ -536,7 +540,9 @@
    lua_lock(L);
    t = index2adr(L, idx);
    api_checkvalidindex(L, t);
@@ -36,7 +36,7 @@
    lua_unlock(L);
  }
  
-@@ -541,7 +547,9 @@
+@@ -548,7 +554,9 @@
    t = index2adr(L, idx);
    api_checkvalidindex(L, t);
    setsvalue(L, &key, luaS_new(L, k));
@@ -47,7 +47,7 @@
    api_incr_top(L);
    lua_unlock(L);
  }
-@@ -641,7 +649,9 @@
+@@ -648,7 +656,9 @@
    api_checknelems(L, 2);
    t = index2adr(L, idx);
    api_checkvalidindex(L, t);
@@ -58,7 +58,7 @@
    L->top -= 2;  /* pop index and value */
    lua_unlock(L);
  }
-@@ -655,7 +665,9 @@
+@@ -662,7 +672,9 @@
    t = index2adr(L, idx);
    api_checkvalidindex(L, t);
    setsvalue(L, &key, luaS_new(L, k));
@@ -69,7 +69,7 @@
    L->top--;  /* pop value */
    lua_unlock(L);
  }
-@@ -758,22 +770,29 @@
+@@ -765,22 +777,29 @@
  */
  
  
@@ -109,7 +109,7 @@
    lua_unlock(L);
  }
  
-@@ -788,31 +807,36 @@
+@@ -795,31 +814,36 @@
  };
  
  
@@ -163,7 +163,7 @@
    lua_unlock(L);
    return status;
  }
-@@ -827,7 +851,7 @@
+@@ -834,7 +858,7 @@
  };
  
  
@@ -172,7 +172,7 @@
    struct CCallS *c = cast(struct CCallS *, ud);
    Closure *cl;
    cl = luaF_newCclosure(L, 0, getcurrenv(L));
-@@ -836,7 +860,8 @@
+@@ -843,7 +867,8 @@
    api_incr_top(L);
    setpvalue(L->top, c->ud);  /* push only argument */
    api_incr_top(L);
@@ -182,7 +182,7 @@
  }
  
  
-@@ -846,7 +871,7 @@
+@@ -853,7 +878,7 @@
    lua_lock(L);
    c.func = func;
    c.ud = ud;
@@ -191,7 +191,7 @@
    lua_unlock(L);
    return status;
  }
-@@ -954,7 +979,7 @@
+@@ -964,7 +989,7 @@
  LUA_API int lua_error (lua_State *L) {
    lua_lock(L);
    api_checknelems(L, 1);
@@ -200,7 +200,7 @@
    lua_unlock(L);
    return 0;  /* to avoid warnings */
  }
-@@ -982,7 +1007,9 @@
+@@ -992,7 +1017,9 @@
    api_checknelems(L, n);
    if (n >= 2) {
      luaC_checkGC(L);
@@ -211,9 +211,9 @@
      L->top -= (n-1);
    }
    else if (n == 0) {  /* push empty string */
-diff -ruN oldsrc/lbaselib.c newsrc/lbaselib.c
---- oldsrc/lbaselib.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lbaselib.c	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/lbaselib.c lua-5.1.4.new/src/lbaselib.c
+--- lua-5.1.4/src/lbaselib.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lbaselib.c	2009-09-08 05:40:44.045591292 -0400
 @@ -30,13 +30,18 @@
  */
  static int luaB_print (lua_State *L) {
@@ -253,7 +253,7 @@
  }
  
  
-@@ -369,32 +375,53 @@
+@@ -371,32 +377,53 @@
  }
  
  
@@ -324,7 +324,7 @@
    switch (lua_type(L, 1)) {
      case LUA_TNUMBER:
        lua_pushstring(L, lua_tostring(L, 1));
-@@ -466,6 +493,7 @@
+@@ -468,6 +495,7 @@
    {"tostring", luaB_tostring},
    {"type", luaB_type},
    {"unpack", luaB_unpack},
@@ -332,7 +332,7 @@
    {"xpcall", luaB_xpcall},
    {NULL, NULL}
  };
-@@ -482,6 +510,7 @@
+@@ -520,6 +548,7 @@
    if (!lua_checkstack(co, narg))
      luaL_error(L, "too many arguments to resume");
    if (lua_status(co) == 0 && lua_gettop(co) == 0) {
@@ -340,7 +340,7 @@
      lua_pushliteral(L, "cannot resume dead coroutine");
      return -1;  /* error flag */
    }
-@@ -489,13 +518,16 @@
+@@ -528,13 +557,16 @@
    status = lua_resume(co, narg);
    if (status == 0 || status == LUA_YIELD) {
      int nres = lua_gettop(co);
@@ -358,7 +358,7 @@
      return -1;  /* error flag */
    }
  }
-@@ -506,16 +538,10 @@
+@@ -545,16 +577,10 @@
    int r;
    luaL_argcheck(L, co, 1, "coroutine expected");
    r = auxresume(L, co, lua_gettop(L) - 1);
@@ -377,7 +377,7 @@
  }
  
  
-@@ -536,8 +562,7 @@
+@@ -575,8 +601,7 @@
  
  static int luaB_cocreate (lua_State *L) {
    lua_State *NL = lua_newthread(L);
@@ -387,9 +387,9 @@
    lua_pushvalue(L, 1);  /* move function to top */
    lua_xmove(L, NL, 1);  /* move function from L to NL */
    return 1;
-diff -ruN oldsrc/ldebug.c newsrc/ldebug.c
---- oldsrc/ldebug.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/ldebug.c	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/ldebug.c lua-5.1.4.new/src/ldebug.c
+--- lua-5.1.4/src/ldebug.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/ldebug.c	2009-09-08 05:40:44.045591292 -0400
 @@ -36,8 +36,8 @@
  static int currentpc (lua_State *L, CallInfo *ci) {
    if (!isLua(ci)) return -1;  /* function is not a Lua function? */
@@ -401,7 +401,7 @@
  }
  
  
-@@ -597,24 +597,11 @@
+@@ -615,24 +615,11 @@
  }
  
  
@@ -427,9 +427,9 @@
 +  luaD_throw(L, LUA_ERRRUN);
  }
  
-diff -ruN oldsrc/ldebug.h newsrc/ldebug.h
---- oldsrc/ldebug.h	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/ldebug.h	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/ldebug.h lua-5.1.4.new/src/ldebug.h
+--- lua-5.1.4/src/ldebug.h	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/ldebug.h	2009-09-08 05:40:44.045591292 -0400
 @@ -26,7 +26,6 @@
  LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,
                                               const TValue *p2);
@@ -438,9 +438,9 @@
  LUAI_FUNC int luaG_checkcode (const Proto *pt);
  LUAI_FUNC int luaG_checkopenop (Instruction i);
  
-diff -ruN oldsrc/ldo.c newsrc/ldo.c
---- oldsrc/ldo.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/ldo.c	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/ldo.c lua-5.1.4.new/src/ldo.c
+--- lua-5.1.4/src/ldo.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/ldo.c	2009-09-08 05:40:44.045591292 -0400
 @@ -58,6 +58,10 @@
        setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling"));
        break;
@@ -493,7 +493,7 @@
    }
    else {
      L->status = cast_byte(errcode);
-@@ -114,12 +134,84 @@
+@@ -114,12 +136,84 @@
    lj.previous = L->errorJmp;  /* chain new error handler */
    L->errorJmp = &lj;
    LUAI_TRY(L, &lj,
@@ -579,7 +579,7 @@
  /* }====================================================== */
  
  
-@@ -180,10 +272,11 @@
+@@ -180,10 +274,11 @@
  
  void luaD_callhook (lua_State *L, int event, int line) {
    lua_Hook hook = L->hook;
@@ -592,7 +592,7 @@
      ar.event = event;
      ar.currentline = line;
      if (event == LUA_HOOKTAILRET)
-@@ -193,14 +286,22 @@
+@@ -193,14 +288,22 @@
      luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
      L->ci->top = L->top + LUA_MINSTACK;
      lua_assert(L->ci->top <= L->stack_last);
@@ -618,7 +618,7 @@
    }
  }
  
-@@ -262,17 +363,17 @@
+@@ -262,17 +365,17 @@
  
  
  int luaD_precall (lua_State *L, StkId func, int nresults) {
@@ -641,7 +641,7 @@
      luaD_checkstack(L, p->maxstacksize);
      func = restorestack(L, funcr);
      if (!p->is_vararg) {  /* no varargs? */
-@@ -290,16 +391,18 @@
+@@ -290,16 +393,18 @@
      L->base = ci->base = base;
      ci->top = L->base + p->maxstacksize;
      lua_assert(ci->top <= L->stack_last);
@@ -664,7 +664,7 @@
      }
      return PCRLUA;
    }
-@@ -312,11 +415,13 @@
+@@ -312,11 +417,13 @@
      L->base = ci->base = ci->func + 1;
      ci->top = L->top + LUA_MINSTACK;
      lua_assert(ci->top <= L->stack_last);
@@ -680,7 +680,7 @@
      lua_lock(L);
      if (n < 0)  /* yielding? */
        return PCRYIELD;
-@@ -349,7 +454,7 @@
+@@ -349,7 +456,7 @@
    res = ci->func;  /* res == final position of 1st result */
    wanted = ci->nresults;
    L->base = (ci - 1)->base;  /* restore base */
@@ -689,7 +689,7 @@
    /* move results to correct place */
    for (i = wanted; i != 0 && firstResult < L->top; i--)
      setobjs2s(L, res++, firstResult++);
-@@ -366,41 +471,51 @@
+@@ -366,41 +473,51 @@
  ** When returns, all the results are on the stack, starting at the original
  ** function position.
  */ 
@@ -767,7 +767,7 @@
  }
  
  
-@@ -414,67 +529,61 @@
+@@ -415,67 +532,61 @@
  
  
  LUA_API int lua_resume (lua_State *L, int nargs) {
@@ -875,7 +875,7 @@
  /*
  ** Execute a protected parser.
  */
-@@ -484,12 +593,13 @@
+@@ -487,12 +624,13 @@
    const char *name;
  };
  
@@ -890,7 +890,7 @@
    luaC_checkGC(L);
    tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
                                                               &p->buff, p->name);
-@@ -499,6 +609,7 @@
+@@ -502,6 +640,7 @@
      cl->l.upvals[i] = luaF_newupval(L);
    setclvalue(L, L->top, cl);
    incr_top(L);
@@ -898,7 +898,7 @@
  }
  
  
-@@ -507,7 +618,8 @@
+@@ -510,7 +649,8 @@
    int status;
    p.z = z; p.name = name;
    luaZ_initbuffer(L, &p.buff);
@@ -908,9 +908,9 @@
    luaZ_freebuffer(L, &p.buff);
    return status;
  }
-diff -ruN oldsrc/ldo.h newsrc/ldo.h
---- oldsrc/ldo.h	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/ldo.h	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/ldo.h lua-5.1.4.new/src/ldo.h
+--- lua-5.1.4/src/ldo.h	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/ldo.h	2009-09-08 05:40:44.048922581 -0400
 @@ -31,18 +31,30 @@
  /* results from luaD_precall */
  #define PCRLUA		0	/* initiated a call to a Lua function */
@@ -962,10 +962,10 @@
  
  LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);
  
-diff -ruN oldsrc/lgc.c newsrc/lgc.c
---- oldsrc/lgc.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lgc.c	2006-04-15 23:44:03.000000000 -0500
-@@ -455,15 +455,12 @@
+diff -ruN lua-5.1.4/src/lgc.c lua-5.1.4.new/src/lgc.c
+--- lua-5.1.4/src/lgc.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lgc.c	2009-09-08 05:40:44.048922581 -0400
+@@ -457,15 +457,12 @@
    makewhite(g, o);
    tm = fasttm(L, udata->uv.metatable, TM_GC);
    if (tm != NULL) {
@@ -982,9 +982,9 @@
      g->GCthreshold = oldt;  /* restore threshold */
    }
  }
-diff -ruN oldsrc/lstate.c newsrc/lstate.c
---- oldsrc/lstate.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lstate.c	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/lstate.c lua-5.1.4.new/src/lstate.c
+--- lua-5.1.4/src/lstate.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lstate.c	2009-09-08 05:40:44.048922581 -0400
 @@ -55,6 +55,7 @@
    setnilvalue(L1->top++);  /* `function' entry for this `ci' */
    L1->base = L1->ci->base = L1->top;
@@ -1028,7 +1028,7 @@
    setnilvalue(gt(L));
  }
  
-@@ -190,9 +190,10 @@
+@@ -190,9 +193,10 @@
  }
  
  
@@ -1040,7 +1040,7 @@
  }
  
  
-@@ -202,9 +203,9 @@
+@@ -201,9 +205,9 @@
    lua_lock(L);
    luaF_close(L, L->stack);  /* close all upvalues for this thread */
    luaC_separateudata(L, 1);  /* separate udata that have GC metamethods */
@@ -1051,9 +1051,9 @@
      L->base = L->top = L->ci->base;
      L->nCcalls = 0;
    } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
-diff -ruN oldsrc/lstate.h newsrc/lstate.h
---- oldsrc/lstate.h	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lstate.h	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/lstate.h lua-5.1.4.new/src/lstate.h
+--- lua-5.1.4/src/lstate.h	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lstate.h	2009-09-08 05:40:44.048922581 -0400
 @@ -48,10 +48,12 @@
  typedef struct CallInfo {
    StkId base;  /* base for this function */
@@ -1096,7 +1096,7 @@
    int hookcount;
    lua_Hook hook;
    TValue l_gt;  /* table of globals */
-@@ -122,7 +122,7 @@
+@@ -123,7 +123,7 @@
    GCObject *openupval;  /* list of open upvalues in this stack */
    GCObject *gclist;
    struct lua_longjmp *errorJmp;  /* current error recover point */
@@ -1105,9 +1105,9 @@
  };
  
  
-diff -ruN oldsrc/ltablib.c newsrc/ltablib.c
---- oldsrc/ltablib.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/ltablib.c	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/ltablib.c lua-5.1.4.new/src/ltablib.c
+--- lua-5.1.4/src/ltablib.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/ltablib.c	2009-09-08 05:40:44.048922581 -0400
 @@ -20,14 +20,22 @@
  
  
@@ -1152,10 +1152,10 @@
      if (!lua_isnil(L, -1))
        return 1;
      lua_pop(L, 2);  /* remove value and result */
-diff -ruN oldsrc/luaconf.h newsrc/luaconf.h
---- oldsrc/luaconf.h	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/luaconf.h	2006-04-15 23:44:03.000000000 -0500
-@@ -580,7 +580,7 @@
+diff -ruN lua-5.1.4/src/luaconf.h lua-5.1.4.new/src/luaconf.h
+--- lua-5.1.4/src/luaconf.h	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/luaconf.h	2009-09-08 05:40:44.048922581 -0400
+@@ -607,7 +607,7 @@
  /* C++ exceptions */
  #define LUAI_THROW(L,c)	throw(c)
  #define LUAI_TRY(L,c,a)	try { a } catch(...) \
@@ -1164,9 +1164,9 @@
  #define luai_jmpbuf	int  /* dummy variable */
  
  #elif defined(LUA_USE_ULONGJMP)
-diff -ruN oldsrc/lua.h newsrc/lua.h
---- oldsrc/lua.h	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lua.h	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/lua.h lua-5.1.4.new/src/lua.h
+--- lua-5.1.4/src/lua.h	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lua.h	2009-09-08 05:40:44.048922581 -0400
 @@ -16,7 +16,7 @@
  #include "luaconf.h"
  
@@ -1176,7 +1176,7 @@
  #define LUA_VERSION_NUM	501
  #define LUA_COPYRIGHT	"Copyright (C) 1994-2006 Lua.org, PUC-Rio"
  #define LUA_AUTHORS 	"R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
-@@ -44,6 +44,7 @@
+@@ -45,6 +45,7 @@
  #define LUA_ERRSYNTAX	3
  #define LUA_ERRMEM	4
  #define LUA_ERRERR	5
@@ -1184,7 +1184,7 @@
  
  
  typedef struct lua_State lua_State;
-@@ -197,22 +198,37 @@
+@@ -198,22 +199,37 @@
  /*
  ** `load' and `call' functions (load and run Lua code)
  */
@@ -1225,9 +1225,9 @@
  /*
  ** garbage-collection function and options
  */
-diff -ruN oldsrc/lvm.c newsrc/lvm.c
---- oldsrc/lvm.c	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lvm.c	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/lvm.c lua-5.1.4.new/src/lvm.c
+--- lua-5.1.4/src/lvm.c	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lvm.c	2009-09-08 05:40:44.052255477 -0400
 @@ -57,10 +57,10 @@
  }
  
@@ -1242,7 +1242,7 @@
    if (mask > LUA_MASKLINE) {  /* instruction-hook set? */
      if (L->hookcount == 0) {
        resethookcount(L);
-@@ -76,6 +76,7 @@
+@@ -74,6 +74,7 @@
      if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
        luaD_callhook(L, LUA_HOOKLINE, newline);
    }
@@ -1250,7 +1250,7 @@
  }
  
  
-@@ -87,7 +88,7 @@
+@@ -85,7 +86,7 @@
    setobj2s(L, L->top+2, p2);  /* 2nd argument */
    luaD_checkstack(L, 3);
    L->top += 3;
@@ -1259,7 +1259,7 @@
    res = restorestack(L, result);
    L->top--;
    setobjs2s(L, res, L->top);
-@@ -103,7 +104,7 @@
+@@ -101,7 +102,7 @@
    setobj2s(L, L->top+3, p3);  /* 3th argument */
    luaD_checkstack(L, 4);
    L->top += 4;
@@ -1268,7 +1268,7 @@
  }
  
  
-@@ -282,8 +283,11 @@
+@@ -280,8 +281,11 @@
      StkId top = L->base + last + 1;
      int n = 2;  /* number of elements handled in this pass (at least 2) */
      if (!tostring(L, top-2) || !tostring(L, top-1)) {
@@ -1306,7 +1306,7 @@
    cl = &clvalue(L->ci->func)->l;
    base = L->base;
    k = cl->p->k;
-@@ -385,14 +390,8 @@
+@@ -386,14 +391,8 @@
      const Instruction i = *pc++;
      StkId ra;
      if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
@@ -1323,7 +1323,7 @@
      /* warning!! several calls may realloc the stack and invalidate `ra' */
      ra = RA(i);
      lua_assert(base == L->base && L->base == L->ci->base);
-@@ -582,7 +581,7 @@
+@@ -583,7 +582,7 @@
          int b = GETARG_B(i);
          int nresults = GETARG_C(i) - 1;
          if (b != 0) L->top = ra+b;  /* else previous instruction set top */
@@ -1332,7 +1332,7 @@
          switch (luaD_precall(L, ra, nresults)) {
            case PCRLUA: {
              nexeccalls++;
-@@ -595,14 +594,14 @@
+@@ -596,14 +595,14 @@
              continue;
            }
            default: {
@@ -1349,7 +1349,7 @@
          lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);
          switch (luaD_precall(L, ra, LUA_MULTRET)) {
            case PCRLUA: {
-@@ -617,7 +616,7 @@
+@@ -618,7 +617,7 @@
                setobjs2s(L, func+aux, pfunc+aux);
              ci->top = L->top = func+aux;  /* correct top */
              lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);
@@ -1358,7 +1358,7 @@
              ci->tailcalls++;  /* one more call lost */
              L->ci--;  /* remove new frame */
              goto reentry;
-@@ -627,7 +626,7 @@
+@@ -628,7 +627,7 @@
              continue;
            }
            default: {
@@ -1367,7 +1367,7 @@
            }
          }
        }
-@@ -635,14 +634,13 @@
+@@ -636,14 +635,13 @@
          int b = GETARG_B(i);
          if (b != 0) L->top = ra+b-1;
          if (L->openupval) luaF_close(L, base);
@@ -1385,7 +1385,7 @@
            goto reentry;
          }
        }
-@@ -662,7 +660,7 @@
+@@ -663,7 +661,7 @@
          const TValue *init = ra;
          const TValue *plimit = ra+1;
          const TValue *pstep = ra+2;
@@ -1394,7 +1394,7 @@
          if (!tonumber(init, ra))
            luaG_runerror(L, LUA_QL("for") " initial value must be a number");
          else if (!tonumber(plimit, ra+1))
-@@ -679,7 +677,7 @@
+@@ -680,7 +678,7 @@
          setobjs2s(L, cb+1, ra+1);
          setobjs2s(L, cb, ra);
          L->top = cb+3;  /* func. + 2 args (state and index) */
@@ -1403,7 +1403,7 @@
          L->top = L->ci->top;
          cb = RA(i) + 3;  /* previous call may change the stack */
          if (!ttisnil(cb)) {  /* continue loop? */
-@@ -760,3 +758,56 @@
+@@ -761,3 +759,56 @@
    }
  }
  
@@ -1460,9 +1460,9 @@
 +             GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL);
 +}
 +
-diff -ruN oldsrc/lvm.h newsrc/lvm.h
---- oldsrc/lvm.h	2006-04-15 23:40:17.000000000 -0500
-+++ newsrc/lvm.h	2006-04-15 23:44:03.000000000 -0500
+diff -ruN lua-5.1.4/src/lvm.h lua-5.1.4.new/src/lvm.h
+--- lua-5.1.4/src/lvm.h	2009-09-08 05:41:29.245553574 -0400
++++ lua-5.1.4.new/src/lvm.h	2009-09-08 05:40:44.052255477 -0400
 @@ -21,6 +21,9 @@
  #define equalobj(L,o1,o2) \
  	(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))
--- lua5.1-rvm.patch	2009-09-08 08:43:38.454503248 -0400
+++ lua5.1.4-rvm-safe	2009-09-08 08:43:38.464950526 -0400
@@ -335,17 +335,14 @@
 @@ -520,6 +548,7 @@
    if (!lua_checkstack(co, narg))
      luaL_error(L, "too many arguments to resume");
-   if (lua_status(co) == 0 && lua_gettop(co) == 0) {
+   if (status != CO_SUS) {
 +    lua_pushboolean(L, 0);
-     lua_pushliteral(L, "cannot resume dead coroutine");
+     lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]);
      return -1;  /* error flag */
    }
-@@ -528,13 +557,16 @@
-   status = lua_resume(co, narg);
-   if (status == 0 || status == LUA_YIELD) {
+@@ -530,11 +559,14 @@
      int nres = lua_gettop(co);
--    if (!lua_checkstack(L, nres))
-+    if (!lua_checkstack(L, nres+1))
+     if (!lua_checkstack(L, nres + 1))
        luaL_error(L, "too many results to resume");
 +    lua_pushboolean(L, 1);
      lua_xmove(co, L, nres);  /* move yielded values */
@@ -689,7 +686,7 @@
    /* move results to correct place */
    for (i = wanted; i != 0 && firstResult < L->top; i--)
      setobjs2s(L, res++, firstResult++);
-@@ -366,41 +473,51 @@
+@@ -366,42 +473,51 @@
  ** When returns, all the results are on the stack, starting at the original
  ** function position.
  */ 
@@ -727,6 +724,7 @@
 -      return;
 -  }
 -  else {  /* resuming from previous yield */
+-    lua_assert(L->status == LUA_YIELD);
 -    if (!f_isLua(ci)) {  /* `common' yield? */
 -      /* finish interrupted execution of `OP_CALL' */
 -      lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
@@ -767,7 +765,7 @@
  }
  
  
-@@ -415,67 +532,61 @@
+@@ -415,69 +532,61 @@
  
  
  LUA_API int lua_resume (lua_State *L, int nargs) {
@@ -816,8 +814,10 @@
 -    luaD_seterrorobj(L, status, L->top);
 -    L->ci->top = L->top;
 -  }
--  else
+-  else {
+-    lua_assert(L->nCcalls == L->baseCcalls);
 -    status = L->status;
+-  }
 +  L->nCcalls = LUA_NOYIELD | LUA_NOVPCALL;
 +  L->status = status;
    lua_unlock(L);
@@ -1010,7 +1010,7 @@
  }
  
  
-@@ -89,15 +91,13 @@
+@@ -89,15 +91,14 @@
    L->hook = NULL;
    L->hookmask = 0;
    L->basehookcount = 0;
@@ -1018,7 +1018,8 @@
    resethookcount(L);
    L->openupval = NULL;
    L->size_ci = 0;
--  L->nCcalls = 0;
+-  L->nCcalls = L->baseCcalls = 0;
++  L->baseCcalls = 0;
 +  L->nCcalls = LUA_NOYIELD | LUA_NOVPCALL;
    L->status = 0;
    L->base_ci = L->ci = NULL;
@@ -1049,7 +1050,7 @@
      L->ci = L->base_ci;
 +    L->ci->errfunc = 0;  /* no error function during GC metamethods */
      L->base = L->top = L->ci->base;
-     L->nCcalls = 0;
+     L->nCcalls = L->baseCcalls = 0;
    } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);
 diff -ruN lua-5.1.4/src/lstate.h lua-5.1.4.new/src/lstate.h
 --- lua-5.1.4/src/lstate.h	2009-09-08 05:41:29.245553574 -0400
@@ -1070,7 +1071,7 @@
  } CallInfo;
  
  
-@@ -100,21 +102,19 @@
+@@ -100,22 +102,20 @@
  struct lua_State {
    CommonHeader;
    lu_byte status;
@@ -1089,10 +1090,11 @@
 -  int stacksize;
    int size_ci;  /* size of array `base_ci' */
 -  unsigned short nCcalls;  /* number of nested C calls */
++  unsigned short nCcalls;  /* number of nested C calls + callflags */
+   unsigned short baseCcalls;  /* nested C calls when resuming coroutine */
 -  lu_byte hookmask;
 -  lu_byte allowhook;
 -  int basehookcount;
-+  unsigned short nCcalls;  /* number of nested C calls + callflags */
    int hookcount;
    lua_Hook hook;
    TValue l_gt;  /* table of globals */
@@ -1167,14 +1169,16 @@
 diff -ruN lua-5.1.4/src/lua.h lua-5.1.4.new/src/lua.h
 --- lua-5.1.4/src/lua.h	2009-09-08 05:41:29.245553574 -0400
 +++ lua-5.1.4.new/src/lua.h	2009-09-08 05:40:44.048922581 -0400
-@@ -16,7 +16,7 @@
+@@ -16,8 +16,8 @@
  #include "luaconf.h"
  
  
 -#define LUA_VERSION	"Lua 5.1"
+-#define LUA_RELEASE	"Lua 5.1.4"
 +#define LUA_VERSION	"Lua 5.1+rvm"
++#define LUA_RELEASE	"Lua 5.1.4+rvm"
  #define LUA_VERSION_NUM	501
- #define LUA_COPYRIGHT	"Copyright (C) 1994-2006 Lua.org, PUC-Rio"
+ #define LUA_COPYRIGHT	"Copyright (C) 1994-2008 Lua.org, PUC-Rio"
  #define LUA_AUTHORS 	"R. Ierusalimschy, L. H. de Figueiredo & W. Celes"
 @@ -45,6 +45,7 @@
  #define LUA_ERRSYNTAX	3
@@ -1271,7 +1275,7 @@
 @@ -280,8 +281,11 @@
      StkId top = L->base + last + 1;
      int n = 2;  /* number of elements handled in this pass (at least 2) */
-     if (!tostring(L, top-2) || !tostring(L, top-1)) {
+     if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {
 +      setpvalue(L->top, (void *)(ptrdiff_t)(last - 1));  /* for luaV_resume */
 +      L->top++;
        if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
@@ -1289,7 +1293,7 @@
  
  
  #define arith_op(op,tm) { \
-@@ -370,13 +374,14 @@
+@@ -370,14 +374,15 @@
  
  
  
@@ -1301,6 +1305,7 @@
    const Instruction *pc;
 +  int nexeccalls = 1;
   reentry:  /* entry point */
+   lua_assert(isLua(L->ci));
 -  pc = L->savedpc;
 +  pc = GETPC(L);
    cl = &clvalue(L->ci->func)->l;
--- lua5.1-rvm.patch	2009-09-08 08:43:38.464950526 -0400
+++ lua5.1.4-rvm-unsure	2009-09-08 08:45:57.617817088 -0400
@@ -453,7 +453,7 @@
    L->base = L->ci->base;
    luaF_close(L, L->base);  /* close eventual pending closures */
    luaD_seterrorobj(L, status, L->base);
--  L->nCcalls = 0;
+-  L->nCcalls = L->baseCcalls;
 -  L->allowhook = 1;
 +  L->nCcalls = LUA_NOYIELD | LUA_NOVPCALL;
    restore_stack_limit(L);
@@ -718,13 +718,14 @@
 -static void resume (lua_State *L, void *ud) {
 -  StkId firstArg = cast(StkId, ud);
 -  CallInfo *ci = L->ci;
--  if (L->status != LUA_YIELD) {  /* start coroutine */
+-  if (L->status == 0) {  /* start coroutine? */
 -    lua_assert(ci == L->base_ci && firstArg > L->base);
 -    if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)
 -      return;
 -  }
 -  else {  /* resuming from previous yield */
 -    lua_assert(L->status == LUA_YIELD);
+-    L->status = 0;
 -    if (!f_isLua(ci)) {  /* `common' yield? */
 -      /* finish interrupted execution of `OP_CALL' */
 -      lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||
@@ -750,7 +751,6 @@
 -      L->base = L->ci->base;
 +    L->base = L->ci->base;  /* restore invariant */
    }
--  L->status = 0;
 -  luaV_execute(L, cast_int(L->ci - L->base_ci));
 +  return f_continue(L, (void *)(ptrdiff_t)0);  /* resume remaining frames */
 +}
@@ -765,7 +765,7 @@
  }
  
  
-@@ -415,69 +532,61 @@
+@@ -415,69 +532,64 @@
  
  
  LUA_API int lua_resume (lua_State *L, int nargs) {
@@ -773,10 +773,7 @@
 +  void *ud;
    int status;
    lua_lock(L);
--  if (L->status != LUA_YIELD) {
--    if (L->status != 0)
--      return resume_error(L, "cannot resume dead coroutine");
--    else if (L->ci != L->base_ci)
+-  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))
 +  switch (L->status) {
 +  case LUA_YIELD:
 +    pf = f_coresume;
@@ -792,6 +789,9 @@
 +  default:
 +    return resume_error(L, "cannot resume dead coroutine");
 +  }
+   if (L->nCcalls >= LUAI_MAXCCALLS)
+     return resume_error(L, "C stack overflow");
++  L->baseCcalls = ++L->nCcalls;
 +  lua_assert(cast(StkId, ud) >= L->base);
 +  for (;;) {
 +    L->nCcalls = 0;
@@ -805,9 +805,10 @@
 +    }
 +    pf = f_continue;
 +    ud = (void *)(ptrdiff_t)0;  /* (void *)saveci(L, L->base_ci); */
-   }
++  }
 -  luai_userstateresume(L, nargs);
--  lua_assert(L->errfunc == 0 && L->nCcalls == 0);
+-  lua_assert(L->errfunc == 0);
+-  L->baseCcalls = ++L->nCcalls;
 -  status = luaD_rawrunprotected(L, resume, L->top - nargs);
 -  if (status != 0) {  /* error? */
 -    L->status = cast_byte(status);  /* mark thread as `dead' */
@@ -818,6 +819,7 @@
 -    lua_assert(L->nCcalls == L->baseCcalls);
 -    status = L->status;
 -  }
+-  --L->nCcalls;
 +  L->nCcalls = LUA_NOYIELD | LUA_NOVPCALL;
 +  L->status = status;
    lua_unlock(L);
@@ -829,7 +831,7 @@
 -  luai_userstateyield(L, nresults);
 +LUA_API int lua_vyield (lua_State *L, int nresults, void *ctx) {
    lua_lock(L);
--  if (L->nCcalls > 0)
+-  if (L->nCcalls > L->baseCcalls)
 -    luaG_runerror(L, "attempt to yield across metamethod/C-call boundary");
 -  L->base = L->top - nresults;  /* protect stack slots below */
 -  L->status = LUA_YIELD;
@@ -1243,9 +1245,9 @@
 -  L->savedpc = pc;
 +  const Instruction *oldpc = GETPC(L);
 +  SAVEPC(L, pc);
-   if (mask > LUA_MASKLINE) {  /* instruction-hook set? */
-     if (L->hookcount == 0) {
-       resethookcount(L);
+   if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {
+     resethookcount(L);
+     luaD_callhook(L, LUA_HOOKCOUNT, -1);
 @@ -74,6 +74,7 @@
      if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))
        luaD_callhook(L, LUA_HOOKLINE, newline);
@@ -1281,9 +1283,9 @@
        if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))
          luaG_concaterror(L, top-2, top-1);
 +      L->top--;
-     } else if (tsvalue(top-1)->len > 0) {  /* if len=0, do nothing */
-       /* at least two string values; get as many as possible */
-       size_t tl = tsvalue(top-1)->len;
+     } else if (tsvalue(top-1)->len == 0)  /* second op is empty? */
+       (void)tostring(L, top - 2);  /* result is first op (as string) */
+     else {
 @@ -354,7 +358,7 @@
  #define dojump(L,pc,i)	{(pc) += (i); luai_threadyield(L);}