summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLua Team <team@lua.org>2012-05-23 12:00:00 +0000
committerrepogen <>2012-05-23 12:00:00 +0000
commitad17e8349cfc1992f1df7ae937fc146b1a0d564e (patch)
treef9a541ea772e343f075ba3bc8bf3aabe990519c3
parent1cb937cf2d4583482aadaff45b6628b39fdcd91e (diff)
downloadlua-github-ad17e8349cfc1992f1df7ae937fc146b1a0d564e.tar.gz
Lua 5.2.1-rc15.2.1-rc1
-rw-r--r--Makefile2
-rw-r--r--README2
-rw-r--r--doc/contents.html6
-rw-r--r--doc/lua.css10
-rw-r--r--doc/manual.css4
-rw-r--r--doc/manual.html160
-rw-r--r--doc/readme.html16
-rw-r--r--src/lapi.c18
-rw-r--r--src/lauxlib.c8
-rw-r--r--src/lbaselib.c3
-rw-r--r--src/lcorolib.c5
-rw-r--r--src/ldo.c26
-rw-r--r--src/ldump.c2
-rw-r--r--src/lfunc.c7
-rw-r--r--src/lfunc.h4
-rw-r--r--src/lgc.c342
-rw-r--r--src/lgc.h16
-rw-r--r--src/llimits.h24
-rw-r--r--src/lmathlib.c12
-rw-r--r--src/lmem.c18
-rw-r--r--src/loadlib.c93
-rw-r--r--src/lobject.h42
-rw-r--r--src/lopcodes.c3
-rw-r--r--src/loslib.c17
-rw-r--r--src/lparser.c139
-rw-r--r--src/lparser.h6
-rw-r--r--src/lstate.c9
-rw-r--r--src/lstate.h8
-rw-r--r--src/lstring.c22
-rw-r--r--src/lstrlib.c35
-rw-r--r--src/ltable.c6
-rw-r--r--src/lua.c31
-rw-r--r--src/lua.h8
-rw-r--r--src/luaconf.h103
-rw-r--r--src/lundump.c35
-rw-r--r--src/lundump.h4
-rw-r--r--src/lvm.c28
-rw-r--r--src/lzio.c4
38 files changed, 685 insertions, 593 deletions
diff --git a/Makefile b/Makefile
index ec53e1a2..bd9515fd 100644
--- a/Makefile
+++ b/Makefile
@@ -46,7 +46,7 @@ TO_MAN= lua.1 luac.1
# Lua version and release.
V= 5.2
-R= $V.0
+R= $V.1
# Targets start here.
all: $(PLAT)
diff --git a/README b/README
index 0ffe4ca6..bdbab775 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
-This is Lua 5.2.1, released on xx xxx 2012.
+This is Lua 5.2.1, released on 23 May 2012.
For installation instructions, license details, and
further information about Lua, see doc/readme.html.
diff --git a/doc/contents.html b/doc/contents.html
index 5342723f..8340ff35 100644
--- a/doc/contents.html
+++ b/doc/contents.html
@@ -33,7 +33,7 @@ For a complete introduction to Lua programming, see the book
<A HREF="#index">index</A>
<HR>
<SMALL>
-Copyright &copy; 2011 Lua.org, PUC-Rio.
+Copyright &copy; 2011&ndash;2012 Lua.org, PUC-Rio.
Freely available under the terms of the
<A HREF="http://www.lua.org/license.html#5">Lua license</A>.
</SMALL>
@@ -521,10 +521,10 @@ Freely available under the terms of the
<HR>
<SMALL CLASS="footer">
Last update:
-Tue Nov 29 22:30:23 BRST 2011
+Wed May 23 13:28:09 BRT 2012
</SMALL>
<!--
-Last change: revised for Lua 5.2.0
+Last change: revised for Lua 5.2.1
-->
</BODY>
diff --git a/doc/lua.css b/doc/lua.css
index 54708f82..7fafbb1b 100644
--- a/doc/lua.css
+++ b/doc/lua.css
@@ -3,8 +3,8 @@ body {
background-color: #FFFFFF ;
font-family: Helvetica, Arial, sans-serif ;
text-align: justify ;
- margin-right: 20px ;
- margin-left: 20px ;
+ margin-right: 30px ;
+ margin-left: 30px ;
}
h1, h2, h3, h4 {
@@ -16,9 +16,9 @@ h1, h2, h3, h4 {
h2 {
padding-top: 0.4em ;
padding-bottom: 0.4em ;
- padding-left: 20px ;
- padding-right: 20px ;
- margin-left: -20px ;
+ padding-left: 30px ;
+ padding-right: 30px ;
+ margin-left: -30px ;
background-color: #E0E0FF ;
}
diff --git a/doc/manual.css b/doc/manual.css
index ac357a89..b49b3629 100644
--- a/doc/manual.css
+++ b/doc/manual.css
@@ -18,7 +18,7 @@ span.apii {
p+h1, ul+h1 {
padding-top: 0.4em ;
padding-bottom: 0.4em ;
- padding-left: 20px ;
- margin-left: -20px ;
+ padding-left: 30px ;
+ margin-left: -30px ;
background-color: #E0E0FF ;
}
diff --git a/doc/manual.html b/doc/manual.html
index 360d3168..cd6dda52 100644
--- a/doc/manual.html
+++ b/doc/manual.html
@@ -19,7 +19,7 @@ Lua 5.2 Reference Manual
by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes
<p>
<small>
-Copyright &copy; 2011 Lua.org, PUC-Rio.
+Copyright &copy; 2011&ndash;2012 Lua.org, PUC-Rio.
Freely available under the terms of the
<a href="http://www.lua.org/license.html#5">Lua license</a>.
</small>
@@ -33,7 +33,7 @@ Freely available under the terms of the
<!-- ====================================================================== -->
<p>
-<!-- $Id: manual.of,v 1.94 2011/12/12 15:26:26 roberto Exp $ -->
+<!-- $Id: manual.of,v 1.97 2012/05/23 15:50:01 roberto Exp $ -->
@@ -913,6 +913,14 @@ the object memory is freed only when it becomes completely inaccessible;
its finalizer will never be called twice.
+<p>
+When you close a state (see <a href="#lua_close"><code>lua_close</code></a>),
+Lua calls the finalizers of all objects marked for collection,
+following the reverse order that they were marked.
+If any finalizer marks new objects for collection during that phase,
+these new objects will not be finalized.
+
+
@@ -1206,7 +1214,7 @@ results in a newline in the string.
The escape sequence '<code>\z</code>' skips the following span
of white-space characters,
including line breaks;
-it is particularly useful to break and indent a long string
+it is particularly useful to break and indent a long literal string
into multiple lines without adding the newlines and spaces
into the string contents.
@@ -1234,7 +1242,7 @@ an opening long bracket of level&nbsp;1 is written as <code>[=[</code>,
and so on.
A <em>closing long bracket</em> is defined similarly;
for instance, a closing long bracket of level&nbsp;4 is written as <code>]====]</code>.
-A long string starts with an opening long bracket of any level and
+A <em>long literal</em> starts with an opening long bracket of any level and
ends at the first closing long bracket of the same level.
It can contain any text except a closing bracket of the proper level.
Literals in this bracketed form can run for several lines,
@@ -2922,7 +2930,7 @@ it seems to be a safe assumption.)
<hr><h3><a name="lua_arith"><code>lua_arith</code></a></h3><p>
<span class="apii">[-(2|1), +1, <em>e</em>]</span>
-<pre>int lua_arith (lua_State *L, int op);</pre>
+<pre>void lua_arith (lua_State *L, int op);</pre>
<p>
Performs an arithmetic operation over the two values
@@ -4400,7 +4408,7 @@ and then pops the top element.
<hr><h3><a name="lua_resume"><code>lua_resume</code></a></h3><p>
<span class="apii">[-?, +?, &ndash;]</span>
-<pre>int lua_resume (lua_State *L, lua_State *from, int narg);</pre>
+<pre>int lua_resume (lua_State *L, lua_State *from, int nargs);</pre>
<p>
Starts and resumes a coroutine in a given thread.
@@ -4410,7 +4418,7 @@ Starts and resumes a coroutine in a given thread.
To start a coroutine,
you push onto the thread stack the main function plus any arguments;
then you call <a href="#lua_resume"><code>lua_resume</code></a>,
-with <code>narg</code> being the number of arguments.
+with <code>nargs</code> being the number of arguments.
This call returns when the coroutine suspends or finishes its execution.
When it returns, the stack contains all values passed to <a href="#lua_yield"><code>lua_yield</code></a>,
or all values returned by the body function.
@@ -4550,14 +4558,15 @@ the new value associated to the userdata at the given index.
<pre>typedef struct lua_State lua_State;</pre>
<p>
-An opaque structure that keeps the whole state of a Lua interpreter.
+An opaque structure that points to a thread and indirectly
+(through the thread) to the whole state of a Lua interpreter.
The Lua library is fully reentrant:
it has no global variables.
-All information about a state is kept in this structure.
+All information about a state is accessible through this structure.
<p>
-A pointer to this state must be passed as the first argument to
+A pointer to this structure must be passed as the first argument to
every function in the library, except to <a href="#lua_newstate"><code>lua_newstate</code></a>,
which creates a Lua state from scratch.
@@ -5149,7 +5158,7 @@ Returns the current hook mask.
<pre>int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);</pre>
<p>
-Returns information about a specific function or function invocation.
+Gets information about a specific function or function invocation.
<p>
@@ -5268,7 +5277,7 @@ the number of active local variables.
<pre>int lua_getstack (lua_State *L, int level, lua_Debug *ar);</pre>
<p>
-Get information about the interpreter runtime stack.
+Gets information about the interpreter runtime stack.
<p>
@@ -5345,6 +5354,11 @@ Therefore, if a hook calls back Lua to execute a function or a chunk,
this execution occurs without any calls to hooks.
+<p>
+Hook functions cannot yield
+(that is, call <a href="#lua_yieldk"><code>lua_yieldk</code></a> or <a href="#lua_yield"><code>lua_yield</code></a>).
+
+
@@ -5450,7 +5464,7 @@ when the index is greater than the number of upvalues.
<p>
Returns an unique identifier for the upvalue numbered <code>n</code>
-from the closure at index <code>fidx</code>.
+from the closure at index <code>funcindex</code>.
Parameters <code>funcindex</code> and <code>n</code> are as in the <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>
(see <a href="#lua_getupvalue"><code>lua_getupvalue</code></a>)
(but <code>n</code> cannot be greater than the number of upvalues).
@@ -5467,13 +5481,14 @@ will return identical ids for those upvalue indices.
-<hr><h3><a name="lua_upvaluejoin"><code>lua_upvaluejoin</code></a></h3>
-<pre>void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
- int fidx2, int n2);</pre>
+<hr><h3><a name="lua_upvaluejoin"><code>lua_upvaluejoin</code></a></h3><p>
+<span class="apii">[-0, +0, &ndash;]</span>
+<pre>void lua_upvaluejoin (lua_State *L, int funcindex1, int n1,
+ int funcindex2, int n2);</pre>
<p>
-Make the <code>n1</code>-th upvalue of the Lua closure at index <code>fidx1</code>
-refer to the <code>n2</code>-th upvalue of the Lua closure at index <code>fidx2</code>.
+Make the <code>n1</code>-th upvalue of the Lua closure at index <code>funcindex1</code>
+refer to the <code>n2</code>-th upvalue of the Lua closure at index <code>funcindex2</code>.
@@ -5614,7 +5629,7 @@ which is the value to be added to the buffer.
<span class="apii">[-0, +0, <em>v</em>]</span>
<pre>void luaL_argcheck (lua_State *L,
int cond,
- int narg,
+ int arg,
const char *extramsg);</pre>
<p>
@@ -5627,7 +5642,7 @@ If not, raises an error with a standard message.
<hr><h3><a name="luaL_argerror"><code>luaL_argerror</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_argerror (lua_State *L, int narg, const char *extramsg);</pre>
+<pre>int luaL_argerror (lua_State *L, int arg, const char *extramsg);</pre>
<p>
Raises an error with a standard message
@@ -5686,7 +5701,7 @@ size <code>sz</code> with a call <code>luaL_buffinitsize(L, &amp;b, sz)</code>.<
<li>Then copy the string into that space.</li>
<li>
-Finish by calling <code>luaL_pushresult(&amp;b, sz)</code>,
+Finish by calling <code>luaL_pushresultsize(&amp;b, sz)</code>,
where <code>sz</code> is the total size of the resulting string
copied into that space.
</li>
@@ -5762,11 +5777,11 @@ this function returns false (without pushing any value on the stack).
<hr><h3><a name="luaL_checkany"><code>luaL_checkany</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>void luaL_checkany (lua_State *L, int narg);</pre>
+<pre>void luaL_checkany (lua_State *L, int arg);</pre>
<p>
Checks whether the function has an argument
-of any type (including <b>nil</b>) at position <code>narg</code>.
+of any type (including <b>nil</b>) at position <code>arg</code>.
@@ -5774,10 +5789,10 @@ of any type (including <b>nil</b>) at position <code>narg</code>.
<hr><h3><a name="luaL_checkint"><code>luaL_checkint</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_checkint (lua_State *L, int narg);</pre>
+<pre>int luaL_checkint (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
and returns this number cast to an <code>int</code>.
@@ -5786,10 +5801,10 @@ and returns this number cast to an <code>int</code>.
<hr><h3><a name="luaL_checkinteger"><code>luaL_checkinteger</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Integer luaL_checkinteger (lua_State *L, int narg);</pre>
+<pre>lua_Integer luaL_checkinteger (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
@@ -5798,10 +5813,10 @@ and returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code
<hr><h3><a name="luaL_checklong"><code>luaL_checklong</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>long luaL_checklong (lua_State *L, int narg);</pre>
+<pre>long luaL_checklong (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
and returns this number cast to a <code>long</code>.
@@ -5810,10 +5825,10 @@ and returns this number cast to a <code>long</code>.
<hr><h3><a name="luaL_checklstring"><code>luaL_checklstring</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>const char *luaL_checklstring (lua_State *L, int narg, size_t *l);</pre>
+<pre>const char *luaL_checklstring (lua_State *L, int arg, size_t *l);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a string
+Checks whether the function argument <code>arg</code> is a string
and returns this string;
if <code>l</code> is not <code>NULL</code> fills <code>*l</code>
with the string's length.
@@ -5829,10 +5844,10 @@ so all conversions and caveats of that function apply here.
<hr><h3><a name="luaL_checknumber"><code>luaL_checknumber</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Number luaL_checknumber (lua_State *L, int narg);</pre>
+<pre>lua_Number luaL_checknumber (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
and returns this number.
@@ -5842,12 +5857,12 @@ and returns this number.
<hr><h3><a name="luaL_checkoption"><code>luaL_checkoption</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
<pre>int luaL_checkoption (lua_State *L,
- int narg,
+ int arg,
const char *def,
const char *const lst[]);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a string and
+Checks whether the function argument <code>arg</code> is a string and
searches for this string in the array <code>lst</code>
(which must be NULL-terminated).
Returns the index in the array where the string was found.
@@ -5858,7 +5873,7 @@ if the string cannot be found.
<p>
If <code>def</code> is not <code>NULL</code>,
the function uses <code>def</code> as a default value when
-there is no argument <code>narg</code> or when this argument is <b>nil</b>.
+there is no argument <code>arg</code> or when this argument is <b>nil</b>.
<p>
@@ -5886,10 +5901,10 @@ raising an error if the stack cannot grow to that size.
<hr><h3><a name="luaL_checkstring"><code>luaL_checkstring</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>const char *luaL_checkstring (lua_State *L, int narg);</pre>
+<pre>const char *luaL_checkstring (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a string
+Checks whether the function argument <code>arg</code> is a string
and returns this string.
@@ -5903,10 +5918,10 @@ so all conversions and caveats of that function apply here.
<hr><h3><a name="luaL_checktype"><code>luaL_checktype</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>void luaL_checktype (lua_State *L, int narg, int t);</pre>
+<pre>void luaL_checktype (lua_State *L, int arg, int t);</pre>
<p>
-Checks whether the function argument <code>narg</code> has type <code>t</code>.
+Checks whether the function argument <code>arg</code> has type <code>t</code>.
See <a href="#lua_type"><code>lua_type</code></a> for the encoding of types for <code>t</code>.
@@ -5915,10 +5930,10 @@ See <a href="#lua_type"><code>lua_type</code></a> for the encoding of types for
<hr><h3><a name="luaL_checkudata"><code>luaL_checkudata</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>void *luaL_checkudata (lua_State *L, int narg, const char *tname);</pre>
+<pre>void *luaL_checkudata (lua_State *L, int arg, const char *tname);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a userdata
+Checks whether the function argument <code>arg</code> is a userdata
of the type <code>tname</code> (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>) and
returns the userdata address (see <a href="#lua_touserdata"><code>lua_touserdata</code></a>).
@@ -5928,10 +5943,10 @@ returns the userdata address (see <a href="#lua_touserdata"><code>lua_touserdata
<hr><h3><a name="luaL_checkunsigned"><code>luaL_checkunsigned</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Unsigned luaL_checkunsigned (lua_State *L, int narg);</pre>
+<pre>lua_Unsigned luaL_checkunsigned (lua_State *L, int arg);</pre>
<p>
-Checks whether the function argument <code>narg</code> is a number
+Checks whether the function argument <code>arg</code> is a number
and returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
@@ -6100,7 +6115,7 @@ Pushes the resulting string on the stack and returns it.
<hr><h3><a name="luaL_len"><code>luaL_len</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +0, <em>e</em>]</span>
<pre>int luaL_len (lua_State *L, int index);</pre>
<p>
@@ -6108,7 +6123,7 @@ Returns the "length" of the value at the given acceptable index
as a number;
it is equivalent to the '<code>#</code>' operator in Lua (see <a href="#3.4.6">&sect;3.4.6</a>).
Raises an error if the result of the operation is not a number.
-(This only can happen through metamethods.)
+(This case only can happen through metamethods.)
@@ -6309,10 +6324,10 @@ Opens all standard Lua libraries into the given state.
<hr><h3><a name="luaL_optint"><code>luaL_optint</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>int luaL_optint (lua_State *L, int narg, int d);</pre>
+<pre>int luaL_optint (lua_State *L, int arg, int d);</pre>
<p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
returns this number cast to an <code>int</code>.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
@@ -6325,11 +6340,11 @@ Otherwise, raises an error.
<hr><h3><a name="luaL_optinteger"><code>luaL_optinteger</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
<pre>lua_Integer luaL_optinteger (lua_State *L,
- int narg,
+ int arg,
lua_Integer d);</pre>
<p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
returns this number cast to a <a href="#lua_Integer"><code>lua_Integer</code></a>.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
@@ -6341,10 +6356,10 @@ Otherwise, raises an error.
<hr><h3><a name="luaL_optlong"><code>luaL_optlong</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>long luaL_optlong (lua_State *L, int narg, long d);</pre>
+<pre>long luaL_optlong (lua_State *L, int arg, long d);</pre>
<p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
returns this number cast to a <code>long</code>.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
@@ -6357,12 +6372,12 @@ Otherwise, raises an error.
<hr><h3><a name="luaL_optlstring"><code>luaL_optlstring</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
<pre>const char *luaL_optlstring (lua_State *L,
- int narg,
+ int arg,
const char *d,
size_t *l);</pre>
<p>
-If the function argument <code>narg</code> is a string,
+If the function argument <code>arg</code> is a string,
returns this string.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
@@ -6379,10 +6394,10 @@ fills the position <code>*l</code> with the result's length.
<hr><h3><a name="luaL_optnumber"><code>luaL_optnumber</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
-<pre>lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);</pre>
+<pre>lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number d);</pre>
<p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
returns this number.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
@@ -6395,11 +6410,11 @@ Otherwise, raises an error.
<hr><h3><a name="luaL_optstring"><code>luaL_optstring</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
<pre>const char *luaL_optstring (lua_State *L,
- int narg,
+ int arg,
const char *d);</pre>
<p>
-If the function argument <code>narg</code> is a string,
+If the function argument <code>arg</code> is a string,
returns this string.
If this argument is absent or is <b>nil</b>,
returns <code>d</code>.
@@ -6412,11 +6427,11 @@ Otherwise, raises an error.
<hr><h3><a name="luaL_optunsigned"><code>luaL_optunsigned</code></a></h3><p>
<span class="apii">[-0, +0, <em>v</em>]</span>
<pre>lua_Unsigned luaL_optunsigned (lua_State *L,
- int narg,
+ int arg,
lua_Unsigned u);</pre>
<p>
-If the function argument <code>narg</code> is a number,
+If the function argument <code>arg</code> is a number,
returns this number cast to a <a href="#lua_Unsigned"><code>lua_Unsigned</code></a>.
If this argument is absent or is <b>nil</b>,
returns <code>u</code>.
@@ -6583,7 +6598,7 @@ in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code>
<hr><h3><a name="luaL_testudata"><code>luaL_testudata</code></a></h3><p>
<span class="apii">[-0, +0, <em>m</em>]</span>
-<pre>void *luaL_testudata (lua_State *L, int narg, const char *tname);</pre>
+<pre>void *luaL_testudata (lua_State *L, int arg, const char *tname);</pre>
<p>
This function works like <a href="#luaL_checkudata"><code>luaL_checkudata</code></a>,
@@ -6749,7 +6764,7 @@ the host program can open them individually by using
<a name="pdf-luaopen_string"><code>luaopen_string</code></a> (for the string library),
<a name="pdf-luaopen_table"><code>luaopen_table</code></a> (for the table library),
<a name="pdf-luaopen_math"><code>luaopen_math</code></a> (for the mathematical library),
-<a name="pdf-luaopen_bitlib"><code>luaopen_bitlib</code></a> (for the bit library),
+<a name="pdf-luaopen_bit32"><code>luaopen_bit32</code></a> (for the bit library),
<a name="pdf-luaopen_io"><code>luaopen_io</code></a> (for the I/O library),
<a name="pdf-luaopen_os"><code>luaopen_os</code></a> (for the Operating System library),
and <a name="pdf-luaopen_debug"><code>luaopen_debug</code></a> (for the debug library).
@@ -7914,24 +7929,26 @@ If <code>repl</code> is a string, then its value is used for replacement.
The character&nbsp;<code>%</code> works as an escape character:
any sequence in <code>repl</code> of the form <code>%<em>d</em></code>,
with <em>d</em> between 1 and 9,
-stands for the value of the <em>d</em>-th captured substring (see below).
+stands for the value of the <em>d</em>-th captured substring.
The sequence <code>%0</code> stands for the whole match.
The sequence <code>%%</code> stands for a single&nbsp;<code>%</code>.
<p>
If <code>repl</code> is a table, then the table is queried for every match,
-using the first capture as the key;
-if the pattern specifies no captures,
-then the whole match is used as the key.
+using the first capture as the key.
<p>
If <code>repl</code> is a function, then this function is called every time a
match occurs, with all captured substrings passed as arguments,
-in order;
+in order.
+
+
+<p>
+In any case,
if the pattern specifies no captures,
-then the whole match is passed as a sole argument.
+then it behaves as if the whole pattern was inside a capture.
<p>
@@ -10091,6 +10108,9 @@ You can avoid some incompatibilities by compiling Lua with
appropriate options (see file <code>luaconf.h</code>).
However,
all these compatibility options will be removed in the next version of Lua.
+Similarly,
+all features marked as deprecated in Lua&nbsp;5.1
+have been removed in Lua&nbsp;5.2.
@@ -10387,10 +10407,10 @@ Here is the complete syntax of Lua in extended BNF.
<HR>
<SMALL CLASS="footer">
Last update:
-Mon Dec 12 15:21:08 BRST 2011
+Wed May 23 13:28:41 BRT 2012
</SMALL>
<!--
-Last change: revised for Lua 5.2.0
+Last change: revised for Lua 5.2.1
-->
</body></html>
diff --git a/doc/readme.html b/doc/readme.html
index f0c77a16..7bd1829d 100644
--- a/doc/readme.html
+++ b/doc/readme.html
@@ -101,14 +101,6 @@ Try also
<A HREF="http://luaforwindows.luaforge.net/">Lua for Windows</A>,
an easy-to-use distribution of Lua that includes many useful libraries.
-<!--
-<P>
-If you only want to try Lua,
-try the
-<A HREF="demo.html">live demo</A>.
-<P>
--->
-
<H3>Building Lua</H3>
<P>
@@ -118,7 +110,7 @@ Here are the details.
<OL>
<LI>
Open a terminal window and move to
-the top-level directory, which is named <TT>lua-5.2.0</TT>.
+the top-level directory, which is named <TT>lua-5.2.1</TT>.
The Makefile there controls both the build process and the installation process.
<P>
<LI>
@@ -381,7 +373,7 @@ For details, see
<A HREF="http://www.lua.org/license.html">this</A>.
<BLOCKQUOTE STYLE="padding-bottom: 0em">
-Copyright &copy; 1994&ndash;2011 Lua.org, PUC-Rio.
+Copyright &copy; 1994&ndash;2012 Lua.org, PUC-Rio.
<P>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -409,10 +401,10 @@ THE SOFTWARE.
<HR>
<SMALL CLASS="footer">
Last update:
-Wed Nov 23 16:17:22 BRST 2011
+Thu May 17 11:09:49 BRT 2012
</SMALL>
<!--
-Last change: revised for Lua 5.2.0
+Last change: revised for Lua 5.2.1
-->
</BODY>
diff --git a/src/lapi.c b/src/lapi.c
index e96ceb9e..736d9648 100644
--- a/src/lapi.c
+++ b/src/lapi.c
@@ -1,5 +1,5 @@
/*
-** $Id: lapi.c,v 2.159 2011/11/30 12:32:05 roberto Exp $
+** $Id: lapi.c,v 2.163 2012/05/23 15:42:27 roberto Exp $
** Lua API
** See Copyright Notice in lua.h
*/
@@ -1045,17 +1045,17 @@ LUA_API int lua_gc (lua_State *L, int what, int data) {
}
case LUA_GCSTEP: {
if (g->gckind == KGC_GEN) { /* generational mode? */
- res = (g->lastmajormem == 0); /* 1 if will do major collection */
+ res = (g->GCestimate == 0); /* true if it will do major collection */
luaC_forcestep(L); /* do a single step */
}
else {
- while (data-- >= 0) {
- luaC_forcestep(L);
- if (g->gcstate == GCSpause) { /* end of cycle? */
- res = 1; /* signal it */
- break;
- }
- }
+ lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE;
+ if (g->gcrunning)
+ debt += g->GCdebt; /* include current debt */
+ luaE_setdebt(g, debt);
+ luaC_forcestep(L);
+ if (g->gcstate == GCSpause) /* end of cycle? */
+ res = 1; /* signal it */
}
break;
}
diff --git a/src/lauxlib.c b/src/lauxlib.c
index 5f4916ea..24d4abb2 100644
--- a/src/lauxlib.c
+++ b/src/lauxlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lauxlib.c,v 1.242 2012/03/19 22:57:14 roberto Exp $
+** $Id: lauxlib.c,v 1.243 2012/04/20 17:05:17 roberto Exp $
** Auxiliary functions for building Lua libraries
** See Copyright Notice in lua.h
*/
@@ -892,10 +892,8 @@ LUALIB_API void luaL_requiref (lua_State *L, const char *modname,
lua_setfield(L, -2, modname); /* _LOADED[modname] = module */
lua_pop(L, 1); /* remove _LOADED table */
if (glb) {
- lua_pushglobaltable(L);
- lua_pushvalue(L, -2); /* copy of 'mod' */
- lua_setfield(L, -2, modname); /* _G[modname] = module */
- lua_pop(L, 1); /* remove _G table */
+ lua_pushvalue(L, -1); /* copy of 'mod' */
+ lua_setglobal(L, modname); /* _G[modname] = module */
}
}
diff --git a/src/lbaselib.c b/src/lbaselib.c
index 1dfae301..dbfcb02c 100644
--- a/src/lbaselib.c
+++ b/src/lbaselib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lbaselib.c,v 1.273 2011/11/30 13:03:24 roberto Exp $
+** $Id: lbaselib.c,v 1.274 2012/04/27 14:13:19 roberto Exp $
** Basic library
** See Copyright Notice in lua.h
*/
@@ -293,6 +293,7 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) {
lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) {
+ lua_pop(L, 1); /* pop result */
*size = 0;
return NULL;
}
diff --git a/src/lcorolib.c b/src/lcorolib.c
index 0edde26d..c7932d90 100644
--- a/src/lcorolib.c
+++ b/src/lcorolib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lcorolib.c,v 1.3 2011/08/23 17:24:34 roberto Exp $
+** $Id: lcorolib.c,v 1.4 2012/04/27 18:59:04 roberto Exp $
** Coroutine Library
** See Copyright Notice in lua.h
*/
@@ -80,8 +80,9 @@ static int luaB_auxwrap (lua_State *L) {
static int luaB_cocreate (lua_State *L) {
- lua_State *NL = lua_newthread(L);
+ lua_State *NL;
luaL_checktype(L, 1, LUA_TFUNCTION);
+ NL = lua_newthread(L);
lua_pushvalue(L, 1); /* move function to top */
lua_xmove(L, NL, 1); /* move function from L to NL */
return 1;
diff --git a/src/ldo.c b/src/ldo.c
index 26f9a674..0a5ed6be 100644
--- a/src/ldo.c
+++ b/src/ldo.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldo.c,v 2.102 2011/11/29 15:55:08 roberto Exp $
+** $Id: ldo.c,v 2.104 2012/05/08 13:53:33 roberto Exp $
** Stack and Call structure of Lua
** See Copyright Notice in lua.h
*/
@@ -402,8 +402,6 @@ static void finishCcall (lua_State *L) {
int n;
lua_assert(ci->u.c.k != NULL); /* must have a continuation */
lua_assert(L->nny == 0);
- /* finish 'luaD_call' */
- L->nCcalls--;
/* finish 'lua_callk' */
adjustresults(L, ci->nresults);
/* call continuation function */
@@ -484,9 +482,10 @@ static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) {
** do the work for 'lua_resume' in protected mode
*/
static void resume (lua_State *L, void *ud) {
+ int nCcalls = L->nCcalls;
StkId firstArg = cast(StkId, ud);
CallInfo *ci = L->ci;
- if (L->nCcalls >= LUAI_MAXCCALLS)
+ if (nCcalls >= LUAI_MAXCCALLS)
resume_error(L, "C stack overflow", firstArg);
if (L->status == LUA_OK) { /* may be starting a coroutine */
if (ci != &L->base_ci) /* not in base level? */
@@ -513,11 +512,11 @@ static void resume (lua_State *L, void *ud) {
api_checknelems(L, n);
firstArg = L->top - n; /* yield results come from continuation */
}
- L->nCcalls--; /* finish 'luaD_call' */
luaD_poscall(L, firstArg); /* finish 'luaD_precall' */
}
unroll(L, NULL);
}
+ lua_assert(nCcalls == L->nCcalls);
}
@@ -627,24 +626,23 @@ static void checkmode (lua_State *L, const char *mode, const char *x) {
static void f_parser (lua_State *L, void *ud) {
int i;
- Proto *tf;
Closure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = zgetc(p->z); /* read first character */
if (c == LUA_SIGNATURE[0]) {
checkmode(L, p->mode, "binary");
- tf = luaU_undump(L, p->z, &p->buff, p->name);
+ cl = luaU_undump(L, p->z, &p->buff, p->name);
}
else {
checkmode(L, p->mode, "text");
- tf = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
+ cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
+ }
+ lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues);
+ for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */
+ UpVal *up = luaF_newupval(L);
+ cl->l.upvals[i] = up;
+ luaC_objbarrier(L, cl, up);
}
- setptvalue2s(L, L->top, tf);
- incr_top(L);
- cl = luaF_newLclosure(L, tf);
- setclLvalue(L, L->top - 1, cl);
- for (i = 0; i < tf->sizeupvalues; i++) /* initialize upvalues */
- cl->l.upvals[i] = luaF_newupval(L);
}
diff --git a/src/ldump.c b/src/ldump.c
index ae1c780f..d5e6a47c 100644
--- a/src/ldump.c
+++ b/src/ldump.c
@@ -1,5 +1,5 @@
/*
-** $Id: ldump.c,v 1.20 2012/03/21 18:11:35 lhf Exp $
+** $Id: ldump.c,v 2.17 2012/01/23 23:02:10 roberto Exp $
** save precompiled Lua chunks
** See Copyright Notice in lua.h
*/
diff --git a/src/lfunc.c b/src/lfunc.c
index 9492283a..4fd27fe5 100644
--- a/src/lfunc.c
+++ b/src/lfunc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lfunc.c,v 2.28 2012/01/20 22:05:50 roberto Exp $
+** $Id: lfunc.c,v 2.29 2012/05/08 13:53:33 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -27,10 +27,9 @@ Closure *luaF_newCclosure (lua_State *L, int n) {
}
-Closure *luaF_newLclosure (lua_State *L, Proto *p) {
- int n = p->sizeupvalues;
+Closure *luaF_newLclosure (lua_State *L, int n) {
Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl;
- c->l.p = p;
+ c->l.p = NULL;
c->l.nupvalues = cast_byte(n);
while (n--) c->l.upvals[n] = NULL;
return c;
diff --git a/src/lfunc.h b/src/lfunc.h
index fe8efde0..e236a717 100644
--- a/src/lfunc.h
+++ b/src/lfunc.h
@@ -1,5 +1,5 @@
/*
-** $Id: lfunc.h,v 2.7 2012/01/20 22:05:50 roberto Exp $
+** $Id: lfunc.h,v 2.8 2012/05/08 13:53:33 roberto Exp $
** Auxiliary functions to manipulate prototypes and closures
** See Copyright Notice in lua.h
*/
@@ -20,7 +20,7 @@
LUAI_FUNC Proto *luaF_newproto (lua_State *L);
LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems);
-LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, Proto *p);
+LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems);
LUAI_FUNC UpVal *luaF_newupval (lua_State *L);
LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);
LUAI_FUNC void luaF_close (lua_State *L, StkId level);
diff --git a/src/lgc.c b/src/lgc.c
index ce421637..e15da8b2 100644
--- a/src/lgc.c
+++ b/src/lgc.c
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.c,v 2.119 2012/01/25 21:05:40 roberto Exp $
+** $Id: lgc.c,v 2.128 2012/05/23 15:43:14 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -24,34 +24,35 @@
-/* how much to allocate before next GC step */
-#define GCSTEPSIZE 1024
+/* cost of sweeping one element (half the size of a small object) */
+#define GCSWEEPCOST ((sizeof(TString) + 4) / 2)
/* maximum number of elements to sweep in each single step */
-#define GCSWEEPMAX 40
-
-/* cost of sweeping one element */
-#define GCSWEEPCOST 1
+#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4))
/* maximum number of finalizers to call in each GC step */
#define GCFINALIZENUM 4
-/* cost of marking the root set */
-#define GCROOTCOST 10
+/* (arbitrary) cost of atomic step */
+#define GCATOMICCOST GCSTEPSIZE
-/* cost of atomic step */
-#define GCATOMICCOST 1000
-/* basic cost to traverse one object (to be added to the links the
- object may have) */
-#define TRAVCOST 5
+/*
+** macro to apply the "speed" of the garbage collector: the constant
+** 80 makes the standard 'stepmul' of 200 results in the GC handling
+** 80/200 = 1/2.5 = 0.4Kbytes for every 1Kb allocated.
+** (The computation tries to avoid overflows or underflows.)
+*/
+#define workrate(x,mul) \
+ ((x) < MAX_INT/80 ? ((x) * 80) / mul : ((x) / mul) * 80)
/*
** standard negative debt for GC; a reasonable "time" to wait before
** starting a new cycle
*/
-#define stddebt(g) (-cast(l_mem, gettotalbytes(g)/100) * g->gcpause)
+#define stddebtest(g,e) (-cast(l_mem, (e)/100) * g->gcpause)
+#define stddebt(g) stddebtest(g, gettotalbytes(g))
/*
@@ -65,12 +66,6 @@
#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS)
#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT)
-/*
-** dirty trick: we know that 'reallymarkobject' does not use 'g' when
-** object is a string
-*/
-#define stringmark(s) markobject(NULL, s)
-
#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT)
@@ -127,10 +122,10 @@ static void removeentry (Node *n) {
** other objects: if really collected, cannot keep them; for objects
** being finalized, keep them in keys, but not in values
*/
-static int iscleared (const TValue *o) {
+static int iscleared (global_State *g, const TValue *o) {
if (!iscollectable(o)) return 0;
else if (ttisstring(o)) {
- stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */
+ markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */
return 0;
}
else return iswhite(gcvalue(o));
@@ -250,53 +245,57 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list,
** upvalues are already linked in 'headuv' list.)
*/
static void reallymarkobject (global_State *g, GCObject *o) {
+ lu_mem size;
white2gray(o);
switch (gch(o)->tt) {
case LUA_TSHRSTR:
case LUA_TLNGSTR: {
- gray2black(o);
- return; /* nothing else to mark */
+ size = sizestring(gco2ts(o));
+ break; /* nothing else to mark; make it black */
}
case LUA_TUSERDATA: {
Table *mt = gco2u(o)->metatable;
markobject(g, mt);
markobject(g, gco2u(o)->env);
- gray2black(o); /* all pointers marked */
- return;
+ size = sizeudata(gco2u(o));
+ break;
}
case LUA_TUPVAL: {
UpVal *uv = gco2uv(o);
markvalue(g, uv->v);
- if (uv->v == &uv->u.value) /* closed? (open upvalues remain gray) */
- gray2black(o); /* make it black */
- return;
+ if (uv->v != &uv->u.value) /* open? */
+ return; /* open upvalues remain gray */
+ size = sizeof(UpVal);
+ break;
}
case LUA_TLCL: {
gco2lcl(o)->gclist = g->gray;
g->gray = o;
- break;
+ return;
}
case LUA_TCCL: {
gco2ccl(o)->gclist = g->gray;
g->gray = o;
- break;
+ return;
}
case LUA_TTABLE: {
linktable(gco2t(o), &g->gray);
- break;
+ return;
}
case LUA_TTHREAD: {
gco2th(o)->gclist = g->gray;
g->gray = o;
- break;
+ return;
}
case LUA_TPROTO: {
gco2p(o)->gclist = g->gray;
g->gray = o;
- break;
+ return;
}
- default: lua_assert(0);
+ default: lua_assert(0); return;
}
+ gray2black(o);
+ g->GCmemtrav += size;
}
@@ -369,7 +368,7 @@ static void traverseweakvalue (global_State *g, Table *h) {
else {
lua_assert(!ttisnil(gkey(n)));
markvalue(g, gkey(n)); /* mark key */
- if (!hasclears && iscleared(gval(n))) /* is there a white value? */
+ if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */
hasclears = 1; /* table will have to be cleared */
}
}
@@ -398,7 +397,7 @@ static int traverseephemeron (global_State *g, Table *h) {
checkdeadkey(n);
if (ttisnil(gval(n))) /* entry is empty? */
removeentry(n); /* remove it */
- else if (iscleared(gkey(n))) { /* key is not marked (yet)? */
+ else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */
hasclears = 1; /* table must be cleared */
if (valiswhite(gval(n))) /* value not marked yet? */
prop = 1; /* must propagate again */
@@ -436,30 +435,26 @@ static void traversestrongtable (global_State *g, Table *h) {
}
-static int traversetable (global_State *g, Table *h) {
+static lu_mem traversetable (global_State *g, Table *h) {
+ const char *weakkey, *weakvalue;
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
markobject(g, h->metatable);
- if (mode && ttisstring(mode)) { /* is there a weak mode? */
- int weakkey = (strchr(svalue(mode), 'k') != NULL);
- int weakvalue = (strchr(svalue(mode), 'v') != NULL);
- if (weakkey || weakvalue) { /* is really weak? */
- black2gray(obj2gco(h)); /* keep table gray */
- if (!weakkey) { /* strong keys? */
- traverseweakvalue(g, h);
- return TRAVCOST + sizenode(h);
- }
- else if (!weakvalue) { /* strong values? */
- traverseephemeron(g, h);
- return TRAVCOST + h->sizearray + sizenode(h);
- }
- else {
- linktable(h, &g->allweak); /* nothing to traverse now */
- return TRAVCOST;
- }
- } /* else go through */
+ if (mode && ttisstring(mode) && /* is there a weak mode? */
+ ((weakkey = strchr(svalue(mode), 'k')),
+ (weakvalue = strchr(svalue(mode), 'v')),
+ (weakkey || weakvalue))) { /* is really weak? */
+ black2gray(obj2gco(h)); /* keep table gray */
+ if (!weakkey) /* strong keys? */
+ traverseweakvalue(g, h);
+ else if (!weakvalue) /* strong values? */
+ traverseephemeron(g, h);
+ else /* all weak */
+ linktable(h, &g->allweak); /* nothing to traverse now */
}
- traversestrongtable(g, h);
- return TRAVCOST + h->sizearray + (2 * sizenode(h));
+ else /* not weak */
+ traversestrongtable(g, h);
+ return sizeof(Table) + sizeof(TValue) * h->sizearray +
+ sizeof(Node) * sizenode(h);
}
@@ -467,91 +462,101 @@ static int traverseproto (global_State *g, Proto *f) {
int i;
if (f->cache && iswhite(obj2gco(f->cache)))
f->cache = NULL; /* allow cache to be collected */
- stringmark(f->source);
+ markobject(g, f->source);
for (i = 0; i < f->sizek; i++) /* mark literals */
markvalue(g, &f->k[i]);
for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */
- stringmark(f->upvalues[i].name);
+ markobject(g, f->upvalues[i].name);
for (i = 0; i < f->sizep; i++) /* mark nested protos */
markobject(g, f->p[i]);
for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */
- stringmark(f->locvars[i].varname);
- return TRAVCOST + f->sizek + f->sizeupvalues + f->sizep + f->sizelocvars;
+ markobject(g, f->locvars[i].varname);
+ return sizeof(Proto) + sizeof(Instruction) * f->sizecode +
+ sizeof(Proto *) * f->sizep +
+ sizeof(TValue) * f->sizek +
+ sizeof(int) * f->sizelineinfo +
+ sizeof(LocVar) * f->sizelocvars +
+ sizeof(Upvaldesc) * f->sizeupvalues;
}
-static int traverseCclosure (global_State *g, CClosure *cl) {
+static lu_mem traverseCclosure (global_State *g, CClosure *cl) {
int i;
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
markvalue(g, &cl->upvalue[i]);
- return TRAVCOST + cl->nupvalues;
+ return sizeCclosure(cl->nupvalues);
}
-static int traverseLclosure (global_State *g, LClosure *cl) {
+static lu_mem traverseLclosure (global_State *g, LClosure *cl) {
int i;
- lua_assert(cl->nupvalues == cl->p->sizeupvalues);
markobject(g, cl->p); /* mark its prototype */
for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */
markobject(g, cl->upvals[i]);
- return TRAVCOST + cl->nupvalues;
+ return sizeLclosure(cl->nupvalues);
}
-static int traversestack (global_State *g, lua_State *L) {
- StkId o = L->stack;
+static lu_mem traversestack (global_State *g, lua_State *th) {
+ StkId o = th->stack;
if (o == NULL)
return 1; /* stack not completely built yet */
- for (; o < L->top; o++)
+ for (; o < th->top; o++)
markvalue(g, o);
if (g->gcstate == GCSatomic) { /* final traversal? */
- StkId lim = L->stack + L->stacksize; /* real end of stack */
+ StkId lim = th->stack + th->stacksize; /* real end of stack */
for (; o < lim; o++) /* clear not-marked stack slice */
setnilvalue(o);
}
- return TRAVCOST + cast_int(o - L->stack);
+ return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
}
/*
** traverse one gray object, turning it to black (except for threads,
** which are always gray).
-** Returns number of values traversed.
*/
-static int propagatemark (global_State *g) {
+static void propagatemark (global_State *g) {
+ lu_mem size;
GCObject *o = g->gray;
lua_assert(isgray(o));
gray2black(o);
switch (gch(o)->tt) {
case LUA_TTABLE: {
Table *h = gco2t(o);
- g->gray = h->gclist;
- return traversetable(g, h);
+ g->gray = h->gclist; /* remove from 'gray' list */
+ size = traversetable(g, h);
+ break;
}
case LUA_TLCL: {
LClosure *cl = gco2lcl(o);
- g->gray = cl->gclist;
- return traverseLclosure(g, cl);
+ g->gray = cl->gclist; /* remove from 'gray' list */
+ size = traverseLclosure(g, cl);
+ break;
}
case LUA_TCCL: {
CClosure *cl = gco2ccl(o);
- g->gray = cl->gclist;
- return traverseCclosure(g, cl);
+ g->gray = cl->gclist; /* remove from 'gray' list */
+ size = traverseCclosure(g, cl);
+ break;
}
case LUA_TTHREAD: {
lua_State *th = gco2th(o);
- g->gray = th->gclist;
+ g->gray = th->gclist; /* remove from 'gray' list */
th->gclist = g->grayagain;
- g->grayagain = o;
+ g->grayagain = o; /* insert into 'grayagain' list */
black2gray(o);
- return traversestack(g, th);
+ size = traversestack(g, th);
+ break;
}
case LUA_TPROTO: {
Proto *p = gco2p(o);
- g->gray = p->gclist;
- return traverseproto(g, p);
+ g->gray = p->gclist; /* remove from 'gray' list */
+ size = traverseproto(g, p);
+ break;
}
- default: lua_assert(0); return 0;
+ default: lua_assert(0); return;
}
+ g->GCmemtrav += size;
}
@@ -614,12 +619,12 @@ static void convergeephemerons (global_State *g) {
** clear entries with unmarked keys from all weaktables in list 'l' up
** to element 'f'
*/
-static void clearkeys (GCObject *l, GCObject *f) {
+static void clearkeys (global_State *g, GCObject *l, GCObject *f) {
for (; l != f; l = gco2t(l)->gclist) {
Table *h = gco2t(l);
Node *n, *limit = gnodelast(h);
for (n = gnode(h, 0); n < limit; n++) {
- if (!ttisnil(gval(n)) && (iscleared(gkey(n)))) {
+ if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(n); /* and remove entry from table */
}
@@ -632,18 +637,18 @@ static void clearkeys (GCObject *l, GCObject *f) {
** clear entries with unmarked values from all weaktables in list 'l' up
** to element 'f'
*/
-static void clearvalues (GCObject *l, GCObject *f) {
+static void clearvalues (global_State *g, GCObject *l, GCObject *f) {
for (; l != f; l = gco2t(l)->gclist) {
Table *h = gco2t(l);
Node *n, *limit = gnodelast(h);
int i;
for (i = 0; i < h->sizearray; i++) {
TValue *o = &h->array[i];
- if (iscleared(o)) /* value was collected? */
+ if (iscleared(g, o)) /* value was collected? */
setnilvalue(o); /* remove value */
}
for (n = gnode(h, 0); n < limit; n++) {
- if (!ttisnil(gval(n)) && iscleared(gval(n))) {
+ if (!ttisnil(gval(n)) && iscleared(g, gval(n))) {
setnilvalue(gval(n)); /* remove value ... */
removeentry(n); /* and remove entry from table */
}
@@ -713,7 +718,6 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
int ow = otherwhite(g);
int toclear, toset; /* bits to clear and to set in all live objects */
int tostop; /* stop sweep when this is true */
- l_mem debt = g->GCdebt; /* current debt */
if (isgenerational(g)) { /* generational mode? */
toclear = ~0; /* clear nothing */
toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */
@@ -732,20 +736,16 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {
freeobj(L, curr); /* erase 'curr' */
}
else {
+ if (testbits(marked, tostop))
+ return NULL; /* stop sweeping this list */
if (gch(curr)->tt == LUA_TTHREAD)
sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */
- if (testbits(marked, tostop)) {
- static GCObject *nullp = NULL;
- p = &nullp; /* stop sweeping this list */
- break;
- }
/* update marks */
gch(curr)->marked = cast_byte((marked & toclear) | toset);
p = &gch(curr)->next; /* go to next element */
}
}
- luaE_setdebt(g, debt); /* sweeping should not change debt */
- return p;
+ return (*p == NULL) ? NULL : p;
}
/* }====================================================== */
@@ -858,11 +858,18 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
return; /* nothing to be done */
else { /* move 'o' to 'finobj' list */
GCObject **p;
- for (p = &g->allgc; *p != o; p = &gch(*p)->next) ;
- *p = gch(o)->next; /* remove 'o' from root list */
- gch(o)->next = g->finobj; /* link it in list 'finobj' */
+ GCheader *ho = gch(o);
+ /* avoid removing current sweep object */
+ if (g->sweepgc == &ho->next) {
+ /* step to next object in the list */
+ g->sweepgc = (ho->next == NULL) ? NULL : &gch(ho->next)->next;
+ }
+ /* search for pointer pointing to 'o' */
+ for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ }
+ *p = ho->next; /* remove 'o' from root list */
+ ho->next = g->finobj; /* link it in list 'finobj' */
g->finobj = o;
- l_setbit(gch(o)->marked, SEPARATED); /* mark it as such */
+ l_setbit(ho->marked, SEPARATED); /* mark it as such */
resetoldbit(o); /* see MOVE OLD rule */
}
}
@@ -880,6 +887,24 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) {
#define sweepphases \
(bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep))
+
+/*
+** enter first sweep phase (strings) and prepare pointers for other
+** sweep phases. The calls to 'sweeplist' attempt to make pointers
+** point to an object inside the list (instead of to the header), so
+** that the real sweep do not need to skip objects created between "now"
+** and the start of the real sweep.
+*/
+static void entersweep (lua_State *L) {
+ global_State *g = G(L);
+ g->gcstate = GCSsweepstring;
+ lua_assert(g->sweepgc == NULL && g->sweepfin == NULL);
+ g->sweepstrgc = 0; /* prepare to sweep strings, ... */
+ g->sweepfin = sweeplist(L, &g->finobj, 1); /* finalizable objects, ... */
+ g->sweepgc = sweeplist(L, &g->allgc, 1); /* and regular objects */
+}
+
+
/*
** change GC mode
*/
@@ -889,15 +914,14 @@ void luaC_changemode (lua_State *L, int mode) {
if (mode == KGC_GEN) { /* change to generational mode */
/* make sure gray lists are consistent */
luaC_runtilstate(L, bitmask(GCSpropagate));
- g->lastmajormem = gettotalbytes(g);
+ g->GCestimate = gettotalbytes(g);
g->gckind = KGC_GEN;
}
else { /* change to incremental mode */
/* sweep all objects to turn them back to white
(as white has not changed, nothing extra will be collected) */
- g->sweepstrgc = 0;
- g->gcstate = GCSsweepstring;
g->gckind = KGC_NORMAL;
+ entersweep(L);
luaC_runtilstate(L, ~sweepphases);
}
}
@@ -946,8 +970,8 @@ static void atomic (lua_State *L) {
convergeephemerons(g);
/* at this point, all strongly accessible objects are marked. */
/* clear values from weak tables, before checking finalizers */
- clearvalues(g->weak, NULL);
- clearvalues(g->allweak, NULL);
+ clearvalues(g, g->weak, NULL);
+ clearvalues(g, g->allweak, NULL);
origweak = g->weak; origall = g->allweak;
separatetobefnz(L, 0); /* separate objects to be finalized */
markbeingfnz(g); /* mark userdata that will be finalized */
@@ -955,63 +979,64 @@ static void atomic (lua_State *L) {
convergeephemerons(g);
/* at this point, all resurrected objects are marked. */
/* remove dead objects from weak tables */
- clearkeys(g->ephemeron, NULL); /* clear keys from all ephemeron tables */
- clearkeys(g->allweak, NULL); /* clear keys from all allweak tables */
+ clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */
+ clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */
/* clear values from resurrected weak tables */
- clearvalues(g->weak, origweak);
- clearvalues(g->allweak, origall);
- g->sweepstrgc = 0; /* prepare to sweep strings */
- g->gcstate = GCSsweepstring;
+ clearvalues(g, g->weak, origweak);
+ clearvalues(g, g->allweak, origall);
g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */
+ entersweep(L); /* prepare to sweep strings */
/*lua_checkmemory(L);*/
}
-static l_mem singlestep (lua_State *L) {
+static lu_mem singlestep (lua_State *L) {
global_State *g = G(L);
switch (g->gcstate) {
case GCSpause: {
+ g->GCmemtrav = 0; /* start to count memory traversed */
if (!isgenerational(g))
markroot(g); /* start a new collection */
- /* in any case, root must be marked */
+ /* in any case, root must be marked at this point */
lua_assert(!iswhite(obj2gco(g->mainthread))
&& !iswhite(gcvalue(&g->l_registry)));
g->gcstate = GCSpropagate;
- return GCROOTCOST;
+ return g->GCmemtrav;
}
case GCSpropagate: {
- if (g->gray)
- return propagatemark(g);
+ if (g->gray) {
+ lu_mem oldtrav = g->GCmemtrav;
+ propagatemark(g);
+ return g->GCmemtrav - oldtrav; /* memory traversed in this step */
+ }
else { /* no more `gray' objects */
g->gcstate = GCSatomic; /* finish mark phase */
+ g->GCestimate = g->GCmemtrav; /* save what was counted */
atomic(L);
return GCATOMICCOST;
}
}
case GCSsweepstring: {
- if (g->sweepstrgc < g->strt.size) {
- sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);
- return GCSWEEPCOST;
- }
- else { /* no more strings to sweep */
- g->sweepgc = &g->finobj; /* prepare to sweep finalizable objects */
+ int i;
+ for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++)
+ sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]);
+ g->sweepstrgc += i;
+ if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */
g->gcstate = GCSsweepudata;
- return 0;
- }
+ return i * GCSWEEPCOST;
}
case GCSsweepudata: {
- if (*g->sweepgc) {
- g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
+ if (g->sweepfin) {
+ g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX);
return GCSWEEPMAX*GCSWEEPCOST;
}
else {
- g->sweepgc = &g->allgc; /* go to next phase */
g->gcstate = GCSsweep;
- return GCSWEEPCOST;
+ return 0;
}
}
case GCSsweep: {
- if (*g->sweepgc) {
+ if (g->sweepgc) {
g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);
return GCSWEEPMAX*GCSWEEPCOST;
}
@@ -1042,15 +1067,16 @@ void luaC_runtilstate (lua_State *L, int statesmask) {
static void generationalcollection (lua_State *L) {
global_State *g = G(L);
- if (g->lastmajormem == 0) { /* signal for another major collection? */
+ if (g->GCestimate == 0) { /* signal for another major collection? */
luaC_fullgc(L, 0); /* perform a full regular collection */
- g->lastmajormem = gettotalbytes(g); /* update control */
+ g->GCestimate = gettotalbytes(g); /* update control */
}
else {
+ lu_mem estimate = g->GCestimate;
luaC_runtilstate(L, ~bitmask(GCSpause)); /* run complete cycle */
luaC_runtilstate(L, bitmask(GCSpause));
- if (gettotalbytes(g) > g->lastmajormem/100 * g->gcmajorinc)
- g->lastmajormem = 0; /* signal for a major collection */
+ if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc)
+ g->GCestimate = 0; /* signal for a major collection */
}
luaE_setdebt(g, stddebt(g));
}
@@ -1058,27 +1084,31 @@ static void generationalcollection (lua_State *L) {
static void step (lua_State *L) {
global_State *g = G(L);
- l_mem lim = g->gcstepmul; /* how much to work */
+ l_mem debt = g->GCdebt;
+ int stepmul = g->gcstepmul;
+ if (stepmul <= 0) stepmul = 1;
do { /* always perform at least one single step */
- lim -= singlestep(L);
- } while (lim > 0 && g->gcstate != GCSpause);
- if (g->gcstate != GCSpause)
- luaE_setdebt(g, g->GCdebt - GCSTEPSIZE);
- else
- luaE_setdebt(g, stddebt(g));
+ lu_mem work = singlestep(L); /* do some work */
+ work = workrate(work, stepmul); /* apply work rate */
+ debt -= work;
+ } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause);
+ if (g->gcstate == GCSpause)
+ debt = stddebtest(g, g->GCestimate); /* pause until next cycle */
+ luaE_setdebt(g, debt);
}
/*
-** performs a basic GC step even if the collector is stopped
+** performs a basic GC step
*/
void luaC_forcestep (lua_State *L) {
global_State *g = G(L);
int i;
if (isgenerational(g)) generationalcollection(L);
else step(L);
- for (i = 0; i < GCFINALIZENUM && g->tobefnz; i++)
- GCTM(L, 1); /* Call a few pending finalizers */
+ /* run a few finalizers (or all of them at the end of a collect cycle) */
+ for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++)
+ GCTM(L, 1); /* call one finalizer */
}
@@ -1086,10 +1116,13 @@ void luaC_forcestep (lua_State *L) {
** performs a basic GC step only if collector is running
*/
void luaC_step (lua_State *L) {
- if (G(L)->gcrunning) luaC_forcestep(L);
+ global_State *g = G(L);
+ if (g->gcrunning) luaC_forcestep(L);
+ else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */
}
+
/*
** performs a full GC cycle; if "isemergency", does not call
** finalizers (which could change stack positions)
@@ -1097,16 +1130,19 @@ void luaC_step (lua_State *L) {
void luaC_fullgc (lua_State *L, int isemergency) {
global_State *g = G(L);
int origkind = g->gckind;
+ int someblack = keepinvariant(g);
lua_assert(origkind != KGC_EMERGENCY);
- if (!isemergency) /* do not run finalizers during emergency GC */
+ if (isemergency) /* do not run finalizers during emergency GC */
+ g->gckind = KGC_EMERGENCY;
+ else {
+ g->gckind = KGC_NORMAL;
callallpendingfinalizers(L, 1);
- if (keepinvariant(g)) { /* marking phase? */
+ }
+ if (someblack) { /* may there be some black objects? */
/* must sweep all objects to turn them back to white
(as white has not changed, nothing will be collected) */
- g->sweepstrgc = 0;
- g->gcstate = GCSsweepstring;
+ entersweep(L);
}
- g->gckind = isemergency ? KGC_EMERGENCY : KGC_NORMAL;
/* finish any pending sweep phase to start a new cycle */
luaC_runtilstate(L, bitmask(GCSpause));
/* run entire collector */
diff --git a/src/lgc.h b/src/lgc.h
index 04559303..bdd5cce6 100644
--- a/src/lgc.h
+++ b/src/lgc.h
@@ -1,5 +1,5 @@
/*
-** $Id: lgc.h,v 2.53 2012/01/23 20:29:12 roberto Exp $
+** $Id: lgc.h,v 2.56 2012/05/23 15:43:14 roberto Exp $
** Garbage Collector
** See Copyright Notice in lua.h
*/
@@ -20,13 +20,19 @@
** is that a black object can never point to a white one. Moreover,
** any gray object must be in a "gray list" (gray, grayagain, weak,
** allweak, ephemeron) so that it can be visited again before finishing
-** the collection cycle. (These rule does not apply to strings,
-** which are never black but do not need to be visited again.)
-** These lists have no meaning when the invariant is not being enforced
-** (e.g., sweep phase).
+** the collection cycle. These lists have no meaning when the invariant
+** is not being enforced (e.g., sweep phase).
*/
+
+/* how much to allocate before next GC step */
+#if !defined(GCSTEPSIZE)
+/* ~100 small strings */
+#define GCSTEPSIZE (cast_int(100 * sizeof(TString)))
+#endif
+
+
/*
** Possible states of the Garbage Collector
*/
diff --git a/src/llimits.h b/src/llimits.h
index 98f8fea0..6b2b4b9a 100644
--- a/src/llimits.h
+++ b/src/llimits.h
@@ -1,5 +1,5 @@
/*
-** $Id: llimits.h,v 1.96 2012/01/25 21:05:40 roberto Exp $
+** $Id: llimits.h,v 1.98 2012/05/11 14:10:50 roberto Exp $
** Limits, basic types, and some other `installation-dependent' definitions
** See Copyright Notice in lua.h
*/
@@ -125,15 +125,6 @@ typedef LUAI_UACNUMBER l_uacNumber;
/*
-** maximum length for short strings, that is, strings that are
-** internalized. (Cannot be smaller than reserved words or tags
-** for metamethods; #"function" = 8, #"__newindex" = 10; should
-** not be larger than 255, to allow future changes)
-*/
-#define LUA_MAXSHORTLEN (8 * sizeof(void*))
-
-
-/*
** type for virtual-machine instructions
** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)
*/
@@ -218,31 +209,36 @@ typedef lu_int32 Instruction;
#elif defined(LUA_IEEE754TRICK) /* }{ */
/* the next trick should work on any machine using IEEE754 with
- a 32-bit integer type */
+ a 32-bit int type */
union luai_Cast { double l_d; LUA_INT32 l_p[2]; };
#if !defined(LUA_IEEEENDIAN) /* { */
#define LUAI_EXTRAIEEE \
static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)};
-#define LUA_IEEEENDIAN (ieeeendian.l_p[1] == 33)
+#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33)
#else
+#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN
#define LUAI_EXTRAIEEE /* empty */
#endif /* } */
#define lua_number2int32(i,n,t) \
{ LUAI_EXTRAIEEE \
volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \
- (i) = (t)u.l_p[LUA_IEEEENDIAN]; }
+ (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; }
#define luai_hashnum(i,n) \
{ volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \
(i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */
#define lua_number2int(i,n) lua_number2int32(i, n, int)
-#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer)
#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned)
+/* the trick can be expanded to lua_Integer when it is a 32-bit value */
+#if defined(LUA_IEEELL)
+#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer)
+#endif
+
#endif /* } */
diff --git a/src/lmathlib.c b/src/lmathlib.c
index b17237f0..c3c605e8 100644
--- a/src/lmathlib.c
+++ b/src/lmathlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmathlib.c,v 1.80 2011/07/05 12:49:35 roberto Exp $
+** $Id: lmathlib.c,v 1.81 2012/05/18 17:47:53 roberto Exp $
** Standard mathematical library
** See Copyright Notice in lua.h
*/
@@ -17,17 +17,17 @@
#include "lualib.h"
-#undef PI
-#define PI (3.14159265358979323846)
-#define RADIANS_PER_DEGREE (PI/180.0)
-
-
/* macro 'l_tg' allows the addition of an 'l' or 'f' to all math operations */
#if !defined(l_tg)
#define l_tg(x) (x)
#endif
+#undef PI
+#define PI (l_tg(3.1415926535897932384626433832795))
+#define RADIANS_PER_DEGREE (PI/180.0)
+
+
static int math_abs (lua_State *L) {
lua_pushnumber(L, l_tg(fabs)(luaL_checknumber(L, 1)));
diff --git a/src/lmem.c b/src/lmem.c
index 792deb3c..3f88496e 100644
--- a/src/lmem.c
+++ b/src/lmem.c
@@ -1,5 +1,5 @@
/*
-** $Id: lmem.c,v 1.83 2011/11/30 12:42:49 roberto Exp $
+** $Id: lmem.c,v 1.84 2012/05/23 15:41:53 roberto Exp $
** Interface to Memory Manager
** See Copyright Notice in lua.h
*/
@@ -94,22 +94,6 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
}
lua_assert((nsize == 0) == (newblock == NULL));
g->GCdebt = (g->GCdebt + nsize) - realosize;
-#if defined(TRACEMEM)
- { /* auxiliary patch to monitor garbage collection.
- ** To plot, gnuplot with following command:
- ** plot TRACEMEM using 1:2 with lines, TRACEMEM using 1:3 with lines
- */
- static unsigned long total = 0; /* our "time" */
- static FILE *f = NULL; /* output file */
- total++; /* "time" always grows */
- if ((total % 200) == 0) {
- if (f == NULL) f = fopen(TRACEMEM, "w");
- fprintf(f, "%lu %u %d %d\n", total,
- gettotalbytes(g), g->GCdebt, g->gcstate * 10000);
- }
- }
-#endif
-
return newblock;
}
diff --git a/src/loadlib.c b/src/loadlib.c
index 783bc12b..ea332f44 100644
--- a/src/loadlib.c
+++ b/src/loadlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: loadlib.c,v 1.108 2011/12/12 16:34:03 roberto Exp $
+** $Id: loadlib.c,v 1.110 2012/04/26 19:38:52 roberto Exp $
** Dynamic library loader for Lua
** See Copyright Notice in lua.h
**
@@ -92,9 +92,9 @@
#define LUA_OFSEP "_"
-#define LIBPREFIX "LOADLIB: "
+/* table (in the registry) that keeps handles for all loaded C libraries */
+#define CLIBS "_CLIBS"
-#define POF LUA_POF
#define LIB_FAIL "open"
@@ -248,48 +248,54 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {
#endif
-
-static void **ll_register (lua_State *L, const char *path) {
- void **plib;
- lua_pushfstring(L, "%s%s", LIBPREFIX, path);
- lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */
- if (!lua_isnil(L, -1)) /* is there an entry? */
- plib = (void **)lua_touserdata(L, -1);
- else { /* no entry yet; create one */
- lua_pop(L, 1); /* remove result from gettable */
- plib = (void **)lua_newuserdata(L, sizeof(const void *));
- *plib = NULL;
- luaL_setmetatable(L, "_LOADLIB");
- lua_pushfstring(L, "%s%s", LIBPREFIX, path);
- lua_pushvalue(L, -2);
- lua_settable(L, LUA_REGISTRYINDEX);
- }
+static void *ll_checkclib (lua_State *L, const char *path) {
+ void *plib;
+ lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+ lua_getfield(L, -1, path);
+ plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */
+ lua_pop(L, 2); /* pop CLIBS table and 'plib' */
return plib;
}
+static void ll_addtoclib (lua_State *L, const char *path, void *plib) {
+ lua_getfield(L, LUA_REGISTRYINDEX, CLIBS);
+ lua_pushlightuserdata(L, plib);
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -3, path); /* CLIBS[path] = plib */
+ lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */
+ lua_pop(L, 1); /* pop CLIBS table */
+}
+
+
/*
-** __gc tag method: calls library's `ll_unloadlib' function with the lib
-** handle
+** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib
+** handles in list CLIBS
*/
static int gctm (lua_State *L) {
- void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB");
- if (*lib) ll_unloadlib(*lib);
- *lib = NULL; /* mark library as closed */
+ int n = luaL_len(L, 1);
+ for (; n >= 1; n--) { /* for each handle, in reverse order */
+ lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */
+ ll_unloadlib(lua_touserdata(L, -1));
+ lua_pop(L, 1); /* pop handle */
+ }
return 0;
}
static int ll_loadfunc (lua_State *L, const char *path, const char *sym) {
- void **reg = ll_register(L, path);
- if (*reg == NULL) *reg = ll_load(L, path, *sym == '*');
- if (*reg == NULL) return ERRLIB; /* unable to load library */
+ void *reg = ll_checkclib(L, path); /* check loaded C libraries */
+ if (reg == NULL) { /* must load library? */
+ reg = ll_load(L, path, *sym == '*');
+ if (reg == NULL) return ERRLIB; /* unable to load library */
+ ll_addtoclib(L, path, reg);
+ }
if (*sym == '*') { /* loading only library (no function)? */
lua_pushboolean(L, 1); /* return 'true' */
return 0; /* no errors */
}
else {
- lua_CFunction f = ll_sym(L, *reg, sym);
+ lua_CFunction f = ll_sym(L, reg, sym);
if (f == NULL)
return ERRFUNC; /* unable to find function */
lua_pushcfunction(L, f); /* else create new function */
@@ -418,12 +424,12 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) {
if (mark) {
int stat;
funcname = lua_pushlstring(L, modname, mark - modname);
- funcname = lua_pushfstring(L, POF"%s", funcname);
+ funcname = lua_pushfstring(L, LUA_POF"%s", funcname);
stat = ll_loadfunc(L, filename, funcname);
if (stat != ERRFUNC) return stat;
modname = mark + 1; /* else go ahead and try old-style name */
}
- funcname = lua_pushfstring(L, POF"%s", modname);
+ funcname = lua_pushfstring(L, LUA_POF"%s", modname);
return ll_loadfunc(L, filename, funcname);
}
@@ -666,18 +672,10 @@ static const luaL_Reg ll_funcs[] = {
};
-static const lua_CFunction searchers[] =
- {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
-
-
-LUAMOD_API int luaopen_package (lua_State *L) {
+static void createsearcherstable (lua_State *L) {
+ static const lua_CFunction searchers[] =
+ {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL};
int i;
- /* create new type _LOADLIB */
- luaL_newmetatable(L, "_LOADLIB");
- lua_pushcfunction(L, gctm);
- lua_setfield(L, -2, "__gc");
- /* create `package' table */
- luaL_newlib(L, pk_funcs);
/* create 'searchers' table */
lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0);
/* fill it with pre-defined searchers */
@@ -686,6 +684,19 @@ LUAMOD_API int luaopen_package (lua_State *L) {
lua_pushcclosure(L, searchers[i], 1);
lua_rawseti(L, -2, i+1);
}
+}
+
+
+LUAMOD_API int luaopen_package (lua_State *L) {
+ /* create table CLIBS to keep track of loaded C libraries */
+ luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS);
+ lua_createtable(L, 0, 1); /* metatable for CLIBS */
+ lua_pushcfunction(L, gctm);
+ lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */
+ lua_setmetatable(L, -2);
+ /* create `package' table */
+ luaL_newlib(L, pk_funcs);
+ createsearcherstable(L);
#if defined(LUA_COMPAT_LOADERS)
lua_pushvalue(L, -1); /* make a copy of 'searchers' table */
lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */
diff --git a/src/lobject.h b/src/lobject.h
index 20dd44d4..ca75a028 100644
--- a/src/lobject.h
+++ b/src/lobject.h
@@ -1,5 +1,5 @@
/*
-** $Id: lobject.h,v 2.68 2012/01/25 21:05:40 roberto Exp $
+** $Id: lobject.h,v 2.70 2012/05/11 14:10:50 roberto Exp $
** Type definitions for Lua objects
** See Copyright Notice in lua.h
*/
@@ -236,11 +236,6 @@ typedef struct lua_TValue TValue;
val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \
checkliveness(G(L),io); }
-#define setptvalue(L,obj,x) \
- { TValue *io=(obj); \
- val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TPROTO)); \
- checkliveness(G(L),io); }
-
#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY)
@@ -271,6 +266,8 @@ typedef struct lua_TValue TValue;
#define setsvalue2n setsvalue
+/* check whether a number is valid (useful only for NaN trick) */
+#define luai_checknum(L,o,c) { /* empty */ }
/*
@@ -278,10 +275,7 @@ typedef struct lua_TValue TValue;
** NaN Trick
** =======================================================
*/
-
-#if defined(LUA_NANTRICK) \
- || defined(LUA_NANTRICK_LE) \
- || defined(LUA_NANTRICK_BE)
+#if defined(LUA_NANTRICK)
/*
** numbers are represented in the 'd_' field. All other values have the
@@ -289,15 +283,23 @@ typedef struct lua_TValue TValue;
** a "signaled NaN", which is never generated by regular operations by
** the CPU (nor by 'strtod')
*/
-#if !defined(NNMARK)
+
+/* allows for external implementation for part of the trick */
+#if !defined(NNMARK) /* { */
+
+
+#if !defined(LUA_IEEEENDIAN)
+#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN'
+#endif
+
+
#define NNMARK 0x7FF7A500
#define NNMASK 0x7FFFFF00
-#endif
#undef TValuefields
#undef NILCONSTANT
-#if defined(LUA_NANTRICK_LE)
+#if (LUA_IEEEENDIAN == 0) /* { */
/* little endian */
#define TValuefields \
@@ -308,7 +310,7 @@ typedef struct lua_TValue TValue;
#define d_(o) ((o)->u.d__)
#define tt_(o) ((o)->u.i.tt__)
-#elif defined(LUA_NANTRICK_BE)
+#else /* }{ */
/* big endian */
#define TValuefields \
@@ -319,10 +321,9 @@ typedef struct lua_TValue TValue;
#define d_(o) ((o)->u.d__)
#define tt_(o) ((o)->u.i.tt__)
-#elif !defined(TValuefields)
-#error option 'LUA_NANTRICK' needs declaration for 'TValuefields'
+#endif /* } */
-#endif
+#endif /* } */
/* correspondence with standard representation */
@@ -372,14 +373,9 @@ typedef struct lua_TValue TValue;
(ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2)))
-
+#undef luai_checknum
#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; }
-
-#else
-
-#define luai_checknum(L,o,c) { /* empty */ }
-
#endif
/* }====================================================== */
diff --git a/src/lopcodes.c b/src/lopcodes.c
index 2e346766..ef736927 100644
--- a/src/lopcodes.c
+++ b/src/lopcodes.c
@@ -1,5 +1,6 @@
/*
-** $Id: lopcodes.c,v 1.48 2011/04/19 16:22:13 roberto Exp $
+** $Id: lopcodes.c,v 1.49 2012/05/14 13:34:18 roberto Exp $
+** Opcodes for Lua virtual machine
** See Copyright Notice in lua.h
*/
diff --git a/src/loslib.c b/src/loslib.c
index 881667da..489755b6 100644
--- a/src/loslib.c
+++ b/src/loslib.c
@@ -1,5 +1,5 @@
/*
-** $Id: loslib.c,v 1.38 2011/11/30 12:35:05 roberto Exp $
+** $Id: loslib.c,v 1.39 2012/05/23 15:37:09 roberto Exp $
** Standard Operating System library
** See Copyright Notice in lua.h
*/
@@ -26,11 +26,12 @@
#if !defined(LUA_STRFTIMEOPTIONS)
#if !defined(LUA_USE_POSIX)
-#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
+#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" }
#else
-#define LUA_STRFTIMEOPTIONS { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "", \
- "E", "cCxXyY", \
- "O", "deHImMSuUVwWy" }
+#define LUA_STRFTIMEOPTIONS \
+ { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \
+ "", "E", "cCxXyY", \
+ "O", "deHImMSuUVwWy" }
#endif
#endif
@@ -43,7 +44,7 @@
*/
#if defined(LUA_USE_MKSTEMP)
#include <unistd.h>
-#define LUA_TMPNAMBUFSIZE 32
+#define LUA_TMPNAMBUFSIZE 32
#define lua_tmpnam(b,e) { \
strcpy(b, "/tmp/lua_XXXXXX"); \
e = mkstemp(b); \
@@ -52,8 +53,8 @@
#elif !defined(lua_tmpnam)
-#define LUA_TMPNAMBUFSIZE L_tmpnam
-#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
+#define LUA_TMPNAMBUFSIZE L_tmpnam
+#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); }
#endif
diff --git a/src/lparser.c b/src/lparser.c
index ac4093cc..b3eb3ca9 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.c,v 2.125 2012/01/23 23:05:18 roberto Exp $
+** $Id: lparser.c,v 2.128 2012/05/20 14:51:23 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -493,21 +493,30 @@ static void leaveblock (FuncState *fs) {
/*
-** adds prototype being created into its parent list of prototypes
-** and codes instruction to create new closure
+** adds a new prototype into list of prototypes
*/
-static void codeclosure (LexState *ls, Proto *clp, expdesc *v) {
- FuncState *fs = ls->fs->prev;
- Proto *f = fs->f; /* prototype of function creating new closure */
+static Proto *addprototype (LexState *ls) {
+ Proto *clp;
+ lua_State *L = ls->L;
+ FuncState *fs = ls->fs;
+ Proto *f = fs->f; /* prototype of current function */
if (fs->np >= f->sizep) {
int oldsize = f->sizep;
- luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,
- MAXARG_Bx, "functions");
+ luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions");
while (oldsize < f->sizep) f->p[oldsize++] = NULL;
}
- f->p[fs->np++] = clp;
- luaC_objbarrier(ls->L, f, clp);
- init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));
+ f->p[fs->np++] = clp = luaF_newproto(L);
+ luaC_objbarrier(L, f, clp);
+ return clp;
+}
+
+
+/*
+** codes instruction to create new closure in parent function
+*/
+static void codeclosure (LexState *ls, expdesc *v) {
+ FuncState *fs = ls->fs->prev;
+ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1));
luaK_exp2nextreg(fs, v); /* fix it at stack top (for GC) */
}
@@ -529,13 +538,9 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
fs->nactvar = 0;
fs->firstlocal = ls->dyd->actvar.n;
fs->bl = NULL;
- f = luaF_newproto(L);
- fs->f = f;
+ f = fs->f;
f->source = ls->source;
f->maxstacksize = 2; /* registers 0/1 are always valid */
- /* anchor prototype (to avoid being collected) */
- setptvalue2s(L, L->top, f);
- incr_top(L);
fs->h = luaH_new(L);
/* anchor table of constants (to avoid being collected) */
sethvalue2s(L, L->top, fs->h);
@@ -568,20 +573,6 @@ static void close_func (LexState *ls) {
anchor_token(ls);
L->top--; /* pop table of constants */
luaC_checkGC(L);
- L->top--; /* pop prototype (after possible collection) */
-}
-
-
-/*
-** opens the main function, which is a regular vararg function with an
-** upvalue named LUA_ENV
-*/
-static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) {
- expdesc v;
- open_func(ls, fs, bl);
- fs->f->is_vararg = 1; /* main function is always vararg */
- init_exp(&v, VLOCAL, 0);
- newupvalue(fs, ls->envn, &v); /* create environment upvalue */
}
@@ -795,8 +786,9 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
/* body -> `(' parlist `)' block END */
FuncState new_fs;
BlockCnt bl;
- open_func(ls, &new_fs, &bl);
+ new_fs.f = addprototype(ls);
new_fs.f->linedefined = line;
+ open_func(ls, &new_fs, &bl);
checknext(ls, '(');
if (ismethod) {
new_localvarliteral(ls, "self"); /* create 'self' parameter */
@@ -807,7 +799,7 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
statlist(ls);
new_fs.f->lastlinedefined = ls->linenumber;
check_match(ls, TK_END, TK_FUNCTION, line);
- codeclosure(ls, new_fs.f, e);
+ codeclosure(ls, e);
close_func(ls);
}
@@ -879,8 +871,8 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
*/
-static void prefixexp (LexState *ls, expdesc *v) {
- /* prefixexp -> NAME | '(' expr ')' */
+static void primaryexp (LexState *ls, expdesc *v) {
+ /* primaryexp -> NAME | '(' expr ')' */
switch (ls->t.token) {
case '(': {
int line = ls->linenumber;
@@ -901,12 +893,12 @@ static void prefixexp (LexState *ls, expdesc *v) {
}
-static void primaryexp (LexState *ls, expdesc *v) {
- /* primaryexp ->
- prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
+static void suffixedexp (LexState *ls, expdesc *v) {
+ /* suffixedexp ->
+ primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
FuncState *fs = ls->fs;
int line = ls->linenumber;
- prefixexp(ls, v);
+ primaryexp(ls, v);
for (;;) {
switch (ls->t.token) {
case '.': { /* fieldsel */
@@ -941,7 +933,7 @@ static void primaryexp (LexState *ls, expdesc *v) {
static void simpleexp (LexState *ls, expdesc *v) {
/* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... |
- constructor | FUNCTION body | primaryexp */
+ constructor | FUNCTION body | suffixedexp */
switch (ls->t.token) {
case TK_NUMBER: {
init_exp(v, VKNUM, 0);
@@ -981,7 +973,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
return;
}
default: {
- primaryexp(ls, v);
+ suffixedexp(ls, v);
return;
}
}
@@ -1141,10 +1133,10 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
expdesc e;
check_condition(ls, vkisvar(lh->v.k), "syntax error");
- if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */
+ if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */
struct LHS_assign nv;
nv.prev = lh;
- primaryexp(ls, &nv.v);
+ suffixedexp(ls, &nv.v);
if (nv.v.k != VINDEXED)
check_conflict(ls, lh, &nv.v);
checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS,
@@ -1210,6 +1202,13 @@ static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) {
}
+/* skip no-op statements */
+static void skipnoopstat (LexState *ls) {
+ while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
+ statement(ls);
+}
+
+
static void labelstat (LexState *ls, TString *label, int line) {
/* label -> '::' NAME '::' */
FuncState *fs = ls->fs;
@@ -1219,9 +1218,7 @@ static void labelstat (LexState *ls, TString *label, int line) {
checknext(ls, TK_DBCOLON); /* skip double colon */
/* create new entry for this label */
l = newlabelentry(ls, ll, label, line, fs->pc);
- /* skip other no-op statements */
- while (ls->t.token == ';' || ls->t.token == TK_DBCOLON)
- statement(ls);
+ skipnoopstat(ls); /* skip other no-op statements */
if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */
/* assume that locals are already out of scope */
ll->arr[l].nactvar = fs->bl->nactvar;
@@ -1384,6 +1381,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
gotostat(ls, v.t); /* handle goto/break */
+ skipnoopstat(ls); /* skip other no-op statements */
if (block_follow(ls, 0)) { /* 'goto' is the entire block? */
leaveblock(fs);
return; /* and that is it */
@@ -1480,13 +1478,15 @@ static void exprstat (LexState *ls) {
/* stat -> func | assignment */
FuncState *fs = ls->fs;
struct LHS_assign v;
- primaryexp(ls, &v.v);
- if (v.v.k == VCALL) /* stat -> func */
- SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
- else { /* stat -> assignment */
+ suffixedexp(ls, &v.v);
+ if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */
v.prev = NULL;
assignment(ls, &v, 1);
}
+ else { /* stat -> func */
+ check_condition(ls, v.v.k == VCALL, "syntax error");
+ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */
+ }
}
@@ -1594,27 +1594,42 @@ static void statement (LexState *ls) {
/* }====================================================================== */
-Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar) {
+/*
+** compiles the main function, which is a regular vararg function with an
+** upvalue named LUA_ENV
+*/
+static void mainfunc (LexState *ls, FuncState *fs) {
+ BlockCnt bl;
+ expdesc v;
+ open_func(ls, fs, &bl);
+ fs->f->is_vararg = 1; /* main function is always vararg */
+ init_exp(&v, VLOCAL, 0); /* create and... */
+ newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */
+ luaX_next(ls); /* read first token */
+ statlist(ls); /* parse main body */
+ check(ls, TK_EOS);
+ close_func(ls);
+}
+
+
+Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ Dyndata *dyd, const char *name, int firstchar) {
LexState lexstate;
FuncState funcstate;
- BlockCnt bl;
- TString *tname = luaS_new(L, name);
- setsvalue2s(L, L->top, tname); /* push name to protect it */
+ Closure *cl = luaF_newLclosure(L, 1); /* create main closure */
+ /* anchor closure (to avoid being collected) */
+ setclLvalue(L, L->top, cl);
incr_top(L);
+ funcstate.f = cl->l.p = luaF_newproto(L);
+ funcstate.f->source = luaS_new(L, name); /* create and anchor TString */
lexstate.buff = buff;
lexstate.dyd = dyd;
dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
- luaX_setinput(L, &lexstate, z, tname, firstchar);
- open_mainfunc(&lexstate, &funcstate, &bl);
- luaX_next(&lexstate); /* read first token */
- statlist(&lexstate); /* main body */
- check(&lexstate, TK_EOS);
- close_func(&lexstate);
- L->top--; /* pop name */
+ luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar);
+ mainfunc(&lexstate, &funcstate);
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
/* all scopes should be correctly finished */
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0);
- return funcstate.f;
+ return cl; /* it's on the stack too */
}
diff --git a/src/lparser.h b/src/lparser.h
index caabf46c..301167d4 100644
--- a/src/lparser.h
+++ b/src/lparser.h
@@ -1,5 +1,5 @@
/*
-** $Id: lparser.h,v 1.69 2011/07/27 18:09:01 roberto Exp $
+** $Id: lparser.h,v 1.70 2012/05/08 13:53:33 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -112,8 +112,8 @@ typedef struct FuncState {
} FuncState;
-LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
- Dyndata *dyd, const char *name, int firstchar);
+LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
+ Dyndata *dyd, const char *name, int firstchar);
#endif
diff --git a/src/lstate.c b/src/lstate.c
index e3aec6a3..1a165003 100644
--- a/src/lstate.c
+++ b/src/lstate.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.c,v 2.93 2012/02/01 21:57:15 roberto Exp $
+** $Id: lstate.c,v 2.97 2012/05/23 15:37:09 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -39,7 +39,7 @@
#endif
-#define MEMERRMSG "not enough memory"
+#define MEMERRMSG "not enough memory"
/*
@@ -48,7 +48,7 @@
*/
#if !defined(luai_makeseed)
#include <time.h>
-#define luai_makeseed(L) cast(size_t, time(NULL))
+#define luai_makeseed() cast(size_t, time(NULL))
#endif
@@ -280,7 +280,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->uvhead.u.l.prev = &g->uvhead;
g->uvhead.u.l.next = &g->uvhead;
g->gcrunning = 0; /* no GC while building state */
- g->lastmajormem = 0;
+ g->GCestimate = 0;
g->strt.size = 0;
g->strt.nuse = 0;
g->strt.hash = NULL;
@@ -292,6 +292,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->allgc = NULL;
g->finobj = NULL;
g->tobefnz = NULL;
+ g->sweepgc = g->sweepfin = NULL;
g->gray = g->grayagain = NULL;
g->weak = g->ephemeron = g->allweak = NULL;
g->totalbytes = sizeof(LG);
diff --git a/src/lstate.h b/src/lstate.h
index 1691ed92..936afc2d 100644
--- a/src/lstate.h
+++ b/src/lstate.h
@@ -1,5 +1,5 @@
/*
-** $Id: lstate.h,v 2.77 2012/02/01 21:57:15 roberto Exp $
+** $Id: lstate.h,v 2.80 2012/05/22 17:50:39 roberto Exp $
** Global State
** See Copyright Notice in lua.h
*/
@@ -113,7 +113,8 @@ typedef struct global_State {
void *ud; /* auxiliary data to `frealloc' */
lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */
l_mem GCdebt; /* bytes allocated not yet compensated by the collector */
- lu_mem lastmajormem; /* memory in use after last major collection */
+ lu_mem GCmemtrav; /* memory traversed by the GC */
+ lu_mem GCestimate; /* an estimate of the non-garbage memory in use */
stringtable strt; /* hash table for strings */
TValue l_registry;
unsigned int seed; /* randomized seed for hashes */
@@ -124,7 +125,8 @@ typedef struct global_State {
int sweepstrgc; /* position of sweep in `strt' */
GCObject *allgc; /* list of all collectable objects */
GCObject *finobj; /* list of collectable objects with finalizers */
- GCObject **sweepgc; /* current position of sweep */
+ GCObject **sweepgc; /* current position of sweep in list 'allgc' */
+ GCObject **sweepfin; /* current position of sweep in list 'finobj' */
GCObject *gray; /* list of gray objects */
GCObject *grayagain; /* list of objects to be traversed atomically */
GCObject *weak; /* list of tables with weak values */
diff --git a/src/lstring.c b/src/lstring.c
index d89ac8f2..8b959f19 100644
--- a/src/lstring.c
+++ b/src/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 2.22 2012/02/01 21:57:15 roberto Exp $
+** $Id: lstring.c,v 2.24 2012/05/11 14:14:42 roberto Exp $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -19,12 +19,23 @@
/*
+** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
+** compute its hash
+*/
+#if !defined(LUAI_HASHLIMIT)
+#define LUAI_HASHLIMIT 5
+#endif
+
+
+/*
** equality for long strings
*/
int luaS_eqlngstr (TString *a, TString *b) {
size_t len = a->tsv.len;
lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR);
- return (len == b->tsv.len) && (memcmp(getstr(a), getstr(b), len) == 0);
+ return (a == b) || /* same instance or... */
+ ((len == b->tsv.len) && /* equal length and ... */
+ (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
}
@@ -40,8 +51,9 @@ int luaS_eqstr (TString *a, TString *b) {
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
unsigned int h = seed ^ l;
size_t l1;
- for (l1 = 0; l1 < l; l1++)
- h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1]));
+ size_t step = (l >> LUAI_HASHLIMIT) + 1;
+ for (l1 = l; l1 >= step; l1 -= step)
+ h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1]));
return h;
}
@@ -142,7 +154,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
** new string (with explicit length)
*/
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
- if (l <= LUA_MAXSHORTLEN) /* short string? */
+ if (l <= LUAI_MAXSHORTLEN) /* short string? */
return internshrstr(L, str, l);
else {
if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
diff --git a/src/lstrlib.c b/src/lstrlib.c
index f5d61fd8..e13098bb 100644
--- a/src/lstrlib.c
+++ b/src/lstrlib.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstrlib.c,v 1.173 2011/11/30 18:24:56 roberto Exp $
+** $Id: lstrlib.c,v 1.176 2012/05/23 15:37:09 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -30,7 +30,7 @@
/* macro to `unsign' a character */
-#define uchar(c) ((unsigned char)(c))
+#define uchar(c) ((unsigned char)(c))
@@ -119,7 +119,9 @@ static int str_rep (lua_State *L) {
char *p = luaL_buffinitsize(L, &b, totallen);
while (n-- > 1) { /* first n-1 copies (followed by separator) */
memcpy(p, s, l * sizeof(char)); p += l;
- memcpy(p, sep, lsep * sizeof(char)); p += lsep;
+ if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */
+ memcpy(p, sep, lsep * sizeof(char)); p += lsep;
+ }
}
memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */
luaL_pushresultsize(&b, totallen);
@@ -745,20 +747,17 @@ static int str_gsub (lua_State *L) {
#if !defined(LUA_INTFRMLEN) /* { */
#if defined(LUA_USE_LONGLONG)
-#define LUA_INTFRMLEN "ll"
-#define LUA_INTFRM_T long long
+#define LUA_INTFRMLEN "ll"
+#define LUA_INTFRM_T long long
#else
-#define LUA_INTFRMLEN "l"
-#define LUA_INTFRM_T long
+#define LUA_INTFRMLEN "l"
+#define LUA_INTFRM_T long
#endif
#endif /* } */
-#define MAX_UINTFRM ((lua_Number)(~(unsigned LUA_INTFRM_T)0))
-#define MAX_INTFRM ((lua_Number)((~(unsigned LUA_INTFRM_T)0)/2))
-#define MIN_INTFRM (-(lua_Number)((~(unsigned LUA_INTFRM_T)0)/2) - 1)
/*
** LUA_FLTFRMLEN is the length modifier for float conversions in
@@ -767,8 +766,8 @@ static int str_gsub (lua_State *L) {
*/
#if !defined(LUA_FLTFRMLEN)
-#define LUA_FLTFRMLEN ""
-#define LUA_FLTFRM_T double
+#define LUA_FLTFRMLEN ""
+#define LUA_FLTFRM_T double
#endif
@@ -870,18 +869,22 @@ static int str_format (lua_State *L) {
}
case 'd': case 'i': {
lua_Number n = luaL_checknumber(L, arg);
- luaL_argcheck(L, (MIN_INTFRM - 1) < n && n < (MAX_INTFRM + 1), arg,
+ LUA_INTFRM_T ni = (LUA_INTFRM_T)n;
+ lua_Number diff = n - (lua_Number)ni;
+ luaL_argcheck(L, -1 < diff && diff < 1, arg,
"not a number in proper range");
addlenmod(form, LUA_INTFRMLEN);
- nb = sprintf(buff, form, (LUA_INTFRM_T)n);
+ nb = sprintf(buff, form, ni);
break;
}
case 'o': case 'u': case 'x': case 'X': {
lua_Number n = luaL_checknumber(L, arg);
- luaL_argcheck(L, 0 <= n && n < (MAX_UINTFRM + 1), arg,
+ unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n;
+ lua_Number diff = n - (lua_Number)ni;
+ luaL_argcheck(L, -1 < diff && diff < 1, arg,
"not a non-negative number in proper range");
addlenmod(form, LUA_INTFRMLEN);
- nb = sprintf(buff, form, (unsigned LUA_INTFRM_T)n);
+ nb = sprintf(buff, form, ni);
break;
}
case 'e': case 'E': case 'f':
diff --git a/src/ltable.c b/src/ltable.c
index 7f28e808..ffa5ecb3 100644
--- a/src/ltable.c
+++ b/src/ltable.c
@@ -1,5 +1,5 @@
/*
-** $Id: ltable.c,v 2.70 2012/02/01 21:57:15 roberto Exp $
+** $Id: ltable.c,v 2.71 2012/05/23 15:37:09 roberto Exp $
** Lua tables (hash)
** See Copyright Notice in lua.h
*/
@@ -48,10 +48,10 @@
#define MAXASIZE (1 << MAXBITS)
-#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
+#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t))))
#define hashstr(t,str) hashpow2(t, (str)->tsv.hash)
-#define hashboolean(t,p) hashpow2(t, p)
+#define hashboolean(t,p) hashpow2(t, p)
/*
diff --git a/src/lua.c b/src/lua.c
index e20ab86d..7614c703 100644
--- a/src/lua.c
+++ b/src/lua.c
@@ -1,5 +1,5 @@
/*
-** $Id: lua.c,v 1.203 2011/12/12 16:34:03 roberto Exp $
+** $Id: lua.c,v 1.205 2012/05/23 15:37:09 roberto Exp $
** Lua stand-alone interpreter
** See Copyright Notice in lua.h
*/
@@ -45,13 +45,13 @@
*/
#if defined(LUA_USE_ISATTY)
#include <unistd.h>
-#define lua_stdin_is_tty() isatty(0)
+#define lua_stdin_is_tty() isatty(0)
#elif defined(LUA_WIN)
#include <io.h>
#include <stdio.h>
-#define lua_stdin_is_tty() _isatty(_fileno(stdin))
+#define lua_stdin_is_tty() _isatty(_fileno(stdin))
#else
-#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
+#define lua_stdin_is_tty() 1 /* assume stdin is a tty */
#endif
@@ -66,19 +66,19 @@
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
-#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
+#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)
#define lua_saveline(L,idx) \
if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \
add_history(lua_tostring(L, idx)); /* add it to history */
-#define lua_freeline(L,b) ((void)L, free(b))
+#define lua_freeline(L,b) ((void)L, free(b))
#elif !defined(lua_readline)
-#define lua_readline(L,b,p) \
+#define lua_readline(L,b,p) \
((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \
fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */
-#define lua_saveline(L,idx) { (void)L; (void)idx; }
-#define lua_freeline(L,b) { (void)L; (void)b; }
+#define lua_saveline(L,idx) { (void)L; (void)idx; }
+#define lua_freeline(L,b) { (void)L; (void)b; }
#endif
@@ -223,16 +223,11 @@ static int dostring (lua_State *L, const char *s, const char *name) {
static int dolibrary (lua_State *L, const char *name) {
int status;
- lua_pushglobaltable(L);
- lua_getfield(L, -1, "require");
+ lua_getglobal(L, "require");
lua_pushstring(L, name);
- status = docall(L, 1, 1);
- if (status == LUA_OK) {
- lua_setfield(L, -2, name); /* global[name] = require return */
- lua_pop(L, 1); /* remove global table */
- }
- else
- lua_remove(L, -2); /* remove global table (below error msg.) */
+ status = docall(L, 1, 1); /* call 'require(name)' */
+ if (status == LUA_OK)
+ lua_setglobal(L, name); /* global[name] = require return */
return report(L, status);
}
diff --git a/src/lua.h b/src/lua.h
index 49d24b94..a3a3a70c 100644
--- a/src/lua.h
+++ b/src/lua.h
@@ -1,5 +1,5 @@
/*
-** $Id: lua.h,v 1.282 2011/11/29 15:55:08 roberto Exp $
+** $Id: lua.h,v 1.283 2012/04/20 13:18:26 roberto Exp $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@@ -19,11 +19,11 @@
#define LUA_VERSION_MAJOR "5"
#define LUA_VERSION_MINOR "2"
#define LUA_VERSION_NUM 502
-#define LUA_VERSION_RELEASE "0" " (work1)"
+#define LUA_VERSION_RELEASE "1"
#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE
-#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2011 Lua.org, PUC-Rio"
+#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2012 Lua.org, PUC-Rio"
#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes"
@@ -413,7 +413,7 @@ struct lua_Debug {
/******************************************************************************
-* Copyright (C) 1994-2011 Lua.org, PUC-Rio. All rights reserved.
+* Copyright (C) 1994-2012 Lua.org, PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
diff --git a/src/luaconf.h b/src/luaconf.h
index bab401e9..e4335df9 100644
--- a/src/luaconf.h
+++ b/src/luaconf.h
@@ -1,5 +1,5 @@
/*
-** $Id: luaconf.h,v 1.170 2011/12/06 16:58:36 roberto Exp $
+** $Id: luaconf.h,v 1.172 2012/05/11 14:14:42 roberto Exp $
** Configuration file for Lua
** See Copyright Notice in lua.h
*/
@@ -223,6 +223,13 @@
(fprintf(stderr, (s), (p)), fflush(stderr))
+/*
+@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is,
+** strings that are internalized. (Cannot be smaller than reserved words
+** or tags for metamethods, as these strings must be internalized;
+** #("function") = 8, #("__newindex") = 10.)
+*/
+#define LUAI_MAXSHORTLEN 40
@@ -453,66 +460,76 @@
#define LUA_UNSIGNED unsigned LUA_INT32
-#if defined(LUA_CORE) /* { */
-#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
+/*
+** Some tricks with doubles
+*/
-/* On a Microsoft compiler on a Pentium, use assembler to avoid clashes
- with a DirectX idiosyncrasy */
+#if defined(LUA_CORE) && \
+ defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
+/*
+** The next definitions activate some tricks to speed up the
+** conversion from doubles to integer types, mainly to LUA_UNSIGNED.
+**
+@@ MS_ASMTRICK uses Microsoft assembler to avoid clashes with a
+** DirectX idiosyncrasy.
+**
+@@ LUA_IEEE754TRICK uses a trick that should work on any machine
+** using IEEE754 with a 32-bit integer type.
+**
+@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be
+** defined when LUA_INTEGER is a 32-bit integer.
+**
+@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
+** (0 for little endian, 1 for big endian); if not defined, Lua will
+** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK).
+**
+@@ LUA_NANTRICK controls the use of a trick to pack all types into
+** a single double value, using NaN values to represent non-number
+** values. The trick only works on 32-bit machines (ints and pointers
+** are 32-bit values) with numbers represented as IEEE 754-2008 doubles
+** with conventional endianess (12345678 or 87654321), in CPUs that do
+** not produce signaling NaN values (all NaNs are quiet).
+*/
+
+/* Microsoft compiler on a Pentium (32 bit) ? */
#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */
#define MS_ASMTRICK
+#define LUA_IEEEENDIAN 0
+#define LUA_NANTRICK
-#else /* }{ */
-/* the next definition uses a trick that should work on any machine
- using IEEE754 with a 32-bit integer type */
-
-#define LUA_IEEE754TRICK
-
-/*
-@@ LUA_IEEEENDIAN is the endianness of doubles in your machine
-** (0 for little endian, 1 for big endian); if not defined, Lua will
-** check it dynamically.
-*/
-/* check for known architectures */
-#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
- defined (__x86_64)
-#define LUA_IEEEENDIAN 0
-#elif defined(__POWERPC__) || defined(__ppc__)
-#define LUA_IEEEENDIAN 1
-#endif
-#endif /* } */
+/* pentium 32 bits? */
+#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */
-#endif /* } */
+#define LUA_IEEE754TRICK
+#define LUA_IEEELL
+#define LUA_IEEEENDIAN 0
+#define LUA_NANTRICK
-#endif /* } */
+/* pentium 64 bits? */
+#elif defined(__x86_64) /* }{ */
-/* }================================================================== */
+#define LUA_IEEE754TRICK
+#define LUA_IEEEENDIAN 0
+#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */
-/*
-@@ LUA_NANTRICK_LE/LUA_NANTRICK_BE controls the use of a trick to
-** pack all types into a single double value, using NaN values to
-** represent non-number values. The trick only works on 32-bit machines
-** (ints and pointers are 32-bit values) with numbers represented as
-** IEEE 754-2008 doubles with conventional endianess (12345678 or
-** 87654321), in CPUs that do not produce signaling NaN values (all NaNs
-** are quiet).
-*/
-#if defined(LUA_CORE) && \
- defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */
+#define LUA_IEEE754TRICK
+#define LUA_IEEEENDIAN 1
-/* little-endian architectures that satisfy those conditions */
-#if defined(__i386__) || defined(__i386) || defined(__X86__) || \
- defined(_M_IX86)
+#else /* }{ */
-#define LUA_NANTRICK_LE
+/* assume IEEE754 and a 32-bit integer type */
+#define LUA_IEEE754TRICK
-#endif
+#endif /* } */
#endif /* } */
+/* }================================================================== */
+
diff --git a/src/lundump.c b/src/lundump.c
index c2173daf..54de011a 100644
--- a/src/lundump.c
+++ b/src/lundump.c
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.c,v 1.72 2012/03/21 18:11:35 lhf Exp $
+** $Id: lundump.c,v 2.22 2012/05/08 13:53:33 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -39,7 +39,7 @@ static l_noret error(LoadState* S, const char* why)
#define LoadVector(S,b,n,size) LoadMem(S,b,n,size)
#if !defined(luai_verifycode)
-#define luai_verifycode(L,b,f) (f)
+#define luai_verifycode(L,b,f) /* empty */
#endif
static void LoadBlock(LoadState* S, void* b, size_t size)
@@ -91,7 +91,7 @@ static void LoadCode(LoadState* S, Proto* f)
LoadVector(S,f->code,n,sizeof(Instruction));
}
-static Proto* LoadFunction(LoadState* S);
+static void LoadFunction(LoadState* S, Proto* f);
static void LoadConstants(LoadState* S, Proto* f)
{
@@ -125,7 +125,11 @@ static void LoadConstants(LoadState* S, Proto* f)
f->p=luaM_newvector(S->L,n,Proto*);
f->sizep=n;
for (i=0; i<n; i++) f->p[i]=NULL;
- for (i=0; i<n; i++) f->p[i]=LoadFunction(S);
+ for (i=0; i<n; i++)
+ {
+ f->p[i]=luaF_newproto(S->L);
+ LoadFunction(S,f->p[i]);
+ }
}
static void LoadUpvalues(LoadState* S, Proto* f)
@@ -164,10 +168,8 @@ static void LoadDebug(LoadState* S, Proto* f)
for (i=0; i<n; i++) f->upvalues[i].name=LoadString(S);
}
-static Proto* LoadFunction(LoadState* S)
+static void LoadFunction(LoadState* S, Proto* f)
{
- Proto* f=luaF_newproto(S->L);
- setptvalue2s(S->L,S->L->top,f); incr_top(S->L);
f->linedefined=LoadInt(S);
f->lastlinedefined=LoadInt(S);
f->numparams=LoadByte(S);
@@ -177,8 +179,6 @@ static Proto* LoadFunction(LoadState* S)
LoadConstants(S,f);
LoadUpvalues(S,f);
LoadDebug(S,f);
- S->L->top--;
- return f;
}
/* the code below must be consistent with the code in luaU_header */
@@ -203,9 +203,10 @@ static void LoadHeader(LoadState* S)
/*
** load precompiled chunk
*/
-Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
+Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
{
LoadState S;
+ Closure* cl;
if (*name=='@' || *name=='=')
S.name=name+1;
else if (*name==LUA_SIGNATURE[0])
@@ -216,7 +217,19 @@ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)
S.Z=Z;
S.b=buff;
LoadHeader(&S);
- return luai_verifycode(L,buff,LoadFunction(&S));
+ cl=luaF_newLclosure(L,1);
+ setclLvalue(L,L->top,cl); incr_top(L);
+ cl->l.p=luaF_newproto(L);
+ LoadFunction(&S,cl->l.p);
+ if (cl->l.p->sizeupvalues != 1)
+ {
+ Proto* p=cl->l.p;
+ cl=luaF_newLclosure(L,cl->l.p->sizeupvalues);
+ cl->l.p=p;
+ setclLvalue(L,L->top-1,cl);
+ }
+ luai_verifycode(L,buff,cl->l.p);
+ return cl;
}
#define MYINT(s) (s[0]-'0')
diff --git a/src/lundump.h b/src/lundump.h
index b63993ff..2b8accec 100644
--- a/src/lundump.h
+++ b/src/lundump.h
@@ -1,5 +1,5 @@
/*
-** $Id: lundump.h,v 1.44 2011/05/06 13:35:17 lhf Exp $
+** $Id: lundump.h,v 1.39 2012/05/08 13:53:33 roberto Exp $
** load precompiled Lua chunks
** See Copyright Notice in lua.h
*/
@@ -11,7 +11,7 @@
#include "lzio.h"
/* load one chunk; from lundump.c */
-LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
+LUAI_FUNC Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);
/* make header; from lundump.c */
LUAI_FUNC void luaU_header (lu_byte* h);
diff --git a/src/lvm.c b/src/lvm.c
index cb8d76ae..accc7c08 100644
--- a/src/lvm.c
+++ b/src/lvm.c
@@ -1,5 +1,5 @@
/*
-** $Id: lvm.c,v 2.149 2012/01/25 21:05:40 roberto Exp $
+** $Id: lvm.c,v 2.151 2012/05/14 17:50:49 roberto Exp $
** Lua virtual machine
** See Copyright Notice in lua.h
*/
@@ -395,7 +395,8 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base,
int nup = p->sizeupvalues;
Upvaldesc *uv = p->upvalues;
int i;
- Closure *ncl = luaF_newLclosure(L, p);
+ Closure *ncl = luaF_newLclosure(L, nup);
+ ncl->l.p = p;
setclLvalue(L, ra, ncl); /* anchor new closure in stack */
for (i = 0; i < nup; i++) { /* fill in its upvalues */
if (uv[i].instack) /* upvalue refers to local variable? */
@@ -501,7 +502,11 @@ void luaV_finishOp (lua_State *L) {
#define Protect(x) { {x;}; base = ci->u.l.base; }
-#define checkGC(L,c) Protect(luaC_condGC(L, c); luai_threadyield(L);)
+#define checkGC(L,c) \
+ Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \
+ luaC_step(L); \
+ L->top = ci->top;}) /* restore top */ \
+ luai_threadyield(L); )
#define arith_op(op,tm) { \
@@ -594,11 +599,7 @@ void luaV_execute (lua_State *L) {
sethvalue(L, ra, t);
if (b != 0 || c != 0)
luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));
- checkGC(L,
- L->top = ra + 1; /* limit of live values */
- luaC_step(L);
- L->top = ci->top; /* restore top */
- )
+ checkGC(L, ra + 1);
)
vmcase(OP_SELF,
StkId rb = RB(i);
@@ -650,10 +651,7 @@ void luaV_execute (lua_State *L) {
ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */
rb = b + base;
setobjs2s(L, ra, rb);
- checkGC(L,
- L->top = (ra >= rb ? ra + 1 : rb); /* limit of live values */
- luaC_step(L);
- )
+ checkGC(L, (ra >= rb ? ra + 1 : rb));
L->top = ci->top; /* restore top */
)
vmcase(OP_JMP,
@@ -831,11 +829,7 @@ void luaV_execute (lua_State *L) {
pushclosure(L, p, cl->upvals, base, ra); /* create a new one */
else
setclLvalue(L, ra, ncl); /* push cashed closure */
- checkGC(L,
- L->top = ra + 1; /* limit of live values */
- luaC_step(L);
- L->top = ci->top; /* restore top */
- )
+ checkGC(L, ra + 1);
)
vmcase(OP_VARARG,
int b = GETARG_B(i) - 1;
diff --git a/src/lzio.c b/src/lzio.c
index 354f94e7..8b77054e 100644
--- a/src/lzio.c
+++ b/src/lzio.c
@@ -1,6 +1,6 @@
/*
-** $Id: lzio.c,v 1.34 2011/07/15 12:35:32 roberto Exp $
-** a generic input stream interface
+** $Id: lzio.c,v 1.35 2012/05/14 13:34:18 roberto Exp $
+** Buffered streams
** See Copyright Notice in lua.h
*/