aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldo.c13
-rw-r--r--lstate.c53
-rw-r--r--lstate.h51
-rw-r--r--testes/all.lua14
4 files changed, 80 insertions, 51 deletions
diff --git a/ldo.c b/ldo.c
index e7e76a65..0ad3120b 100644
--- a/ldo.c
+++ b/ldo.c
@@ -139,9 +139,8 @@ l_noret luaD_throw (lua_State *L, int errcode) {
139 139
140 140
141int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { 141int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
142 l_uint32 oldnCcalls = L->nCcalls - L->nci; 142 l_uint32 oldnCcalls = L->nCcalls + L->nci;
143 struct lua_longjmp lj; 143 struct lua_longjmp lj;
144 lua_assert(L->nCcalls >= L->nci);
145 lj.status = LUA_OK; 144 lj.status = LUA_OK;
146 lj.previous = L->errorJmp; /* chain new error handler */ 145 lj.previous = L->errorJmp; /* chain new error handler */
147 L->errorJmp = &lj; 146 L->errorJmp = &lj;
@@ -149,7 +148,7 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
149 (*f)(L, ud); 148 (*f)(L, ud);
150 ); 149 );
151 L->errorJmp = lj.previous; /* restore old error handler */ 150 L->errorJmp = lj.previous; /* restore old error handler */
152 L->nCcalls = oldnCcalls + L->nci; 151 L->nCcalls = oldnCcalls - L->nci;
153 return lj.status; 152 return lj.status;
154} 153}
155 154
@@ -521,7 +520,7 @@ void luaD_call (lua_State *L, StkId func, int nresults) {
521*/ 520*/
522void luaD_callnoyield (lua_State *L, StkId func, int nResults) { 521void luaD_callnoyield (lua_State *L, StkId func, int nResults) {
523 incXCcalls(L); 522 incXCcalls(L);
524 if (getCcalls(L) >= LUAI_MAXCSTACK) /* possible stack overflow? */ 523 if (getCcalls(L) <= CSTACKERR) /* possible stack overflow? */
525 luaE_freeCI(L); 524 luaE_freeCI(L);
526 luaD_call(L, func, nResults); 525 luaD_call(L, func, nResults);
527 decXCcalls(L); 526 decXCcalls(L);
@@ -672,10 +671,10 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs,
672 else if (L->status != LUA_YIELD) /* ended with errors? */ 671 else if (L->status != LUA_YIELD) /* ended with errors? */
673 return resume_error(L, "cannot resume dead coroutine", nargs); 672 return resume_error(L, "cannot resume dead coroutine", nargs);
674 if (from == NULL) 673 if (from == NULL)
675 L->nCcalls = 1; 674 L->nCcalls = LUAI_MAXCSTACK;
676 else /* correct 'nCcalls' for this thread */ 675 else /* correct 'nCcalls' for this thread */
677 L->nCcalls = getCcalls(from) - from->nci + L->nci + CSTACKCF; 676 L->nCcalls = getCcalls(from) + from->nci - L->nci - CSTACKCF;
678 if (L->nCcalls >= LUAI_MAXCSTACK) 677 if (L->nCcalls <= CSTACKERR)
679 return resume_error(L, "C stack overflow", nargs); 678 return resume_error(L, "C stack overflow", nargs);
680 luai_userstateresume(L, nargs); 679 luai_userstateresume(L, nargs);
681 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); 680 api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
diff --git a/lstate.c b/lstate.c
index 387cd362..296cec2a 100644
--- a/lstate.c
+++ b/lstate.c
@@ -97,35 +97,34 @@ void luaE_setdebt (global_State *g, l_mem debt) {
97 97
98 98
99/* 99/*
100** Increment count of "C calls" and check for overflows. In case of 100** Decrement count of "C calls" and check for overflows. In case of
101** a stack overflow, check appropriate error ("regular" overflow or 101** a stack overflow, check appropriate error ("regular" overflow or
102** overflow while handling stack overflow). 102** overflow while handling stack overflow). If 'nCcalls' is smaller
103** If 'nCcalls' is larger than LUAI_MAXCSTACK but smaller than 103** than CSTACKERR but larger than CSTACKMARK, it means it has just
104** LUAI_MAXCSTACK + CSTACKCF (plus 2 to avoid by-one errors), it means 104** entered the "overflow zone", so the function raises an overflow
105** it has just entered the "overflow zone", so the function raises an 105** error. If 'nCcalls' is smaller than CSTACKMARK (which means it is
106** overflow error. 106** already handling an overflow) but larger than CSTACKERRMARK, does
107** If 'nCcalls' is larger than LUAI_MAXCSTACK + CSTACKCF + 2 107** not report an error (to allow message handling to work). Otherwise,
108** (which means it is already handling an overflow) but smaller than 108** report a stack overflow while handling a stack overflow (probably
109** 9/8 of LUAI_MAXCSTACK, does not report an error (to allow message 109** caused by a repeating error in the message handling function).
110** handling to work).
111** Otherwise, report a stack overflow while handling a stack overflow
112** (probably caused by a repeating error in the message handling
113** function).
114*/ 110*/
111
115void luaE_enterCcall (lua_State *L) { 112void luaE_enterCcall (lua_State *L) {
116 int ncalls = getCcalls(L); 113 int ncalls = getCcalls(L);
117 L->nCcalls++; 114 L->nCcalls--;
118 if (ncalls >= LUAI_MAXCSTACK) { /* possible overflow? */ 115 if (ncalls <= CSTACKERR) { /* possible overflow? */
119 luaE_freeCI(L); /* release unused CIs */ 116 luaE_freeCI(L); /* release unused CIs */
120 ncalls = getCcalls(L); /* update call count */ 117 ncalls = getCcalls(L); /* update call count */
121 if (ncalls >= LUAI_MAXCSTACK) { /* still overflow? */ 118 if (ncalls <= CSTACKERR) { /* still overflow? */
122 if (ncalls <= LUAI_MAXCSTACK + CSTACKCF + 2) { 119 if (ncalls <= CSTACKERRMARK) /* below error-handling zone? */
123 /* no error before increments; raise the error now */
124 L->nCcalls += (CSTACKCF + 4); /* avoid raising it again */
125 luaG_runerror(L, "C stack overflow");
126 }
127 else if (ncalls >= (LUAI_MAXCSTACK + (LUAI_MAXCSTACK >> 3)))
128 luaD_throw(L, LUA_ERRERR); /* error while handling stack error */ 120 luaD_throw(L, LUA_ERRERR); /* error while handling stack error */
121 else if (ncalls >= CSTACKMARK) {
122 /* not in error-handling zone; raise the error now */
123 L->nCcalls = (CSTACKMARK - 1); /* enter error-handling zone */
124 luaG_runerror(L, "C stack overflow1");
125 }
126 /* else stack is in the error-handling zone;
127 allow message handler to work */
129 } 128 }
130 } 129 }
131} 130}
@@ -153,13 +152,13 @@ void luaE_freeCI (lua_State *L) {
153 CallInfo *ci = L->ci; 152 CallInfo *ci = L->ci;
154 CallInfo *next = ci->next; 153 CallInfo *next = ci->next;
155 ci->next = NULL; 154 ci->next = NULL;
156 L->nCcalls -= L->nci; /* subtract removed elements from 'nCcalls' */ 155 L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
157 while ((ci = next) != NULL) { 156 while ((ci = next) != NULL) {
158 next = ci->next; 157 next = ci->next;
159 luaM_free(L, ci); 158 luaM_free(L, ci);
160 L->nci--; 159 L->nci--;
161 } 160 }
162 L->nCcalls += L->nci; /* adjust result */ 161 L->nCcalls -= L->nci; /* adjust result */
163} 162}
164 163
165 164
@@ -169,7 +168,7 @@ void luaE_freeCI (lua_State *L) {
169void luaE_shrinkCI (lua_State *L) { 168void luaE_shrinkCI (lua_State *L) {
170 CallInfo *ci = L->ci; 169 CallInfo *ci = L->ci;
171 CallInfo *next2; /* next's next */ 170 CallInfo *next2; /* next's next */
172 L->nCcalls -= L->nci; /* subtract removed elements from 'nCcalls' */ 171 L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */
173 /* while there are two nexts */ 172 /* while there are two nexts */
174 while (ci->next != NULL && (next2 = ci->next->next) != NULL) { 173 while (ci->next != NULL && (next2 = ci->next->next) != NULL) {
175 luaM_free(L, ci->next); /* free next */ 174 luaM_free(L, ci->next); /* free next */
@@ -178,7 +177,7 @@ void luaE_shrinkCI (lua_State *L) {
178 next2->previous = ci; 177 next2->previous = ci;
179 ci = next2; /* keep next's next */ 178 ci = next2; /* keep next's next */
180 } 179 }
181 L->nCcalls += L->nci; /* adjust result */ 180 L->nCcalls -= L->nci; /* adjust result */
182} 181}
183 182
184 183
@@ -264,7 +263,7 @@ static void preinit_thread (lua_State *L, global_State *g) {
264 L->stacksize = 0; 263 L->stacksize = 0;
265 L->twups = L; /* thread has no upvalues */ 264 L->twups = L; /* thread has no upvalues */
266 L->errorJmp = NULL; 265 L->errorJmp = NULL;
267 L->nCcalls = 0; 266 L->nCcalls = LUAI_MAXCSTACK + CSTACKERR;
268 L->hook = NULL; 267 L->hook = NULL;
269 L->hookmask = 0; 268 L->hookmask = 0;
270 L->basehookcount = 0; 269 L->basehookcount = 0;
diff --git a/lstate.h b/lstate.h
index 3bd52973..858da5be 100644
--- a/lstate.h
+++ b/lstate.h
@@ -64,28 +64,45 @@
64 64
65/* 65/*
66** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of 66** About 'nCcalls': each thread in Lua (a lua_State) keeps a count of
67** how many "C calls" it can do in the C stack, to avoid C-stack overflow. 67** how many "C calls" it still can do in the C stack, to avoid C-stack
68** This count is very rough approximation; it considers only recursive 68** overflow. This count is very rough approximation; it considers only
69** functions inside the interpreter, as non-recursive calls can be 69** recursive functions inside the interpreter, as non-recursive calls
70** considered using a fixed (although unknown) amount of stack space. 70** can be considered using a fixed (although unknown) amount of stack
71** space.
71** 72**
72** The count itself has two parts: the lower part is the count itself; 73** The count has two parts: the lower part is the count itself; the
73** the higher part counts the number of non-yieldable calls in the stack. 74** higher part counts the number of non-yieldable calls in the stack.
75** (They are together so that we can change both with one instruction.)
74** 76**
75** Because calls to external C functions can use of unkown amount 77** Because calls to external C functions can use of unkown amount
76** of space (e.g., functions using an auxiliary buffer), calls 78** of space (e.g., functions using an auxiliary buffer), calls
77** to these functions add more than one to the count. 79** to these functions add more than one to the count (see CSTACKCF).
78** 80**
79** The proper count also includes the number of CallInfo structures 81** The proper count excludes the number of CallInfo structures allocated
80** allocated by Lua, as a kind of "potential" calls. So, when Lua 82** by Lua, as a kind of "potential" calls. So, when Lua calls a function
81** calls a function (and "consumes" one CallInfo), it needs neither to 83** (and "consumes" one CallInfo), it needs neither to decrement nor to
82** increment nor to check 'nCcalls', as its use of C stack is already 84** check 'nCcalls', as its use of C stack is already accounted for.
83** accounted for.
84*/ 85*/
85 86
86/* number of "C stack slots" used by an external C function */ 87/* number of "C stack slots" used by an external C function */
87#define CSTACKCF 10 88#define CSTACKCF 10
88 89
90
91/*
92** The C-stack size is sliced in the following zones:
93** - larger than CSTACKERR: normal stack;
94** - [CSTACKMARK, CSTACKERR]: buffer zone to signal a stack overflow;
95** - [CSTACKCF, CSTACKERRMARK]: error-handling zone;
96** - below CSTACKERRMARK: buffer zone to signal overflow during overflow;
97** (Because the counter can be decremented CSTACKCF at once, we need
98** the so called "buffer zones", with at least that size, to properly
99** detect a change from one zone to the next.)
100*/
101#define CSTACKERR (8 * CSTACKCF)
102#define CSTACKMARK (CSTACKERR - (CSTACKCF + 2))
103#define CSTACKERRMARK (CSTACKCF + 2)
104
105
89/* true if this thread does not have non-yieldable calls in the stack */ 106/* true if this thread does not have non-yieldable calls in the stack */
90#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0) 107#define yieldable(L) (((L)->nCcalls & 0xffff0000) == 0)
91 108
@@ -99,11 +116,11 @@
99/* Decrement the number of non-yieldable calls */ 116/* Decrement the number of non-yieldable calls */
100#define decnny(L) ((L)->nCcalls -= 0x10000) 117#define decnny(L) ((L)->nCcalls -= 0x10000)
101 118
102/* Increment the number of non-yieldable calls and nCcalls */ 119/* Increment the number of non-yieldable calls and decrement nCcalls */
103#define incXCcalls(L) ((L)->nCcalls += 0x10000 + CSTACKCF) 120#define incXCcalls(L) ((L)->nCcalls += 0x10000 - CSTACKCF)
104 121
105/* Decrement the number of non-yieldable calls and nCcalls */ 122/* Decrement the number of non-yieldable calls and increment nCcalls */
106#define decXCcalls(L) ((L)->nCcalls -= 0x10000 + CSTACKCF) 123#define decXCcalls(L) ((L)->nCcalls -= 0x10000 - CSTACKCF)
107 124
108 125
109 126
@@ -336,7 +353,7 @@ LUAI_FUNC void luaE_enterCcall (lua_State *L);
336LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); 353LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont);
337 354
338 355
339#define luaE_exitCcall(L) ((L)->nCcalls--) 356#define luaE_exitCcall(L) ((L)->nCcalls++)
340 357
341#endif 358#endif
342 359
diff --git a/testes/all.lua b/testes/all.lua
index 2e6fe038..72121e8d 100644
--- a/testes/all.lua
+++ b/testes/all.lua
@@ -95,6 +95,8 @@ local function F (m)
95 end 95 end
96end 96end
97 97
98local Cstacklevel
99
98local showmem 100local showmem
99if not T then 101if not T then
100 local max = 0 102 local max = 0
@@ -104,6 +106,7 @@ if not T then
104 print(format(" ---- total memory: %s, max memory: %s ----\n", 106 print(format(" ---- total memory: %s, max memory: %s ----\n",
105 F(m), F(max))) 107 F(m), F(max)))
106 end 108 end
109 Cstacklevel = function () return 0 end -- no info about stack level
107else 110else
108 showmem = function () 111 showmem = function ()
109 T.checkmemory() 112 T.checkmemory()
@@ -117,9 +120,16 @@ else
117 T.totalmem"string", T.totalmem"table", T.totalmem"function", 120 T.totalmem"string", T.totalmem"table", T.totalmem"function",
118 T.totalmem"userdata", T.totalmem"thread")) 121 T.totalmem"userdata", T.totalmem"thread"))
119 end 122 end
123
124 Cstacklevel = function ()
125 local _, _, ncalls, nci = T.stacklevel()
126 return ncalls + nci -- number of free slots in the C stack
127 end
120end 128end
121 129
122 130
131local Cstack = Cstacklevel()
132
123-- 133--
124-- redefine dofile to run files through dump/undump 134-- redefine dofile to run files through dump/undump
125-- 135--
@@ -211,6 +221,10 @@ debug.sethook(function (a) assert(type(a) == 'string') end, "cr")
211-- to survive outside block 221-- to survive outside block
212_G.showmem = showmem 222_G.showmem = showmem
213 223
224
225assert(Cstack == Cstacklevel(),
226 "should be at the same C-stack level it was when started the tests")
227
214end --) 228end --)
215 229
216local _G, showmem, print, format, clock, time, difftime, 230local _G, showmem, print, format, clock, time, difftime,