Lua diffu-lua-5.4.0-work1-work2


Makefile

@@ -36,7 +36,7 @@
 # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
 
 # Convenience platforms targets.
-PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
+PLATS= aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris
 
 # What to install.
 TO_BIN= lua luac

README

@@ -1,5 +1,5 @@
 
-This is Lua 5.4.0 (work1), released on 13 Mar 2018.
+This is Lua 5.4.0 (work2), released on 18 Jun 2018.
 
 For installation instructions, license details, and
 further information about Lua, see doc/readme.html.

doc/contents.html

@@ -32,7 +32,7 @@
 
 <P>
 <SMALL>
-Copyright &copy; 2015&ndash;2018 Lua.org, PUC-Rio.
+Copyright &copy; 2018 Lua.org, PUC-Rio.
 Freely available under the terms of the
 <A HREF="http://www.lua.org/license.html">Lua license</A>.
 </SMALL>

@@ -49,8 +49,8 @@
 <LI><A HREF="manual.html#2.4">2.4 &ndash; Metatables and Metamethods</A>
 <LI><A HREF="manual.html#2.5">2.5 &ndash; Garbage Collection</A>
 <UL>
-<LI><A HREF="manual.html#2.5.1">2.5.1 &ndash; The incremental GC</A>
-<LI><A HREF="manual.html#2.5.2">2.5.2 &ndash; The generational GC</A>
+<LI><A HREF="manual.html#2.5.1">2.5.1 &ndash; Incremental Garbage Collection</A>
+<LI><A HREF="manual.html#2.5.2">2.5.2 &ndash; Generational Garbage Collection</A>
 <LI><A HREF="manual.html#2.5.3">2.5.3 &ndash; Garbage-Collection Metamethods</A>
 <LI><A HREF="manual.html#2.5.4">2.5.4 &ndash; Weak Tables</A>
 </UL>

@@ -611,10 +611,10 @@
 
 <P CLASS="footer">
 Last update:
-Mon Mar 12 21:52:24 -03 2018
+Mon Jun 18 17:11:17 -03 2018
 </P>
 <!--
-Last change: revised for Lua 5.4.0 (work1)
+Last change: revised for Lua 5.4.0 (work2)
 -->
 
 </BODY>

doc/manual.html

@@ -19,7 +19,7 @@
 
 <P>
 <SMALL>
-Copyright &copy; 2015&ndash;2018 Lua.org, PUC-Rio.
+Copyright &copy; 2018 Lua.org, PUC-Rio.
 Freely available under the terms of the
 <a href="http://www.lua.org/license.html">Lua license</a>.
 </SMALL>

@@ -35,7 +35,7 @@
 <!-- ====================================================================== -->
 <p>
 
-<!-- $Id: manual.of,v 1.172 2018/03/12 14:26:44 roberto Exp roberto $ -->
+<!-- $Id: manual.of,v 1.175 2018/06/18 19:17:35 roberto Exp $ -->
 
 
 

@@ -114,7 +114,7 @@
 <h2>2.1 &ndash; <a name="2.1">Values and Types</a></h2>
 
 <p>
-Lua is a <em>dynamically typed language</em>.
+Lua is a dynamically typed language.
 This means that
 variables do not have types; only values do.
 There are no type definitions in the language.

@@ -122,7 +122,7 @@
 
 
 <p>
-All values in Lua are <em>first-class values</em>.
+All values in Lua are first-class values.
 This means that all values can be stored in variables,
 passed as arguments to other functions, and returned as results.
 

@@ -719,7 +719,7 @@
 
 
 
-<h3>2.5.1 &ndash; <a name="2.5.1">The incremental GC</a></h3>
+<h3>2.5.1 &ndash; <a name="2.5.1">Incremental Garbage Collection</a></h3>
 
 <p>
 In incremental mode,

@@ -777,7 +777,7 @@
 
 
 
-<h3>2.5.2 &ndash; <a name="2.5.2">The generational GC</a></h3>
+<h3>2.5.2 &ndash; <a name="2.5.2">Generational Garbage Collection</a></h3>
 
 <p>
 In generational mode,

@@ -1196,8 +1196,9 @@
 
 
 <p>
-We can specify any byte in a short literal string by its numeric value
-(including embedded zeros).
+We can specify any byte in a short literal string,
+including embedded zeros,
+by its numeric value.
 This can be done
 with the escape sequence <code>\x<em>XX</em></code>,
 where <em>XX</em> is a sequence of exactly two hexadecimal digits,

@@ -1577,9 +1578,9 @@
 <p>
 The condition expression of a
 control structure can return any value.
-Both <b>false</b> and <b>nil</b> are considered false.
-All values different from <b>nil</b> and <b>false</b> are considered true
-(in particular, the number 0 and the empty string are also true).
+Both <b>false</b> and <b>nil</b> test false.
+All values different from <b>nil</b> and <b>false</b> test true.
+(In particular, the number 0 and the empty string also test true).
 
 
 <p>

@@ -1942,14 +1943,14 @@
 the arithmetic operators work as follows:
 If both operands are integers,
 the operation is performed over integers and the result is an integer.
-Otherwise, if both operands are numbers
-or strings that can be converted to
-numbers (see <a href="#3.4.3">&sect;3.4.3</a>),
+Otherwise, if both operands are numbers,
 then they are converted to floats,
 the operation is performed following the usual rules
 for floating-point arithmetic
 (usually the IEEE 754 standard),
 and the result is a float.
+(The string library coerces strings to numbers in
+arithmetic operations; see <a href="#3.4.3">&sect;3.4.3</a> for details.)
 
 
 <p>

@@ -2018,8 +2019,7 @@
 Exponentiation and float division
 always convert integer operands to floats.
 All other arithmetic operations applied to mixed numbers
-(integers and floats) convert the integer operand to a float;
-this is called the <em>usual rule</em>.
+(integers and floats) convert the integer operand to a float.
 The C API also converts both integers to floats and
 floats to integers, as needed.
 Moreover, string concatenation accepts numbers as arguments,

@@ -2100,14 +2100,14 @@
 A closure is always equal to itself.
 Closures with any detectable difference
 (different behavior, different definition) are always different.
-Closures created at different times but no detectable differences
+Closures created at different times but with no detectable differences
 may be classified as equal or not
 (depending on internal cashing details).
 
 
 <p>
 You can change the way that Lua compares tables and userdata
-by using the "eq" metamethod (see <a href="#2.4">&sect;2.4</a>).
+by using the <code>__eq</code> metamethod (see <a href="#2.4">&sect;2.4</a>).
 
 
 <p>

@@ -2129,7 +2129,7 @@
 (regardless of their subtypes).
 Otherwise, if both arguments are strings,
 then their values are compared according to the current locale.
-Otherwise, Lua tries to call the "lt" or the "le"
+Otherwise, Lua tries to call the <code>__lt</code> or the <code>__le</code>
 metamethod (see <a href="#2.4">&sect;2.4</a>).
 A comparison <code>a &gt; b</code> is translated to <code>b &lt; a</code>
 and <code>a &gt;= b</code> is translated to <code>b &lt;= a</code>.

@@ -2174,10 +2174,7 @@
      false and nil       --&gt; false
      false or nil        --&gt; nil
      10 and 20           --&gt; 20
-</pre><p>
-(In this manual,
-<code>--&gt;</code> indicates the result of the preceding expression.)
-
+</pre>
 
 
 

@@ -2363,7 +2360,7 @@
 If the value of prefixexp has type <em>function</em>,
 then this function is called
 with the given arguments.
-Otherwise, the prefixexp "call" metamethod is called,
+Otherwise, the prefixexp <code>__call</code> metamethod is called,
 having as first argument the value of prefixexp,
 followed by the original call arguments
 (see <a href="#2.4">&sect;2.4</a>).

@@ -2666,7 +2663,8 @@
 
 <p>
 As in most C&nbsp;libraries,
-the Lua API functions do not check their arguments for validity or consistency.
+the Lua API functions do not check their arguments
+for validity or consistency.
 However, you can change this behavior by compiling Lua
 with the macro <a name="pdf-LUA_USE_APICHECK"><code>LUA_USE_APICHECK</code></a> defined.
 

@@ -2796,6 +2794,8 @@
 within the space allocated for the stack,
 that is, indices up to the stack size.
 (Note that 0 is never an acceptable index.)
+Indices to upvalues (see <a href="#4.4">&sect;4.4</a>) larger than the real number
+of upvalues in the current C&nbsp;function are also acceptable (but invalid).
 Except when noted otherwise,
 functions in the API work with acceptable indices.
 

@@ -2844,6 +2844,10 @@
 produces an acceptable but invalid index.
 
 
+<p>
+A C&nbsp;closure can also change the values of its corresponding upvalues.
+
+
 
 
 

@@ -3122,11 +3126,11 @@
 tells whether the function may raise errors:
 '<code>-</code>' means the function never raises any error;
 '<code>m</code>' means the function may raise out-of-memory errors
-and errors running a <code>__gc</code> metamethod;
+and errors running a finalizer;
+'<code>v</code>' means the function may raise the errors explained in the text;
 '<code>e</code>' means the function may raise any errors
-(it can run arbitrary Lua code,
-either directly or through metamethods);
-'<code>v</code>' means the function may raise an error on purpose.
+(because it can run arbitrary Lua code,
+either directly or through metamethods).
 
 
 

@@ -3275,15 +3279,13 @@
 <pre>void lua_call (lua_State *L, int nargs, int nresults);</pre>
 
 <p>
-Calls a function
-(or a callable object, that is,
-an object with a <code>__call</code> metamethod).
+Calls a function.
 
 
 <p>
-To call a function you must use the following protocol:
-first, the function to be called is pushed onto the stack;
-then, the arguments to the function are pushed
+To do a call you must use the following protocol:
+first, the value to be called is pushed onto the stack;
+then, the arguments to the call are pushed
 in direct order;
 that is, the first argument is pushed first.
 Finally you call <a href="#lua_call"><code>lua_call</code></a>;

@@ -3304,6 +3306,8 @@
 <p>
 Any error while calling and running the function is propagated upwards
 (with a <code>longjmp</code>).
+Like regular Lua calls,
+this function respects the <code>__call</code> metamethod.
 
 
 <p>

@@ -3571,7 +3575,7 @@
 
 
 <hr><h3><a name="lua_gc"><code>lua_gc</code></a></h3><p>
-<span class="apii">[-0, +0, <em>m</em>]</span>
+<span class="apii">[-0, +0, <em>v</em>]</span>
 <pre>int lua_gc (lua_State *L, int what, int data);</pre>
 
 <p>

@@ -3626,13 +3630,15 @@
 (i.e., not stopped).
 </li>
 
-</ul>
-
-<p>
+</ul><p>
 For more details about these options,
 see <a href="#pdf-collectgarbage"><code>collectgarbage</code></a>.
 
 
+<p>
+This function may raise errors when calling finalizers.
+
+
 
 
 

@@ -4186,7 +4192,7 @@
 
 
 <hr><h3><a name="lua_next"><code>lua_next</code></a></h3><p>
-<span class="apii">[-1, +(2|0), <em>e</em>]</span>
+<span class="apii">[-1, +(2|0), <em>v</em>]</span>
 <pre>int lua_next (lua_State *L, int index);</pre>
 
 <p>

@@ -4223,6 +4229,8 @@
 
 
 <p>
+This function may raise an error if the given key
+is neither <b>nil</b> nor present in the table.
 See function <a href="#pdf-next"><code>next</code></a> for the caveats of modifying
 the table during its traversal.
 

@@ -4389,6 +4397,17 @@
 
 <p>
 Pushes a new C&nbsp;closure onto the stack.
+This function receives a pointer to a C&nbsp;function
+and pushes onto the stack a Lua value of type <code>function</code> that,
+when called, invokes the corresponding C&nbsp;function.
+The parameter <code>n</code> tells how many upvalues this function will have
+(see <a href="#4.4">&sect;4.4</a>).
+
+
+<p>
+Any function to be callable by Lua must
+follow the correct protocol to receive its parameters
+and return its results (see <a href="#lua_CFunction"><code>lua_CFunction</code></a>).
 
 
 <p>

@@ -4426,40 +4445,26 @@
 
 <p>
 Pushes a C&nbsp;function onto the stack.
-This function receives a pointer to a C&nbsp;function
-and pushes onto the stack a Lua value of type <code>function</code> that,
-when called, invokes the corresponding C&nbsp;function.
-
-
-<p>
-Any function to be callable by Lua must
-follow the correct protocol to receive its parameters
-and return its results (see <a href="#lua_CFunction"><code>lua_CFunction</code></a>).
 
 
 
 
 
 <hr><h3><a name="lua_pushfstring"><code>lua_pushfstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>e</em>]</span>
+<span class="apii">[-0, +1, <em>v</em>]</span>
 <pre>const char *lua_pushfstring (lua_State *L, const char *fmt, ...);</pre>
 
 <p>
 Pushes onto the stack a formatted string
 and returns a pointer to this string.
 It is similar to the ISO&nbsp;C function <code>sprintf</code>,
-but has some important differences:
-
-<ul>
-
-<li>
-You do not have to allocate space for the result:
+but has two important differences.
+First,
+you do not have to allocate space for the result;
 the result is a Lua string and Lua takes care of memory allocation
 (and deallocation, through garbage collection).
-</li>
-
-<li>
-The conversion specifiers are quite restricted.
+Second,
+the conversion specifiers are quite restricted.
 There are no flags, widths, or precisions.
 The conversion specifiers can only be
 '<code>%%</code>' (inserts the character '<code>%</code>'),

@@ -4470,14 +4475,11 @@
 '<code>%d</code>' (inserts an <code>int</code>),
 '<code>%c</code>' (inserts an <code>int</code> as a one-byte character), and
 '<code>%U</code>' (inserts a <code>long int</code> as a UTF-8 byte sequence).
-</li>
 
-</ul>
 
 <p>
-Unlike other push functions,
-this function checks for the stack space it needs,
-including the slot for its result.
+This function may raise errors due to memory overflow
+or an invalid conversion specifier.
 
 
 

@@ -4629,7 +4631,7 @@
 
 
 <hr><h3><a name="lua_pushvfstring"><code>lua_pushvfstring</code></a></h3><p>
-<span class="apii">[-0, +1, <em>m</em>]</span>
+<span class="apii">[-0, +1, <em>v</em>]</span>
 <pre>const char *lua_pushvfstring (lua_State *L,
                               const char *fmt,
                               va_list argp);</pre>

@@ -5349,16 +5351,10 @@
 
 <hr><h3><a name="lua_version"><code>lua_version</code></a></h3><p>
 <span class="apii">[-0, +0, &ndash;]</span>
-<pre>const lua_Number *lua_version (lua_State *L);</pre>
+<pre>lua_Number lua_version (lua_State *L);</pre>
 
 <p>
-Returns the address of the version number
-(a C static variable)
-stored in the Lua core.
-When called with a valid <a href="#lua_State"><code>lua_State</code></a>,
-returns the address of the version used to create that state.
-When called with <code>NULL</code>,
-returns the address of the version running the call.
+Returns the version number of this core.
 
 
 

@@ -5406,7 +5402,7 @@
 
 
 <hr><h3><a name="lua_yield"><code>lua_yield</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>v</em>]</span>
 <pre>int lua_yield (lua_State *L, int nresults);</pre>
 
 <p>

@@ -5423,7 +5419,7 @@
 
 
 <hr><h3><a name="lua_yieldk"><code>lua_yieldk</code></a></h3><p>
-<span class="apii">[-?, +?, <em>e</em>]</span>
+<span class="apii">[-?, +?, <em>v</em>]</span>
 <pre>int lua_yieldk (lua_State *L,
                 int nresults,
                 lua_KContext ctx,

@@ -5472,9 +5468,10 @@
 
 <p>
 This function can raise an error if it is called from a thread
-with a pending C call with no continuation function,
+with a pending C call with no continuation function
+(what is called a <em>C-call boundary</em>,
 or it is called from a thread that is not running inside a resume
-(e.g., the main thread).
+(typically the main thread).
 
 
 

@@ -5508,8 +5505,8 @@
   unsigned char nparams;      /* (u) number of parameters */
   char isvararg;              /* (u) */
   char istailcall;            /* (t) */
-  unsigned short fTransfer;   /* (r) index of first value transfered */
-  unsigned short nTransfer;   /* (r) number of transfered values */
+  unsigned short ftransfer;   /* (r) index of first value transferred */
+  unsigned short ntransfer;   /* (r) number of transferred values */
   char short_src[LUA_IDSIZE]; /* (S) */
   /* private part */
   <em>other fields</em>

@@ -5605,15 +5602,20 @@
 (always true for C&nbsp;functions).
 </li>
 
-<li><b><code>fTransfer</code>: </b>
-the index of the first local variable being "transfered",
-which means parameters in a call or return values in a return.
-This value is only meaningful during a call hook or a return hook.
+<li><b><code>ftransfer</code>: </b>
+the index on the stack of the first value being "transferred",
+that is, parameters in a call or return values in a return.
+(The other values are in consecutive indices.)
+Using this index, you can access and modify these values
+through <a href="#lua_getlocal"><code>lua_getlocal</code></a> and <a href="#lua_setlocal"><code>lua_setlocal</code></a>.
+This field is only meaningful during a
+call hook, denoting the first parameter,
+or a return hook, denoting the first value being returned.
 (For call hooks, this value is always 1.)
 </li>
 
-<li><b><code>nTransfer</code>: </b>
-The number of values being transfered (see previous item).
+<li><b><code>ntransfer</code>: </b>
+The number of values being transferred (see previous item).
 (For calls of Lua functions,
 this value is always equal to <code>nparams</code>.)
 </li>

@@ -5657,7 +5659,7 @@
 
 
 <hr><h3><a name="lua_getinfo"><code>lua_getinfo</code></a></h3><p>
-<span class="apii">[-(0|1), +(0|1|2), <em>e</em>]</span>
+<span class="apii">[-(0|1), +(0|1|2), <em>m</em>]</span>
 <pre>int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);</pre>
 
 <p>

@@ -5672,7 +5674,7 @@
 
 
 <p>
-To get information about a function you push it onto the stack
+To get information about a function, you push it onto the stack
 and start the <code>what</code> string with the character '<code>&gt;</code>'.
 (In that case,
 <code>lua_getinfo</code> pops the function from the top of the stack.)

@@ -5727,13 +5729,16 @@
 <p>
 If this option is given together with option '<code>f</code>',
 its table is pushed after the function.
+
+
+<p>
+This is the only option that can raise a memory error.
 </li>
 
 </ul>
 
 <p>
-This function returns 0 on error
-(for instance, an invalid option in <code>what</code>).
+This function returns 0 if given an invalid option in <code>what</code>.
 
 
 

@@ -5744,8 +5749,8 @@
 <pre>const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);</pre>
 
 <p>
-Gets information about a local variable of
-a given activation record or a given function.
+Gets information about a local variable or a temporary value
+of a given activation record or a given function.
 
 
 <p>

@@ -6448,19 +6453,15 @@
 <pre>void luaL_checkversion (lua_State *L);</pre>
 
 <p>
-Checks whether the core running the call,
-the core that created the Lua state,
-and the code making the call are all using the same version of Lua.
-Also checks whether the core running the call
-and the core that created the Lua state
-are using the same address space.
+Checks whether the code making the call and the Lua library being called
+are using the same version of Lua and the same numeric types.
 
 
 
 
 
 <hr><h3><a name="luaL_dofile"><code>luaL_dofile</code></a></h3><p>
-<span class="apii">[-0, +?, <em>e</em>]</span>
+<span class="apii">[-0, +?, <em>m</em>]</span>
 <pre>int luaL_dofile (lua_State *L, const char *filename);</pre>
 
 <p>

@@ -6550,7 +6551,7 @@
 
 <p>
 Pushes onto the stack the field <code>e</code> from the metatable
-of the object at index <code>obj</code> and returns the type of pushed value.
+of the object at index <code>obj</code> and returns the type of the pushed value.
 If the object does not have a metatable,
 or if the metatable does not have this field,
 pushes nothing and returns <code>LUA_TNIL</code>.

@@ -6564,9 +6565,9 @@
 <pre>int luaL_getmetatable (lua_State *L, const char *tname);</pre>
 
 <p>
-Pushes onto the stack the metatable associated with name <code>tname</code>
-in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>)
-(<b>nil</b> if there is no metatable associated with that name).
+Pushes onto the stack the metatable associated with the name <code>tname</code>
+in the registry (see <a href="#luaL_newmetatable"><code>luaL_newmetatable</code></a>),
+or <b>nil</b> if there is no metatable associated with that name.
 Returns the type of the pushed value.
 
 

@@ -6824,7 +6825,7 @@
 
 
 <hr><h3><a name="luaL_opt"><code>luaL_opt</code></a></h3><p>
-<span class="apii">[-0, +0, <em>e</em>]</span>
+<span class="apii">[-0, +0, &ndash;]</span>
 <pre>T luaL_opt (L, func, arg, dflt);</pre>
 
 <p>

@@ -9240,8 +9241,7 @@
 <code>list[pos+1], list[pos+2], &middot;&middot;&middot;, list[#list]</code>
 and erases element <code>list[#list]</code>;
 The index <code>pos</code> can also be 0 when <code>#list</code> is 0,
-or <code>#list + 1</code>;
-in those cases, the function erases the element <code>list[pos]</code>.
+or <code>#list + 1</code>.
 
 
 <p>

@@ -9530,19 +9530,42 @@
 When called with two integers <code>m</code> and <code>n</code>,
 <code>math.random</code> returns a pseudo-random integer
 with uniform distribution in the range <em>[m, n]</em>.
-The call <code>math.random(n)</code> is equivalent to <code>math.random(1,n)</code>.
+The call <code>math.random(n)</code>, for a positive <code>n</code>,
+is equivalent to <code>math.random(1,n)</code>.
+The call <code>math.random(0)</code> produces an integer with
+all bits (pseudo)random.
+
+
+<p>
+Lua initializes its pseudo-random generator with
+a weak attempt for ``randomness'',
+so that <code>math.random</code> should generate
+different sequences of results each time the program runs.
+To ensure a required level of randomness to the initial state
+(or contrarily, to have a deterministic sequence,
+for instance when debugging a program),
+you should call <a href="#pdf-math.randomseed"><code>math.randomseed</code></a> explicitly.
+
+
+<p>
+The results from this function have good statistical qualities,
+but they are not cryptographically secure.
+(For instance, there are no garanties that it is hard
+to predict future results based on the observation of
+some number of previous results.)
 
 
 
 
 <p>
-<hr><h3><a name="pdf-math.randomseed"><code>math.randomseed (x)</code></a></h3>
+<hr><h3><a name="pdf-math.randomseed"><code>math.randomseed (x [, y])</code></a></h3>
 
 
 <p>
-Sets <code>x</code> as the "seed"
+Sets <code>x</code> and <code>y</code> as the "seed"
 for the pseudo-random generator:
 equal seeds produce equal sequences of numbers.
+The default for <code>y</code> is zero.
 
 
 

@@ -10881,14 +10904,15 @@
 <ul>
 
 <li>
-The coersion of strings to numbers in
+The coercion of strings to numbers in
 arithmetic and bitwise operations
 has been removed from the core language.
-The string library does a similar job for arithmetic operations
+The string library does a similar job
+for arithmetic (but not for bitwise) operations
 using the string metamethods.
 However, unlike in previous versions,
 the new implementation preserves the implicit type of the numeral
-inside the string.
+in the string.
 For instance, the result of <code>"1" + "2"</code> now is an integer,
 not a float.
 </li>

@@ -10902,6 +10926,9 @@
 <ul>
 
 <li>
+The pseudo-random number generator used by the function <a href="#pdf-math.random"><code>math.random</code></a>
+now starts with a somewhat random seed.
+Moreover, it uses a different algorithm.
 </li>
 
 </ul>

@@ -10936,6 +10963,15 @@
 those values were the entire stack.)
 </li>
 
+<li>
+The function <a href="#lua_version"><code>lua_version</code></a> returns the version number,
+instead of an address of the version number.
+(The Lua core should work correctly with libraries using their
+own static copies of the same core,
+so there is no need to check whether they are using the same
+address space.)
+</li>
+
 </ul>
 
 

@@ -11034,10 +11070,10 @@
 
 <P CLASS="footer">
 Last update:
-Mon Mar 12 21:47:51 -03 2018
+Mon Jun 18 17:05:33 -03 2018
 </P>
 <!--
-Last change: revised for Lua 5.4.0 (work1)
+Last change: revised for Lua 5.4.0 (work2)
 -->
 
 </body></html>

doc/readme.html

@@ -47,7 +47,7 @@
 
 <H2><A NAME="about">About Lua</A></H2>
 <P>
-Lua is a powerful, fast, lightweight, embeddable scripting language
+Lua is a powerful, efficient, lightweight, embeddable scripting language
 developed by a
 <A HREF="http://www.lua.org/authors.html">team</A>
 at

@@ -55,7 +55,9 @@
 the Pontifical Catholic University of Rio de Janeiro in Brazil.
 Lua is
 <A HREF="#license">free software</A>
-used in many products and projects around the world.
+used in
+<A HREF="http://www.lua.org/uses.html">many products and projects</A>
+around the world.
 
 <P>
 Lua's

@@ -85,7 +87,8 @@
 Lua is implemented in pure ANSI C and compiles unmodified in all known
 platforms that have an ANSI C compiler.
 Lua also compiles unmodified as C++.
-The instructions given below for building Lua are for Unix-like platforms.
+The instructions given below for building Lua are for Unix-like platforms,
+such as Linux and Mac OS X.
 See also
 <A HREF="#other">instructions for other systems</A>
 and

@@ -107,7 +110,7 @@
 <OL>
 <LI>
 Open a terminal window and move to
-the top-level directory, which is named <TT>lua-5.4.x</TT>.
+the top-level directory, which is named <TT>lua-5.4.0-work2</TT>.
 The <TT>Makefile</TT> there controls both the build process and the installation process.
 <P>
 <LI>

@@ -147,7 +150,7 @@
   Once you have built Lua, you may want to install it in an official
   place in your system. In this case, do "<KBD>make install</KBD>". The official
   place and the way to install files are defined in the <TT>Makefile</TT>. You'll
-  probably need the right permissions to install files.
+  probably need the right permissions to install files, and so make need to do "<KBD>sudo make install</KBD>".
 
 <P>
   To build and install Lua in one step, do "<KBD>make xxx install</KBD>",

@@ -223,11 +226,8 @@
 <DT>
 library:
 <DD>
-lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
-lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c
-ltm.c lundump.c lvm.c lzio.c
-lauxlib.c lbaselib.c lbitlib.c lcorolib.c ldblib.c liolib.c
-lmathlib.c loslib.c lstrlib.c ltablib.c lutf8lib.c loadlib.c linit.c
+lapi.c lcode.c lctype.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c ltable.c ltm.c lundump.c lvm.c lzio.c
+lauxlib.c lbaselib.c lcorolib.c ldblib.c liolib.c lmathlib.c loadlib.c loslib.c lstrlib.c ltablib.c lutf8lib.c linit.c
 <DT>
 interpreter:
 <DD>

@@ -239,9 +239,9 @@
 </DL>
 
 <P>
-  To use Lua as a library in your own programs you'll need to know how to
+  To use Lua as a library in your own programs, you'll need to know how to
   create and use libraries with your compiler. Moreover, to dynamically load
-  C libraries for Lua you'll need to know how to create dynamic libraries
+  C libraries for Lua, you'll need to know how to create dynamic libraries
   and you'll need to make sure that the Lua API functions are accessible to
   those dynamic libraries &mdash; but <EM>don't</EM> link the Lua library
   into each dynamic library. For Unix, we recommend that the Lua library

@@ -316,10 +316,10 @@
 
 <P CLASS="footer">
 Last update:
-Mon Mar 12 14:52:57 -03 2018
+Mon Jun 18 17:08:42 -03 2018
 </P>
 <!--
-Last change: revised for Lua 5.4.0 (work1)
+Last change: revised for Lua 5.4.0 (work2)
 -->
 
 </BODY>

src/Makefile

@@ -26,7 +26,7 @@
 
 # == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE =======
 
-PLATS= aix bsd c89 freebsd generic linux macosx mingw posix solaris
+PLATS= aix bsd c89 freebsd generic linux linux-readline macosx mingw posix solaris
 
 LUA_A=	liblua.a
 CORE_O=	lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o

@@ -97,9 +97,8 @@
 	@echo '*** C89 does not guarantee 64-bit integers for Lua.'
 	@echo ''
 
-
 freebsd:
-	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE" SYSLIBS="-Wl,-E -lreadline"
+	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX -DLUA_USE_READLINE -I/usr/include/edit" SYSLIBS="-Wl,-E -ledit" CC="cc"
 
 generic: $(ALL)
 

@@ -115,7 +114,7 @@
 	$(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX -DLUA_USE_READLINE" SYSLIBS="-lreadline"
 
 mingw:
-	$(MAKE) "LUA_A=lua53.dll" "LUA_T=lua.exe" \
+	$(MAKE) "LUA_A=lua54.dll" "LUA_T=lua.exe" \
 	"AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \
 	"SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe
 	$(MAKE) "LUAC_T=luac.exe" luac.exe

src/lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.290 2018/02/27 20:01:55 roberto Exp $
+** $Id: lapi.c,v 2.295 2018/06/18 12:08:10 roberto Exp $
 ** Lua API
 ** See Copyright Notice in lua.h
 */

@@ -37,11 +37,10 @@
   "$LuaAuthors: " LUA_AUTHORS " $";
 
 
-/* value at a non-valid index */
-#define NONVALIDVALUE		cast(TValue *, luaO_nilobject)
 
-/* corresponding test */
-#define isvalid(o)	((o) != luaO_nilobject)
+/* test for a valid index */
+#define isvalid(L, o)	(!ttisnil(o) || o != &G(L)->nilvalue)
+
 
 /* test for pseudo index */
 #define ispseudo(i)		((i) <= LUA_REGISTRYINDEX)

@@ -49,21 +48,13 @@
 /* test for upvalue */
 #define isupvalue(i)		((i) < LUA_REGISTRYINDEX)
 
-/* test for valid but not pseudo index */
-#define isstackindex(i, o)	(isvalid(o) && !ispseudo(i))
-
-#define api_checkvalidindex(l,o)  api_check(l, isvalid(o), "invalid index")
-
-#define api_checkstackindex(l, i, o)  \
-	api_check(l, isstackindex(i, o), "index not in the stack")
-
 
 static TValue *index2value (lua_State *L, int idx) {
   CallInfo *ci = L->ci;
   if (idx > 0) {
     StkId o = ci->func + idx;
     api_check(L, idx <= L->ci->top - (ci->func + 1), "unacceptable index");
-    if (o >= L->top) return NONVALIDVALUE;
+    if (o >= L->top) return &G(L)->nilvalue;
     else return s2v(o);
   }
   else if (!ispseudo(idx)) {  /* negative index */

@@ -76,10 +67,10 @@
     idx = LUA_REGISTRYINDEX - idx;
     api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large");
     if (ttislcf(s2v(ci->func)))  /* light C function? */
-      return NONVALIDVALUE;  /* it has no upvalues */
+      return &G(L)->nilvalue;  /* it has no upvalues */
     else {
       CClosure *func = clCvalue(s2v(ci->func));
-      return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE;
+      return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : &G(L)->nilvalue;
     }
   }
 }

@@ -147,10 +138,9 @@
 }
 
 
-LUA_API const lua_Number *lua_version (lua_State *L) {
-  static const lua_Number version = LUA_VERSION_NUM;
-  if (L == NULL) return &version;
-  else return G(L)->version;
+LUA_API lua_Number lua_version (lua_State *L) {
+  UNUSED(L);
+  return LUA_VERSION_NUM;
 }
 
 

@@ -231,7 +221,7 @@
   lua_lock(L);
   fr = index2value(L, fromidx);
   to = index2value(L, toidx);
-  api_checkvalidindex(L, to);
+  api_check(l, isvalid(L, to), "invalid index");
   setobj(L, to, fr);
   if (isupvalue(toidx))  /* function upvalue? */
     luaC_barrier(L, clCvalue(s2v(L->ci->func)), fr);

@@ -257,7 +247,7 @@
 
 LUA_API int lua_type (lua_State *L, int idx) {
   const TValue *o = index2value(L, idx);
-  return (isvalid(o) ? ttype(o) : LUA_TNONE);
+  return (isvalid(L, o) ? ttype(o) : LUA_TNONE);
 }
 
 

@@ -302,7 +292,7 @@
 LUA_API int lua_rawequal (lua_State *L, int index1, int index2) {
   const TValue *o1 = index2value(L, index1);
   const TValue *o2 = index2value(L, index2);
-  return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0;
+  return (isvalid(L, o1) && isvalid(L, o2)) ? luaV_rawequalobj(o1, o2) : 0;
 }
 
 

@@ -329,7 +319,7 @@
   lua_lock(L);  /* may call tag method */
   o1 = index2value(L, index1);
   o2 = index2value(L, index2);
-  if (isvalid(o1) && isvalid(o2)) {
+  if (isvalid(L, o1) && isvalid(L, o2)) {
     switch (op) {
       case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break;
       case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break;

@@ -705,27 +695,6 @@
 }
 
 
-static int auxkeydef (lua_State *L, int idx, int remove) {
-  int res;
-  lua_lock(L);
-  api_checknelems(L, 1);
-  res = luaT_keydef(L, index2value(L, idx), s2v(L->top - 1), remove);
-  L->top--;  /* remove key */
-  lua_unlock(L);
-  return res;
-}
-
-
-LUA_API void lua_removekey (lua_State *L, int idx) {
-  auxkeydef(L, idx, 1);
-}
-
-
-LUA_API int lua_keyin (lua_State *L, int idx) {
-  return auxkeydef(L, idx, 0);
-}
-
-
 LUA_API void lua_createtable (lua_State *L, int narray, int nrec) {
   Table *t;
   lua_lock(L);

src/lauxlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lauxlib.c,v 1.294 2018/02/27 18:47:32 roberto Exp $
+** $Id: lauxlib.c,v 1.295 2018/06/18 12:08:10 roberto Exp $
 ** Auxiliary functions for building Lua libraries
 ** See Copyright Notice in lua.h
 */

@@ -950,13 +950,11 @@
 
 
 LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) {
-  const lua_Number *v = lua_version(L);
+  lua_Number v = lua_version(L);
   if (sz != LUAL_NUMSIZES)  /* check numeric types */
     luaL_error(L, "core and library have incompatible numeric types");
-  if (v != lua_version(NULL))
-    luaL_error(L, "multiple Lua VMs detected");
-  else if (*v != ver)
+  else if (v != ver)
     luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f",
-                  (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v);
+                  (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)v);
 }
 

src/lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 2.159 2018/03/07 15:55:38 roberto Exp $
+** $Id: lcode.c,v 2.161 2018/04/04 14:23:41 roberto Exp $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */

@@ -678,10 +678,6 @@
       e->k = VNONRELOC;  /* becomes a non-relocatable value */
       break;
     }
-    case VUNDEF: {  /* not a real expression */
-      luaK_semerror(fs->ls, "'undef' is not a value!!");
-      break;
-    }
     case VUPVAL: {  /* move value to some (pending) register */
       e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0);
       e->k = VRELOC;

@@ -1410,48 +1406,6 @@
 }
 
 
-static void normalizeindexed (FuncState *fs, expdesc *v) {
-  if (v->k != VINDEXED) {  /* not in proper form? */
-    int key = fs->freereg;  /* register with key value */
-    luaK_reserveregs(fs, 1);
-    switch (v->k) {
-      case VINDEXI:
-        luaK_int(fs, key, v->u.ind.idx);
-        break;
-      case VINDEXSTR:
-        luaK_codek(fs, key, v->u.ind.idx);
-        break;
-      case VINDEXUP:
-        luaK_codek(fs, key, v->u.ind.idx);
-        luaK_codeABC(fs, OP_GETUPVAL, fs->freereg, v->u.ind.t, 0);
-        v->u.ind.t = fs->freereg;
-        luaK_reserveregs(fs, 1);  /* one more register for the upvalue */
-        break;
-      default:
-        luaK_semerror(fs->ls, "'undef' is not a value!!");
-        break;
-    }
-    v->u.ind.idx = key;
-    v->k = VINDEXED;
-  }
-  freeregs(fs, v->u.ind.t, v->u.ind.idx);
-}
-
-
-static void codeisdef (FuncState *fs, int eq, expdesc *v) {
-  normalizeindexed(fs, v);
-  v->u.info = luaK_codeABCk(fs, OP_ISDEF, 0, v->u.ind.t, v->u.ind.idx, eq);
-  v->k = VRELOC;
-}
-
-
-void luaK_codeundef (FuncState *fs, expdesc *v) {
-  normalizeindexed(fs, v);
-  v->u.info = luaK_codeABC(fs, OP_UNDEF, v->u.ind.t, v->u.ind.idx, 0);
-  v->k = VRELOC;
-}
-
-
 /*
 ** Apply prefix operation 'op' to expression 'e'.
 */

@@ -1500,7 +1454,7 @@
       break;
     }
     case OPR_EQ: case OPR_NE: {
-      if (!tonumeral(v, NULL) && fs->ls->t.token != TK_UNDEF)
+      if (!tonumeral(v, NULL))
         luaK_exp2RK(fs, v);
       /* else keep numeral, which may be an immediate operand */
       break;

@@ -1597,10 +1551,7 @@
       break;
     }
     case OPR_EQ: case OPR_NE: {
-      if (e2->k == VUNDEF)
-        codeisdef(fs, opr == OPR_NE, e1);
-      else
-        codeeq(fs, opr, e1, e2);
+      codeeq(fs, opr, e1, e2);
       break;
     }
     case OPR_LT: case OPR_LE: {

@@ -1696,8 +1647,7 @@
           break;  /* no extra work */
         /* else use OP_RETURN to do the extra work */
         SET_OPCODE(*pc, OP_RETURN);
-        /* FALLTHROUGH */
-      }
+      }  /* FALLTHROUGH */
       case OP_RETURN: case OP_TAILCALL: {
         if (p->sizep > 0 || p->is_vararg) {
           SETARG_C(*pc, p->is_vararg ? p->numparams + 1 : 0);

src/lcode.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.h,v 1.71 2018/03/07 15:55:38 roberto Exp $
+** $Id: lcode.h,v 1.73 2018/04/04 14:23:41 roberto Exp $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */

@@ -78,7 +78,8 @@
 LUAI_FUNC int luaK_jump (FuncState *fs);
 LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);
 LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);
-void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose);
+LUAI_FUNC void luaK_patchgoto (FuncState *fs, int list, int target,
+                               int hasclose);
 LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);
 LUAI_FUNC void luaK_patchclose (FuncState *fs, int list);
 LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);

@@ -89,7 +90,6 @@
                             expdesc *v2, int line);
 LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);
 LUAI_FUNC void luaK_finish (FuncState *fs);
-LUAI_FUNC void luaK_codeundef (FuncState *fs, expdesc *e);
 LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg);
 
 

src/lctype.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lctype.h,v 1.12 2011/07/15 12:50:29 roberto Exp $
+** $Id: lctype.h,v 1.13 2018/06/18 12:51:05 roberto Exp $
 ** 'ctype' functions for Lua
 ** See Copyright Notice in lua.h
 */

@@ -68,7 +68,7 @@
 
 
 /* two more entries for 0 and -1 (EOZ) */
-LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2];
+LUAI_DDEC(const lu_byte luai_ctype_[UCHAR_MAX + 2];)
 
 
 #else			/* }{ */

src/ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.154 2018/03/05 14:15:04 roberto Exp $
+** $Id: ldblib.c,v 1.155 2018/03/16 15:33:34 roberto Exp $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */

@@ -186,8 +186,8 @@
     settabss(L, "namewhat", ar.namewhat);
   }
   if (strchr(options, 'r')) {
-    settabsi(L, "fTransfer", ar.fTransfer);
-    settabsi(L, "nTransfer", ar.nTransfer);
+    settabsi(L, "ftransfer", ar.ftransfer);
+    settabsi(L, "ntransfer", ar.ntransfer);
   }
   if (strchr(options, 't'))
     settabsb(L, "istailcall", ar.istailcall);

src/ldebug.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.c,v 2.155 2018/02/17 19:29:29 roberto Exp $
+** $Id: ldebug.c,v 2.158 2018/06/08 19:06:59 roberto Exp $
 ** Debug Interface
 ** See Copyright Notice in lua.h
 */

@@ -55,7 +55,7 @@
 ** case is when there is no absolute info or the instruction is before
 ** the first absolute one.
 */
-static int getbaseline (Proto *f, int pc, int *basepc) {
+static int getbaseline (const Proto *f, int pc, int *basepc) {
   if (f->sizeabslineinfo == 0 || pc < f->abslineinfo[0].pc) {
     *basepc = -1;  /* start from the beginning */
     return f->linedefined;

@@ -86,7 +86,7 @@
 ** first gets a base line and from there does the increments until
 ** the desired instruction.
 */
-int luaG_getfuncline (Proto *f, int pc) {
+int luaG_getfuncline (const Proto *f, int pc) {
   if (f->lineinfo == NULL)  /* no debug information? */
     return -1;
   else {

@@ -180,7 +180,7 @@
 }
 
 
-static const char *upvalname (Proto *p, int uv) {
+static const char *upvalname (const Proto *p, int uv) {
   TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name);
   if (s == NULL) return "?";
   else return getstr(s);

@@ -265,7 +265,7 @@
     ar->what = "C";
   }
   else {
-    Proto *p = cl->l.p;
+    const Proto *p = cl->l.p;
     ar->source = p->source ? getstr(p->source) : "=?";
     ar->linedefined = p->linedefined;
     ar->lastlinedefined = p->lastlinedefined;

@@ -275,7 +275,7 @@
 }
 
 
-static int nextline (Proto *p, int currentline, int pc) {
+static int nextline (const Proto *p, int currentline, int pc) {
   if (p->lineinfo[pc] != ABSLINEINFO)
     return currentline + p->lineinfo[pc];
   else

@@ -291,7 +291,7 @@
   else {
     int i;
     TValue v;
-    Proto *p = f->l.p;
+    const Proto *p = f->l.p;
     int currentline = p->linedefined;
     Table *t = luaH_new(L);  /* new table to store active lines */
     sethvalue2s(L, L->top, t);  /* push it on stack */

@@ -358,10 +358,10 @@
       }
       case 'r': {
         if (ci == NULL || !(ci->callstatus & CIST_TRAN))
-          ar->fTransfer = ar->nTransfer = 0;
+          ar->ftransfer = ar->ntransfer = 0;
         else {
-          ar->fTransfer = ci->u2.transferinfo.fTransfer;
-          ar->nTransfer = ci->u2.transferinfo.nTransfer;
+          ar->ftransfer = ci->u2.transferinfo.ftransfer;
+          ar->ntransfer = ci->u2.transferinfo.ntransfer;
         }
       }
       case 'L':

@@ -411,14 +411,14 @@
 ** =======================================================
 */
 
-static const char *getobjname (Proto *p, int lastpc, int reg,
+static const char *getobjname (const Proto *p, int lastpc, int reg,
                                const char **name);
 
 
 /*
 ** Find a "name" for the constant 'c'.
 */
-static void kname (Proto *p, int c, const char **name) {
+static void kname (const Proto *p, int c, const char **name) {
   TValue *kvalue = &p->k[c];
   *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
 }

@@ -427,7 +427,7 @@
 /*
 ** Find a "name" for the register 'c'.
 */
-static void rname (Proto *p, int pc, int c, const char **name) {
+static void rname (const Proto *p, int pc, int c, const char **name) {
   const char *what = getobjname(p, pc, c, name); /* search for 'c' */
   if (!(what && *what == 'c'))  /* did not find a constant name? */
     *name = "?";

@@ -437,7 +437,7 @@
 /*
 ** Find a "name" for a 'C' value in an RK instruction.
 */
-static void rkname (Proto *p, int pc, Instruction i, const char **name) {
+static void rkname (const Proto *p, int pc, Instruction i, const char **name) {
   int c = GETARG_C(i);  /* key index */
   if (GETARG_k(i))  /* is 'c' a constant? */
     kname(p, c, name);

@@ -456,7 +456,7 @@
 /*
 ** try to find last instruction before 'lastpc' that modified register 'reg'
 */
-static int findsetreg (Proto *p, int lastpc, int reg) {
+static int findsetreg (const Proto *p, int lastpc, int reg) {
   int pc;
   int setreg = -1;  /* keep last instruction that changed 'reg' */
   int jmptarget = 0;  /* any code before this address is conditional */

@@ -504,7 +504,7 @@
 ** Check whether table being indexed by instruction 'i' is the
 ** environment '_ENV'
 */
-static const char *gxf (Proto *p, int pc, Instruction i, int isup) {
+static const char *gxf (const Proto *p, int pc, Instruction i, int isup) {
   int t = GETARG_B(i);  /* table index */
   const char *name;  /* name of indexed variable */
   if (isup)  /* is an upvalue? */

@@ -515,7 +515,8 @@
 }
 
 
- const char *getobjname (Proto *p, int lastpc, int reg, const char **name) {
+ const char *getobjname (const Proto *p, int lastpc, int reg,
+                         const char **name) {
   int pc;
   *name = luaF_getlocalname(p, reg + 1, lastpc);
   if (*name)  /* is a local? */

@@ -585,7 +586,7 @@
 static const char *funcnamefromcode (lua_State *L, CallInfo *ci,
                                      const char **name) {
   TMS tm = (TMS)0;  /* (initial value avoids warnings) */
-  Proto *p = ci_func(ci)->p;  /* calling function */
+  const Proto *p = ci_func(ci)->p;  /* calling function */
   int pc = currentpc(ci);  /* calling instruction index */
   Instruction i = p->code[pc];  /* calling instruction */
   if (ci->callstatus & CIST_HOOKED) {  /* was it called inside a hook? */

@@ -774,7 +775,7 @@
 ** Check whether new instruction 'newpc' is in a different line from
 ** previous instruction 'oldpc'.
 */
-static int changedline (Proto *p, int oldpc, int newpc) {
+static int changedline (const Proto *p, int oldpc, int newpc) {
   while (oldpc++ < newpc) {
     if (p->lineinfo[oldpc] != 0)
       return (luaG_getfuncline(p, oldpc - 1) != luaG_getfuncline(p, newpc));

@@ -783,33 +784,39 @@
 }
 
 
-void luaG_traceexec (lua_State *L) {
+int luaG_traceexec (lua_State *L, const Instruction *pc) {
   CallInfo *ci = L->ci;
   lu_byte mask = L->hookmask;
-  int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
+  int counthook;
+  if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) {  /* no hooks? */
+    ci->u.l.trap = 0;  /* don't need to stop again */
+    return 0;  /* turn off 'trap' */
+  }
+  pc++;  /* reference is always next instruction */
+  ci->u.l.savedpc = pc;  /* save 'pc' */
+  counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT));
   if (counthook)
     resethookcount(L);  /* reset count */
   else if (!(mask & LUA_MASKLINE))
-    return;  /* no line hook and count != 0; nothing to be done */
+    return 1;  /* no line hook and count != 0; nothing to be done now */
   if (ci->callstatus & CIST_HOOKYIELD) {  /* called hook last time? */
     ci->callstatus &= ~CIST_HOOKYIELD;  /* erase mark */
-    return;  /* do not call hook again (VM yielded, so it did not move) */
+    return 1;  /* do not call hook again (VM yielded, so it did not move) */
   }
   if (!isIT(*(ci->u.l.savedpc - 1)))
     L->top = ci->top;  /* prepare top */
   if (counthook)
     luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0);  /* call count hook */
   if (mask & LUA_MASKLINE) {
-    Proto *p = ci_func(ci)->p;
-    const Instruction *npc = ci->u.l.savedpc;
-    int npci = pcRel(npc, p);
+    const Proto *p = ci_func(ci)->p;
+    int npci = pcRel(pc, p);
     if (npci == 0 ||  /* call linehook when enter a new function, */
-        npc <= L->oldpc ||  /* when jump back (loop), or when */
+        pc <= L->oldpc ||  /* when jump back (loop), or when */
         changedline(p, pcRel(L->oldpc, p), npci)) {  /* enter new line */
-      int newline = luaG_getfuncline(p, npci);  /* new line */
+      int newline = luaG_getfuncline(p, npci);
       luaD_hook(L, LUA_HOOKLINE, newline, 0, 0);  /* call line hook */
     }
-    L->oldpc = npc;
+    L->oldpc = pc;  /* 'pc' of last call to line hook */
   }
   if (L->status == LUA_YIELD) {  /* did hook yield? */
     if (counthook)

@@ -818,5 +825,6 @@
     ci->callstatus |= CIST_HOOKYIELD;  /* mark that it yielded */
     luaD_throw(L, LUA_YIELD);
   }
+  return 1;  /* keep 'trap' on */
 }
 

src/ldebug.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldebug.h,v 2.16 2018/01/28 15:13:26 roberto Exp $
+** $Id: ldebug.h,v 2.18 2018/06/08 19:06:59 roberto Exp $
 ** Auxiliary functions from Debug Interface module
 ** See Copyright Notice in lua.h
 */

@@ -21,7 +21,7 @@
 */
 #define ABSLINEINFO	(-0x80)
 
-LUAI_FUNC int luaG_getfuncline (Proto *f, int pc);
+LUAI_FUNC int luaG_getfuncline (const Proto *f, int pc);
 LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o,
                                                 const char *opname);
 LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1,

@@ -37,7 +37,7 @@
 LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg,
                                                   TString *src, int line);
 LUAI_FUNC l_noret luaG_errormsg (lua_State *L);
-LUAI_FUNC void luaG_traceexec (lua_State *L);
+LUAI_FUNC int luaG_traceexec (lua_State *L, const Instruction *pc);
 
 
 #endif

src/ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 2.199 2018/03/07 16:26:01 roberto Exp $
+** $Id: ldo.c,v 2.202 2018/05/30 14:25:52 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */

@@ -182,7 +182,7 @@
   StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue);
   lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
   lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
-  if (newstack == NULL) {  /* reallocation failed? */
+  if (unlikely(newstack == NULL)) {  /* reallocation failed? */
     if (raiseerror)
       luaM_error(L);
     else return 0;  /* do not raise an error */

@@ -204,7 +204,7 @@
 int luaD_growstack (lua_State *L, int n, int raiseerror) {
   int size = L->stacksize;
   int newsize = 2 * size;  /* tentative new size */
-  if (size > LUAI_MAXSTACK) {  /* need more space after extra size? */
+  if (unlikely(size > LUAI_MAXSTACK)) {  /* need more space after extra size? */
     if (raiseerror)
       luaD_throw(L, LUA_ERRERR);  /* error inside message handler */
     else return 0;

@@ -215,7 +215,7 @@
       newsize = LUAI_MAXSTACK;
     if (newsize < needed)  /* but must respect what was asked for */
       newsize = needed;
-    if (newsize > LUAI_MAXSTACK) {  /* stack overflow? */
+    if (unlikely(newsize > LUAI_MAXSTACK)) {  /* stack overflow? */
       /* add extra size to be able to handle the error message */
       luaD_reallocstack(L, ERRORSTACKSIZE, raiseerror);
       if (raiseerror)

@@ -268,7 +268,7 @@
 ** function, can be changed asynchronously by signals.)
 */
 void luaD_hook (lua_State *L, int event, int line,
-                              int fTransfer, int nTransfer) {
+                              int ftransfer, int ntransfer) {
   lua_Hook hook = L->hook;
   if (hook && L->allowhook) {  /* make sure there is a hook */
     int mask = CIST_HOOKED;

@@ -279,10 +279,10 @@
     ar.event = event;
     ar.currentline = line;
     ar.i_ci = ci;
-    if (nTransfer != 0) {
+    if (ntransfer != 0) {
       mask |= CIST_TRAN;  /* 'ci' has transfer information */
-      ci->u2.transferinfo.fTransfer = fTransfer;
-      ci->u2.transferinfo.nTransfer = nTransfer;
+      ci->u2.transferinfo.ftransfer = ftransfer;
+      ci->u2.transferinfo.ntransfer = ntransfer;
     }
     luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */
     if (L->top + LUA_MINSTACK > ci->top)

@@ -319,24 +319,26 @@
 }
 
 
-static void rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
+static StkId rethook (lua_State *L, CallInfo *ci, StkId firstres, int nres) {
+  ptrdiff_t oldtop = savestack(L, L->top);  /* hook may change top */
   int delta = 0;
   if (isLuacode(ci)) {
     Proto *p = clLvalue(s2v(ci->func))->p;
     if (p->is_vararg)
       delta = ci->u.l.nextraargs + p->numparams + 1;
     if (L->top < ci->top)
-      L->top = ci->top;  /* correct top */
+      L->top = ci->top;  /* correct top to run hook */
   }
   if (L->hookmask & LUA_MASKRET) {  /* is return hook on? */
-    int fTransfer;
+    int ftransfer;
     ci->func += delta;  /* if vararg, back to virtual 'func' */
-    fTransfer = cast(unsigned short, firstres - ci->func);
-    luaD_hook(L, LUA_HOOKRET, -1, fTransfer, nres);  /* call it */
+    ftransfer = cast(unsigned short, firstres - ci->func);
+    luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres);  /* call it */
     ci->func -= delta;
   }
   if (isLua(ci->previous))
     L->oldpc = ci->previous->u.l.savedpc;  /* update 'oldpc' */
+  return restorestack(L, oldtop);
 }
 
 

@@ -348,7 +350,7 @@
 void luaD_tryfuncTM (lua_State *L, StkId func) {
   const TValue *tm = luaT_gettmbyobj(L, s2v(func), TM_CALL);
   StkId p;
-  if (!ttisfunction(tm))
+  if (unlikely(!ttisfunction(tm)))
     luaG_typeerror(L, s2v(func), "call");
   for (p = L->top; p > func; p--)
     setobjs2s(L, p, p-1);

@@ -363,40 +365,33 @@
 ** expressions, multiple results for tail calls/single parameters)
 ** separated.
 */
-static void moveresults (lua_State *L, StkId firstResult, StkId res,
-                                       int nres, int wanted) {
+static void moveresults (lua_State *L, StkId res, int nres, int wanted) {
   switch (wanted) {  /* handle typical cases separately */
-    case 0: break;  /* nothing to move */
-    case 1: {  /* one result needed */
+    case 0:  /* no values needed */
+      L->top = res;
+      break;
+    case 1:  /* one value needed */
       if (nres == 0)   /* no results? */
         setnilvalue(s2v(res));  /* adjust with nil */
       else
-        setobjs2s(L, res, firstResult);  /* move it to proper place */
+        setobjs2s(L, res, L->top - nres);  /* move it to proper place */
+      L->top = res + 1;
       break;
-    }
-    case LUA_MULTRET: {
+    case LUA_MULTRET:
+      wanted = nres;  /* we want all results */
+      /* FALLTHROUGH */
+    default: {  /* multiple results */
+      StkId firstresult = L->top - nres;  /* index of first result */
       int i;
-      for (i = 0; i < nres; i++)  /* move all results to correct place */
-        setobjs2s(L, res + i, firstResult + i);
-      wanted = nres;  /* it wanted what it had */
-      break;
-    }
-    default: {
-      int i;
-      if (wanted <= nres) {  /* enough results? */
-        for (i = 0; i < wanted; i++)  /* move wanted results to correct place */
-          setobjs2s(L, res + i, firstResult + i);
-      }
-      else {  /* not enough results; use all of them plus nils */
-        for (i = 0; i < nres; i++)  /* move all results to correct place */
-          setobjs2s(L, res + i, firstResult + i);
-        for (; i < wanted; i++)  /* complete wanted number of results */
-          setnilvalue(s2v(res + i));
-      }
+      /* move all results to correct place */
+      for (i = 0; i < nres && i < wanted; i++)
+        setobjs2s(L, res + i, firstresult + i);
+      for (; i < wanted; i++)  /* complete wanted number of results */
+        setnilvalue(s2v(res + i));
+      L->top = res + wanted;  /* top points after the last result */
       break;
     }
   }
-  L->top = res + wanted;  /* top points after the last result */
 }
 
 

@@ -404,15 +399,12 @@
 ** Finishes a function call: calls hook if necessary, removes CallInfo,
 ** moves current number of results to proper place.
 */
-void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) {
-  if (L->hookmask) {
-    ptrdiff_t fr = savestack(L, firstResult);  /* hook may change stack */
-    rethook(L, ci, firstResult, nres);
-    firstResult = restorestack(L, fr);
-  }
+void luaD_poscall (lua_State *L, CallInfo *ci, int nres) {
+  if (L->hookmask)
+    L->top = rethook(L, ci, L->top - nres, nres);
   L->ci = ci->previous;  /* back to caller */
   /* move results to proper place */
-  moveresults(L, firstResult, ci->func, nres, ci->nresults);
+  moveresults(L, ci->func, nres, ci->nresults);
 }
 
 

@@ -477,7 +469,7 @@
       n = (*f)(L);  /* do the actual call */
       lua_lock(L);
       api_checknelems(L, n);
-      luaD_poscall(L, ci, L->top - n, n);
+      luaD_poscall(L, ci, n);
       break;
     }
     case LUA_TLCL: {  /* Lua function */

@@ -540,7 +532,7 @@
   n = (*ci->u.c.k)(L, status, ci->u.c.ctx);  /* call continuation function */
   lua_lock(L);
   api_checknelems(L, n);
-  luaD_poscall(L, ci, L->top - n, n);  /* finish 'luaD_call' */
+  luaD_poscall(L, ci, n);  /* finish 'luaD_call' */
 }
 
 

@@ -642,9 +634,8 @@
         n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */
         lua_lock(L);
         api_checknelems(L, n);
-        firstArg = L->top - n;  /* yield results come from continuation */
       }
-      luaD_poscall(L, ci, firstArg, n);  /* finish 'luaD_call' */
+      luaD_poscall(L, ci, n);  /* finish 'luaD_call' */
     }
     unroll(L, NULL);  /* run continuation */
   }

@@ -669,14 +660,14 @@
   L->nny = 0;  /* allow yields */
   api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs);
   status = luaD_rawrunprotected(L, resume, &nargs);
-  if (status == -1)  /* error calling 'lua_resume'? */
+  if (unlikely(status == -1))  /* error calling 'lua_resume'? */
     status = LUA_ERRRUN;
   else {  /* continue running after recoverable errors */
     while (errorstatus(status) && recover(L, status)) {
       /* unroll continuation */
       status = luaD_rawrunprotected(L, unroll, &status);
     }
-    if (errorstatus(status)) {  /* unrecoverable error? */
+    if (unlikely(errorstatus(status))) {  /* unrecoverable error? */
       L->status = cast_byte(status);  /* mark thread as 'dead' */
       seterrorobj(L, status, L->top);  /* push error message */
       L->ci->top = L->top;

@@ -703,7 +694,7 @@
   luai_userstateyield(L, nresults);
   lua_lock(L);
   api_checknelems(L, nresults);
-  if (L->nny > 0) {
+  if (unlikely(L->nny > 0)) {
     if (L != G(L)->mainthread)
       luaG_runerror(L, "attempt to yield across a C-call boundary");
     else

@@ -736,7 +727,7 @@
   ptrdiff_t old_errfunc = L->errfunc;
   L->errfunc = ef;
   status = luaD_rawrunprotected(L, func, u);
-  if (status != LUA_OK) {  /* an error occurred? */
+  if (unlikely(status != LUA_OK)) {  /* an error occurred? */
     StkId oldtop = restorestack(L, old_top);
     luaF_close(L, oldtop);  /* close possible pending closures */
     seterrorobj(L, status, oldtop);

src/ldo.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.h,v 2.43 2018/02/17 19:29:29 roberto Exp $
+** $Id: ldo.h,v 2.44 2018/05/22 12:02:36 roberto Exp $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */

@@ -61,8 +61,7 @@
 LUAI_FUNC void luaD_tryfuncTM (lua_State *L, StkId func);
 LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
                                         ptrdiff_t oldtop, ptrdiff_t ef);
-LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
-                                          int nres);
+LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres);
 LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror);
 LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror);
 LUAI_FUNC void luaD_shrinkstack (lua_State *L);

src/lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.252 2018/02/26 13:35:03 roberto Exp $
+** $Id: lgc.c,v 2.254 2018/06/15 14:14:20 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */

@@ -301,8 +301,8 @@
         gray2black(o);  /* nothing else to mark */
         break;
       }
-      /* else *//* FALLTHROUGH */
-    }
+      /* else... */
+    }  /* FALLTHROUGH */
     case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE:
     case LUA_TTHREAD: case LUA_TPROTO: {
       linkobjgclist(o, g->gray);

@@ -398,7 +398,7 @@
   Node *n, *limit = gnodelast(h);
   /* if there is array part, assume it may have white values (it is not
      worth traversing it now just to check) */
-  int hasclears = (h->sizearray > 0);
+  int hasclears = (h->alimit > 0);
   for (n = gnode(h, 0); n < limit; n++) {  /* traverse hash part */
     if (isempty(gval(n)))  /* entry is empty? */
       clearkey(n);  /* clear its key */

@@ -433,8 +433,9 @@
   int hasww = 0;  /* true if table has entry "white-key -> white-value" */
   Node *n, *limit = gnodelast(h);
   unsigned int i;
+  unsigned int asize = luaH_realasize(h);
   /* traverse array part */
-  for (i = 0; i < h->sizearray; i++) {
+  for (i = 0; i < asize; i++) {
     if (valiswhite(&h->array[i])) {
       marked = 1;
       reallymarkobject(g, gcvalue(&h->array[i]));

@@ -472,7 +473,8 @@
 static void traversestrongtable (global_State *g, Table *h) {
   Node *n, *limit = gnodelast(h);
   unsigned int i;
-  for (i = 0; i < h->sizearray; i++)  /* traverse array part */
+  unsigned int asize = luaH_realasize(h);
+  for (i = 0; i < asize; i++)  /* traverse array part */
     markvalue(g, &h->array[i]);
   for (n = gnode(h, 0); n < limit; n++) {  /* traverse hash part */
     if (isempty(gval(n)))  /* entry is empty? */

@@ -508,7 +510,7 @@
   }
   else  /* not weak */
     traversestrongtable(g, h);
-  return 1 + h->sizearray + 2 * allocsizenode(h);
+  return 1 + h->alimit + 2 * allocsizenode(h);
 }
 
 

@@ -719,7 +721,8 @@
     Table *h = gco2t(l);
     Node *n, *limit = gnodelast(h);
     unsigned int i;
-    for (i = 0; i < h->sizearray; i++) {
+    unsigned int asize = luaH_realasize(h);
+    for (i = 0; i < asize; i++) {
       TValue *o = &h->array[i];
       if (iscleared(g, gcvalueN(o)))  /* value was collected? */
         setempty(o);  /* remove entry */

src/lgc.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.h,v 2.102 2018/02/19 20:06:56 roberto Exp $
+** $Id: lgc.h,v 2.103 2018/06/11 14:19:50 roberto Exp $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */

@@ -69,13 +69,14 @@
 
 /*
 ** Layout for bit use in 'marked' field. First three bits are
-** used for object "age" in generational mode.
+** used for object "age" in generational mode. Last bit is free
+** to be used by respective objects.
 */
 #define WHITE0BIT	3  /* object is white (type 0) */
 #define WHITE1BIT	4  /* object is white (type 1) */
 #define BLACKBIT	5  /* object is black */
 #define FINALIZEDBIT	6  /* object has been marked for finalization */
-#define TESTGRAYBIT	7  /* used by tests (luaL_checkmemory) */
+
 
 
 #define WHITEBITS	bit2mask(WHITE0BIT, WHITE1BIT)

src/ljumptab.h

@@ -79,8 +79,6 @@
 &&L_OP_GEI,
 &&L_OP_TEST,
 &&L_OP_TESTSET,
-&&L_OP_UNDEF,
-&&L_OP_ISDEF,
 &&L_OP_CALL,
 &&L_OP_TAILCALL,
 &&L_OP_RETURN,

src/llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 2.101 2018/03/07 15:55:38 roberto Exp $
+** $Id: llex.c,v 2.102 2018/04/04 14:23:41 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */

@@ -41,7 +41,7 @@
     "and", "break", "do", "else", "elseif",
     "end", "false", "for", "function", "goto", "if",
     "in", "local", "nil", "not", "or", "repeat",
-    "return", "then", "true", "undef", "until", "while",
+    "return", "then", "true", "until", "while",
     "//", "..", "...", "==", ">=", "<=", "~=",
     "<<", ">>", "::", "<eof>",
     "<number>", "<integer>", "<name>", "<string>"

src/llex.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.81 2018/03/07 15:55:38 roberto Exp $
+** $Id: llex.h,v 1.82 2018/04/04 14:23:41 roberto Exp $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */

@@ -28,7 +28,7 @@
   TK_AND = FIRST_RESERVED, TK_BREAK,
   TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
   TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
-  TK_RETURN, TK_THEN, TK_TRUE, TK_UNDEF, TK_UNTIL, TK_WHILE,
+  TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
   /* other terminal symbols */
   TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE,
   TK_SHL, TK_SHR,

src/llimits.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llimits.h,v 1.149 2018/01/28 15:13:26 roberto Exp $
+** $Id: llimits.h,v 1.151 2018/06/15 14:13:45 roberto Exp $
 ** Limits, basic types, and some other 'installation-dependent' definitions
 ** See Copyright Notice in lua.h
 */

@@ -60,6 +60,12 @@
 
 
 /*
+** test whether an unsigned value is a power of 2 (or zero)
+*/
+#define ispow2(x)	(((x) & ((x) - 1)) == 0)
+
+
+/*
 ** conversion of pointer to unsigned integer:
 ** this is for hashing only; there is no problem if the integer
 ** cannot hold the whole pointer value

@@ -131,8 +137,26 @@
 
 
 /*
+** macros to improve jump prediction (used mainly for error handling)
+*/
+#if !defined(likely)
+
+#if defined(__GNUC__)
+#define likely(x)	(__builtin_expect(((x) != 0), 1))
+#define unlikely(x)	(__builtin_expect(((x) != 0), 0))
+#else
+#define likely(x)	(x)
+#define unlikely(x)	(x)
+#endif
+
+#endif
+
+
+/*
 ** non-return type
 */
+#if !defined(l_noret)
+
 #if defined(__GNUC__)
 #define l_noret		void __attribute__((noreturn))
 #elif defined(_MSC_VER) && _MSC_VER >= 1200

@@ -141,6 +165,7 @@
 #define l_noret		void
 #endif
 
+#endif
 
 
 /*

src/lmathlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lmathlib.c,v 1.125 2018/03/12 12:39:03 roberto Exp $
+** $Id: lmathlib.c,v 1.135 2018/06/14 18:47:22 roberto Exp $
 ** Standard mathematical library
 ** See Copyright Notice in lua.h
 */

@@ -14,6 +14,7 @@
 #include <limits.h>
 #include <math.h>
 #include <stdlib.h>
+#include <time.h>
 
 #include "lua.h"
 

@@ -230,12 +231,8 @@
 
 
 static int math_type (lua_State *L) {
-  if (lua_type(L, 1) == LUA_TNUMBER) {
-      if (lua_isinteger(L, 1))
-        lua_pushliteral(L, "integer");
-      else
-        lua_pushliteral(L, "float");
-  }
+  if (lua_type(L, 1) == LUA_TNUMBER)
+    lua_pushstring(L, (lua_isinteger(L, 1)) ? "integer" : "float");
   else {
     luaL_checkany(L, 1);
     lua_pushnil(L);

@@ -247,7 +244,7 @@
 
 /*
 ** {==================================================================
-** Pseudo-Random Number Generator based on 'xorshift128+'.
+** Pseudo-Random Number Generator based on 'xoshiro256**'.
 ** ===================================================================
 */
 

@@ -261,111 +258,192 @@
 #endif
 
 
-#if !defined(LUA_USE_C89) && defined(LLONG_MAX) && !defined(LUA_DEBUG)  /* { */
+/*
+** LUA_RAND32 forces the use of 32-bit integers in the implementation
+** of the PRN generator (mainly for testing).
+*/
+#if !defined(LUA_RAND32) && !defined(Rand64)
+
+/* try to find an integer type with at least 64 bits */
+
+#if (LONG_MAX >> 31 >> 31) >= 1
+
+/* 'long' has at least 64 bits */
+#define Rand64		unsigned long
+
+#elif !defined(LUA_USE_C89) && defined(LLONG_MAX)
+
+/* there is a 'long long' type (which must have at least 64 bits) */
+#define Rand64		unsigned long long
+
+#elif (LUA_MAXINTEGER >> 31 >> 31) >= 1
+
+/* 'lua_Integer' has at least 64 bits */
+#define Rand64		lua_Unsigned
+
+#endif
+
+#endif
+
+
+#if defined(Rand64)  /* { */
 
 /*
-** Assume long long.
+** Standard implementation, using 64-bit integers.
+** If 'Rand64' has more than 64 bits, the extra bits do not interfere
+** with the 64 initial bits, except in a right shift. Moreover, the
+** final result has to discard the extra bits.
 */
 
-/* a 64-bit value */
-typedef unsigned long long I;
+/* avoid using extra bits when needed */
+#define trim64(x)	((x) & 0xffffffffffffffffu)
+
 
-static I xorshift128plus (I *state) {
-  I x = state[0];
-  I y = state[1];
-  state[0] = y;
-  x ^= x << 23;
-  state[1] = (x ^ (x >> 18)) ^ (y ^ (y >> 5));
-  return state[1] + y;
+/* rotate left 'x' by 'n' bits */
+static Rand64 rotl (Rand64 x, int n) {
+  return (x << n) | (trim64(x) >> (64 - n)); 
 }
 
+static Rand64 nextrand (Rand64 *state) {
+  Rand64 state0 = state[0];
+  Rand64 state1 = state[1];
+  Rand64 state2 = state[2] ^ state0;
+  Rand64 state3 = state[3] ^ state1;
+  Rand64 res = rotl(state1 * 5, 7) * 9;
+  state[0] = state0 ^ state3;
+  state[1] = state1 ^ state2;
+  state[2] = state2 ^ (state1 << 17);
+  state[3] = rotl(state3, 45);
+  return res;
+}
+
+
 /* must take care to not shift stuff by more than 63 slots */
 
-#define maskFIG		(~(~1LLU << (FIGS - 1)))  /* use FIGS bits */
-#define shiftFIG	(l_mathop(0.5) / (1LLU << (FIGS - 1)))  /* 2^(-FIG) */
 
 /*
 ** Convert bits from a random integer into a float in the
 ** interval [0,1).
 */
-static lua_Number I2d (I x) {
+#define maskFIG		(~(~(Rand64)1 << (FIGS - 1)))  /* use FIGS bits */
+#define shiftFIG  \
+	(l_mathop(0.5) / ((Rand64)1 << (FIGS - 1)))  /* 2^(-FIGS) */
+
+static lua_Number I2d (Rand64 x) {
   return (lua_Number)(x & maskFIG) * shiftFIG;
 }
 
-/* convert an 'I' to a lua_Unsigned */
-#define I2UInt(x)	((lua_Unsigned)(x))
+/* convert a 'Rand64' to a 'lua_Unsigned' */
+#define I2UInt(x)	((lua_Unsigned)trim64(x))
 
-/* convert a lua_Integer to an 'I' */
-#define Int2I(x)	((I)(x))
+/* convert a 'lua_Unsigned' to a 'Rand64' */
+#define Int2I(x)	((Rand64)(x))
 
-#else  /* no long long   }{ */
 
-/*
-** Use two 32-bit integers to represent a 64-bit quantity.
-*/
+#else	/* no 'Rand64'   }{ */
 
-#if LUAI_BITSINT >= 32
+/* get an integer with at least 32 bits */
+#if (INT_MAX >> 30) >= 1
 typedef unsigned int lu_int32;
 #else
 typedef unsigned long lu_int32;
 #endif
 
-/* a 64-bit value */
-typedef struct I {
+
+/*
+** Use two 32-bit integers to represent a 64-bit quantity.
+*/
+typedef struct Rand64 {
   lu_int32 h;  /* higher half */
   lu_int32 l;  /* lower half */
-} I;
+} Rand64;
 
 
 /*
-** basic operations on 'I' values
+** If 'lu_int32' has more than 32 bits, the extra bits do not interfere
+** with the 32 initial bits, except in a right shift and comparisons.
+** Moreover, the final result has to discard the extra bits.
 */
 
-static I pack (lu_int32 h, lu_int32 l) {
-  I result;
+/* avoid using extra bits when needed */
+#define trim32(x)	((x) & 0xffffffffu)
+
+
+/*
+** basic operations on 'Rand64' values
+*/
+
+/* build a new Rand64 value */
+static Rand64 packI (lu_int32 h, lu_int32 l) {
+  Rand64 result;
   result.h = h;
   result.l = l;
   return result;
 }
 
-/* i ^ (i << n) */
-static I Ixorshl (I i, int n) {
-  return pack(i.h ^ ((i.h << n) | (i.l >> (32 - n))), i.l ^ (i.l << n));
+/* return i << n */
+static Rand64 Ishl (Rand64 i, int n) {
+  lua_assert(n > 0 && n < 32);
+  return packI((i.h << n) | (trim32(i.l) >> (32 - n)), i.l << n);
+}
+
+/* i1 ^= i2 */
+static void Ixor (Rand64 *i1, Rand64 i2) {
+  i1->h ^= i2.h;
+  i1->l ^= i2.l;
+}
+
+/* return i1 + i2 */
+static Rand64 Iadd (Rand64 i1, Rand64 i2) {
+  Rand64 result = packI(i1.h + i2.h, i1.l + i2.l);
+  if (trim32(result.l) < trim32(i1.l))  /* carry? */
+    result.h++;
+  return result;
 }
 
-/* i ^ (i >> n) */
-static I Ixorshr (I i, int n) {
-  return pack(i.h ^ (i.h >> n), i.l ^ ((i.l >> n) | (i.h << (32 - n))));
+/* return i * 5 */
+static Rand64 times5 (Rand64 i) {
+  return Iadd(Ishl(i, 2), i);  /* i * 5 == (i << 2) + i */
 }
 
-static I Ixor (I i1, I i2) {
-  return pack(i1.h ^ i2.h, i1.l ^ i2.l);
+/* return i * 9 */
+static Rand64 times9 (Rand64 i) {
+  return Iadd(Ishl(i, 3), i);  /* i * 9 == (i << 3) + i */
 }
 
-static I Iadd (I i1, I i2) {
-  I result = pack(i1.h + i2.h, i1.l + i2.l);
-  if (result.l < i1.l)  /* carry? */
-    result.h++;
-  return result;
+/* return 'i' rotated left 'n' bits */
+static Rand64 rotl (Rand64 i, int n) {
+  lua_assert(n > 0 && n < 32);
+  return packI((i.h << n) | (trim32(i.l) >> (32 - n)),
+               (trim32(i.h) >> (32 - n)) | (i.l << n));
 }
 
+/* for offsets larger than 32, rotate right by 64 - offset */
+static Rand64 rotl1 (Rand64 i, int n) {
+  lua_assert(n > 32 && n < 64);
+  n = 64 - n;
+  return packI((trim32(i.h) >> n) | (i.l << (32 - n)),
+               (i.h << (32 - n)) | (trim32(i.l) >> n));
+}
 
 /*
-** implementation of 'xorshift128+' algorithm on 'I' values
+** implementation of 'xoshiro256**' algorithm on 'Rand64' values
 */
-static I xorshift128plus (I *state) {
-  I x = state[0];
-  I y = state[1];
-  state[0] = y;
-  x = Ixorshl(x, 23);  /* x ^= x << 23; */
-  /* state[1] = (x ^ (x >> 18)) ^ (y ^ (y >> 5)); */
-  state[1] = Ixor(Ixorshr(x, 18), Ixorshr(y, 5));
-  return Iadd(state[1], y);  /* return state[1] + y; */
+static Rand64 nextrand (Rand64 *state) {
+  Rand64 res = times9(rotl(times5(state[1]), 7));
+  Rand64 t = Ishl(state[1], 17);
+  Ixor(&state[2], state[0]);
+  Ixor(&state[3], state[1]);
+  Ixor(&state[1], state[2]);
+  Ixor(&state[0], state[3]);
+  Ixor(&state[2], t);
+  state[3] = rotl1(state[3], 45);
+  return res;
 }
 
 
 /*
-** Converts an 'I' into a float.
+** Converts a 'Rand64' into a float.
 */
 
 /* an unsigned 1 with proper type */

@@ -373,91 +451,85 @@
 
 #if FIGS <= 32
 
-#define maskHF		0  /* do not need bits from higher half */
-#define maskLOW		(~(~UONE << (FIGS - 1)))  /* use FIG bits */
-#define shiftFIG	(l_mathop(0.5) / (UONE << (FIGS - 1)))  /* 2^(-FIG) */
+#define maskHI		0  /* do not need bits from higher half */
+#define maskLOW		(~(~UONE << (FIGS - 1)))  /* use FIGS bits */
+#define shiftFIG	(l_mathop(0.5) / (UONE << (FIGS - 1)))  /* 2^(-FIGS) */
 
 #else	/* 32 < FIGS <= 64 */
 
 /* must take care to not shift stuff by more than 31 slots */
 
-/* use FIG - 32 bits from higher half */
-#define maskHF		(~(~UONE << (FIGS - 33)))
+/* use FIGS - 32 bits from higher half */
+#define maskHI		(~(~UONE << (FIGS - 33)))
 
-/* use all bits from lower half */
-#define maskLOW		(~(lu_int32)0)
+/* use 32 bits from lower half */
+#define maskLOW		(~(~UONE << 31))
 
-/* 2^(-FIG) == (1 / 2^33) / 2^(FIG-33) */
+/* 2^(-FIGS) == (1 / 2^33) / 2^(FIGS-33) */
 #define shiftFIG  ((lua_Number)(1.0 / 8589934592.0) / (UONE << (FIGS - 33)))
 
 #endif
 
 #define twoto32		l_mathop(4294967296.0)  /* 2^32 */
 
-static lua_Number I2d (I x) {
-  lua_Number h = (lua_Number)(x.h & maskHF);
+static lua_Number I2d (Rand64 x) {
+  lua_Number h = (lua_Number)(x.h & maskHI);
   lua_Number l = (lua_Number)(x.l & maskLOW);
   return (h * twoto32 + l) * shiftFIG;
 }
 
-static lua_Unsigned I2UInt (I x) {
-  return ((lua_Unsigned)x.h << 31 << 1) | x.l;
+
+/* convert a 'Rand64' to a 'lua_Unsigned' */
+static lua_Unsigned I2UInt (Rand64 x) {
+  return ((lua_Unsigned)trim32(x.h) << 31 << 1) | (lua_Unsigned)trim32(x.l);
 }
 
-static I Int2I (lua_Integer n) {
-  lua_Unsigned un = n;
-  return pack((lu_int32)un, (lu_int32)(un >> 31 >> 1));
+/* convert a 'lua_Unsigned' to a 'Rand64' */
+static Rand64 Int2I (lua_Unsigned n) {
+  return packI((lu_int32)(n >> 31 >> 1), (lu_int32)n);
 }
 
 #endif  /* } */
 
 
 /*
-** A state uses two 'I' values.
+** A state uses four 'Rand64' values.
 */
 typedef struct {
-  I s[2];
+  Rand64 s[4];
 } RanState;
 
 
 /*
 ** Project the random integer 'ran' into the interval [0, n].
-** Because 'ran' has 2^B possible values, the projection can only
-** be uniform when the size of the interval [0, n] is a power of 2
-** (exact division). With the fairest possible projection (e.g.,
-** '(ran % (n + 1))'), the maximum bias is 1 in 2^B/n.
-** For a "small" 'n', this bias is acceptable. (Here, we accept
-** a maximum bias of 0.0001%.) For a larger 'n', we first
-** compute 'lim', the smallest (2^b - 1) not smaller than 'n',
-** to get a uniform projection into [0,lim]. If the result is
-** inside [0, n], we are done. Otherwise, we try we another
-** 'ran' until we have a result inside the interval.
+** Because 'ran' has 2^B possible values, the projection can only be
+** uniform when the size of the interval is a power of 2 (exact
+** division).  To get a uniform projection into [0, n], we first compute
+** 'lim', the smallest Mersenne number not smaller than 'n'. We then
+** project 'ran' into the interval [0, lim].  If the result is inside
+** [0, n], we are done. Otherwise, we try with another 'ran', until we
+** have a result inside the interval.
 */
-
-#define MAXBIAS		1000000
-
 static lua_Unsigned project (lua_Unsigned ran, lua_Unsigned n,
                              RanState *state) {
-  if (n < LUA_MAXUNSIGNED / MAXBIAS)
-    return ran % (n + 1);
-  else {
+  lua_Unsigned lim = n;
+  if ((lim & (lim + 1)) > 0) {  /* 'lim + 1' is not a power of 2? */
     /* compute the smallest (2^b - 1) not smaller than 'n' */
-    lua_Unsigned lim = n;
     lim |= (lim >> 1);
     lim |= (lim >> 2);
     lim |= (lim >> 4);
     lim |= (lim >> 8);
     lim |= (lim >> 16);
-#if (LUA_MAXINTEGER >> 30 >> 2) > 0
+#if (LUA_MAXINTEGER >> 30 >> 1) > 0
     lim |= (lim >> 32);  /* integer type has more than 32 bits */
 #endif
-    lua_assert((lim & (lim + 1)) == 0  /* 'lim + 1' is a power of 2 */
-      && lim >= n  /* not smaller than 'n' */
-      && (lim >> 1) < n);  /* it is the smallest one */
-    while ((ran & lim) > n)
-      ran = I2UInt(xorshift128plus(state->s));
-    return ran & lim;
   }
+  lua_assert((lim & (lim + 1)) == 0  /* 'lim + 1' is a power of 2, */
+    && lim >= n  /* not smaller than 'n', */
+    && (lim == 0 || (lim >> 1) < n));  /* and it is the smallest one */
+  while ((ran &= lim) > n)  /* project 'ran' into [0..lim] */
+    ran = I2UInt(nextrand(state->s));  /* not inside [0..n]? try again */
+  return ran;
 }
 
 

@@ -465,7 +537,7 @@
   lua_Integer low, up;
   lua_Unsigned p;
   RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
-  I rv = xorshift128plus(state->s);  /* next pseudo-random value */
+  Rand64 rv = nextrand(state->s);  /* next pseudo-random value */
   switch (lua_gettop(L)) {  /* check number of arguments */
     case 0: {  /* no arguments */
       lua_pushnumber(L, I2d(rv));  /* float between 0 and 1 */

@@ -496,19 +568,22 @@
 }
 
 
-static void setseed (I *state, lua_Integer n) {
+static void setseed (Rand64 *state, lua_Unsigned n1, lua_Unsigned n2) {
   int i;
-  state[0] = Int2I(n);
-  state[1] = Int2I(~n);
+  state[0] = Int2I(n1);
+  state[1] = Int2I(0xff);  /* avoid a zero state */
+  state[2] = Int2I(n2);
+  state[3] = Int2I(0);
   for (i = 0; i < 16; i++)
-    xorshift128plus(state);  /* discard initial values */
+    nextrand(state);  /* discard initial values to "spread" seed */
 }
 
 
 static int math_randomseed (lua_State *L) {
   RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1));
-  lua_Integer n = luaL_checkinteger(L, 1);
-  setseed(state->s, n);
+  lua_Integer n1 = luaL_checkinteger(L, 1);
+  lua_Integer n2 = luaL_optinteger(L, 2, 0);
+  setseed(state->s, n1, n2);
   return 0;
 }
 

@@ -519,9 +594,18 @@
   {NULL, NULL}
 };
 
+
+/*
+** Register the random functions and initialize their state.
+** To give some "randomness" to the initial seed, use the current time
+** and the address of 'L' (in case the machine does address space layout
+** randomization).
+*/
 static void setrandfunc (lua_State *L) {
   RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0);
-  setseed(state->s, 0);
+  lua_Unsigned seed1 = (lua_Unsigned)time(NULL); 
+  lua_Unsigned seed2 = (lua_Unsigned)(size_t)L; 
+  setseed(state->s, seed1, seed2);
   luaL_setfuncs(L, randfuncs, 1);
 }
 

src/lmem.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lmem.c,v 1.96 2018/01/28 15:13:26 roberto Exp $
+** $Id: lmem.c,v 1.98 2018/06/18 12:08:10 roberto Exp $
 ** Interface to Memory Manager
 ** See Copyright Notice in lua.h
 */

@@ -60,7 +60,7 @@
   if (nelems + 1 <= size)  /* does one extra element still fit? */
     return block;  /* nothing to be done */
   if (size >= limit / 2) {  /* cannot double it? */
-    if (size >= limit)  /* cannot grow even a little? */
+    if (unlikely(size >= limit))  /* cannot grow even a little? */
       luaG_runerror(L, "too many %s (limit is %d)", what, limit);
     size = limit;  /* still have at least one free place */
   }

@@ -73,7 +73,7 @@
   /* 'limit' ensures that multiplication will not overflow */
   newblock = luaM_realloc_(L, block, cast_sizet(*psize) * size_elems,
                                      cast_sizet(size) * size_elems);
-  if (newblock == NULL)
+  if (unlikely(newblock == NULL))
     luaM_error(L);
   *psize = size;  /* update only when everything else is OK */
   return newblock;

@@ -88,7 +88,7 @@
   size_t newsize = cast_sizet(final_n * size_elem);
   lua_assert(newsize <= oldsize);
   newblock = (*g->frealloc)(g->ud, block, oldsize, newsize);
-  if (newblock == NULL && final_n > 0)  /* allocation failed? */
+  if (unlikely(newblock == NULL && final_n > 0))  /* allocation failed? */
     luaM_error(L);
   else {
     g->GCdebt += newsize - oldsize;

@@ -114,6 +114,22 @@
 }
 
 
+/*
+** In case of allocation fail, this function will call the GC to try
+** to free some memory and then try the allocation again.
+** (It should not be called when shrinking a block, because then the
+** interpreter may be in the middle of a collection step.)
+*/
+static void *tryagain (lua_State *L, void *block,
+                       size_t osize, size_t nsize) {
+  global_State *g = G(L);
+  if (ttisnil(&g->nilvalue)) {  /* is state fully build? */
+    luaC_fullgc(L, 1);  /* try to free some memory... */
+    return (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
+  }
+  else return NULL;  /* cannot free any memory without a full state */
+}
+
 
 /*
 ** generic allocation routine.

@@ -124,13 +140,10 @@
   lua_assert((osize == 0) == (block == NULL));
   hardtest(L, osize, nsize);
   newblock = (*g->frealloc)(g->ud, block, osize, nsize);
-  if (newblock == NULL && nsize > 0) {
-    /* Is state fully built? Not shrinking a block? */
-    if (g->version && nsize > osize) {
-      luaC_fullgc(L, 1);  /* try to free some memory... */
-      newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
-    }
-    if (newblock == NULL)
+  if (unlikely(newblock == NULL && nsize > 0)) {
+    if (nsize > osize)  /* not shrinking a block? */
+      newblock = tryagain(L, block, osize, nsize);
+    if (newblock == NULL)  /* still no memory? */
       return NULL;
   }
   lua_assert((nsize == 0) == (newblock == NULL));

@@ -142,7 +155,7 @@
 void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize,
                                                     size_t nsize) {
   void *newblock = luaM_realloc_(L, block, osize, nsize);
-  if (newblock == NULL && nsize > 0)  /* allocation failed? */
+  if (unlikely(newblock == NULL && nsize > 0))  /* allocation failed? */
     luaM_error(L);
   return newblock;
 }

@@ -155,11 +168,8 @@
   else {
     global_State *g = G(L);
     void *newblock = (*g->frealloc)(g->ud, NULL, tag, size);
-    if (newblock == NULL) {
-      if (g->version) {  /* is state fully built? */
-        luaC_fullgc(L, 1);  /* try to free some memory... */
-        newblock = (*g->frealloc)(g->ud, NULL, tag, size);  /* try again */
-      }
+    if (unlikely(newblock == NULL)) {
+      newblock = tryagain(L, NULL, tag, size);
       if (newblock == NULL)
         luaM_error(L);
     }

src/lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 2.124 2018/02/27 18:47:32 roberto Exp $
+** $Id: lobject.c,v 2.126 2018/06/01 17:40:38 roberto Exp $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */

@@ -29,10 +29,6 @@
 #include "lvm.h"
 
 
-
-LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT};
-
-
 /*
 ** converts an integer to a "floating point byte", represented as
 ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if

@@ -393,7 +389,7 @@
 
 static void pushstr (lua_State *L, const char *str, size_t l) {
   setsvalue2s(L, L->top, luaS_newlstr(L, str, l));
-  luaD_inctop(L);
+  L->top++;
 }
 
 

@@ -402,11 +398,10 @@
    conventional formats, plus Lua-specific '%I' and '%U'
 */
 const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
-  int n = 0;
-  for (;;) {
-    const char *e = strchr(fmt, '%');
-    if (e == NULL) break;
-    pushstr(L, fmt, e - fmt);
+  int n = 0;  /* number of strings in the stack to concatenate */
+  const char *e;  /* points to next conversion specifier */
+  while ((e = strchr(fmt, '%')) != NULL) {
+    pushstr(L, fmt, e - fmt);  /* string up to conversion specifier */
     switch (*(e+1)) {
       case 's': {  /* zero-terminated string */
         const char *s = va_arg(argp, char *);

@@ -433,7 +428,7 @@
       case 'f': {  /* a 'lua_Number' */
         setfltvalue(s2v(L->top), cast_num(va_arg(argp, l_uacNumber)));
       top2str:  /* convert the top element to a string */
-        luaD_inctop(L);
+        L->top++;
         luaO_tostring(L, s2v(L->top - 1));
         break;
       }

@@ -460,9 +455,12 @@
       }
     }
     n += 2;
-    fmt = e+2;
+    if (L->top + 2 > L->stack_last) {  /* no free stack space? */
+      luaV_concat(L, n);
+      n = 1;
+    }
+    fmt = e + 2;
   }
-  luaD_checkstack(L, 1);
   pushstr(L, fmt, strlen(fmt));
   if (n > 0) luaV_concat(L, n + 1);
   return svalue(s2v(L->top - 1));

src/lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.141 2018/02/26 14:16:05 roberto Exp $
+** $Id: lobject.h,v 2.146 2018/06/15 19:31:22 roberto Exp $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */

@@ -137,16 +137,14 @@
 ** ===================================================================
 */
 
-#define ttisnil(o)		checktag((o), LUA_TNIL)
+/* macro to test for (any kind of) nil */
+#define ttisnil(v)		checktype((v), LUA_TNIL)
 
-/* macro defining a nil value */
-#define NILCONSTANT	{NULL}, LUA_TNIL
-
-#define setnilvalue(obj) settt_(obj, LUA_TNIL)
+/* macro to test for a "pure" nil */
+#define ttisstrictnil(o)	checktag((o), LUA_TNIL)
 
 
-/* (address of) a fixed nil value */
-#define luaO_nilobject		(&luaO_nilobject_)
+#define setnilvalue(obj) settt_(obj, LUA_TNIL)
 
 
 /*

@@ -155,23 +153,32 @@
 */
 #define LUA_TEMPTY	(LUA_TNIL | (1 << 4))
 
-#define ttisnilorempty(v)	checktype((v), LUA_TNIL)
+/*
+** Variant used only in the value returned for a key not found in a
+** table (absent key).
+*/
+#define LUA_TABSTKEY	(LUA_TNIL | (2 << 4))
 
-#define isreallyempty(v)	checktag((v), LUA_TEMPTY)
 
+#define isabstkey(v)		checktag((v), LUA_TABSTKEY)
 
-#if defined(LUA_NILINTABLE)
 
-#define isempty(v)		isreallyempty(v)
+/*
+** macro to detect non-standard nils (used only in assertions)
+*/
+#define isreallyempty(v)	(ttisnil(v) && !ttisstrictnil(v))
 
-#else /* By default, entries with any kind of nil are considered empty */
 
-#define isempty(v)		ttisnilorempty(v)
+/*
+** By default, entries with any kind of nil are considered empty.
+** (In any definition, values associated with absent keys must also
+** be accepted as empty.)
+*/
+#define isempty(v)		ttisnil(v)
 
-#endif
 
-/* macro defining an empty value */
-#define EMPTYCONSTANT	{NULL}, LUA_TEMPTY
+/* macro defining a value corresponding to an absent key */
+#define ABSTKEYCONSTANT		{NULL}, LUA_TABSTKEY
 
 
 /* mark an entry as empty */

@@ -659,11 +666,24 @@
 	  (void)L; checkliveness(L,io_); }
 
 
+/*
+** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the
+** real size of 'array'. Otherwise, the real size of 'array' is the
+** smallest power of two not smaller than 'alimit' (or zero iff 'alimit'
+** is zero); 'alimit' is then used as a hint for #t.
+*/
+
+#define BITRAS		(1 << 7)
+#define isrealasize(t)		(!((t)->marked & BITRAS))
+#define setrealasize(t)		((t)->marked &= cast_byte(~BITRAS))
+#define setnorealasize(t)	((t)->marked |= BITRAS)
+
+
 typedef struct Table {
   CommonHeader;
   lu_byte flags;  /* 1<<p means tagmethod(p) is not present */
   lu_byte lsizenode;  /* log2 of size of 'node' array */
-  unsigned int sizearray;  /* size of 'array' array */
+  unsigned int alimit;  /* "limit" of 'array' array */
   TValue *array;  /* array part */
   Node *node;
   Node *lastfree;  /* any free position is before this position */

@@ -716,8 +736,6 @@
 #define sizenode(t)	(twoto((t)->lsizenode))
 
 
-LUAI_DDEC const TValue luaO_nilobject_;
-
 /* size of buffer for 'luaO_utf8esc' function */
 #define UTF8BUFFSZ	8
 

src/lopcodes.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.c,v 1.80 2018/03/07 15:55:38 roberto Exp $
+** $Id: lopcodes.c,v 1.82 2018/04/19 15:42:41 roberto Exp $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -17,6 +17,8 @@
 
 /* ORDER OP */
 
+#if defined(LUAI_DEFOPNAMES)
+
 LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
   "MOVE",
   "LOADI",

@@ -79,8 +81,6 @@
   "GEI",
   "TEST",
   "TESTSET",
-  "UNDEF",
-  "ISDEF",
   "CALL",
   "TAILCALL",
   "RETURN",

@@ -100,6 +100,8 @@
   NULL
 };
 
+#endif
+
 
 LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
 /*       OT IT T  A  mode		   opcode  */

@@ -164,8 +166,6 @@
  ,opmode(0, 0, 1, 0, iABC)		/* OP_GEI */
  ,opmode(0, 0, 1, 0, iABC)		/* OP_TEST */
  ,opmode(0, 0, 1, 1, iABC)		/* OP_TESTSET */
- ,opmode(0, 0, 0, 0, iABC)		/* OP_UNDEF */
- ,opmode(0, 0, 0, 1, iABC)		/* OP_ISDEF */
  ,opmode(1, 1, 0, 1, iABC)		/* OP_CALL */
  ,opmode(1, 1, 0, 1, iABC)		/* OP_TAILCALL */
  ,opmode(0, 1, 0, 0, iABC)		/* OP_RETURN */

src/lopcodes.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lopcodes.h,v 1.190 2018/03/07 15:55:38 roberto Exp $
+** $Id: lopcodes.h,v 1.193 2018/06/18 12:51:05 roberto Exp $
 ** Opcodes for Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -266,9 +266,6 @@
 OP_TEST,/*	A 	if (not R(A) == k) then pc++			*/
 OP_TESTSET,/*	A B	if (not R(B) == k) then R(A) := R(B) else pc++	*/
 
-OP_UNDEF,/*	A B	R(A)[R(B)] = undef				*/
-OP_ISDEF,/*	A B C	R(A) = (R(B)[R(C)] == undef			*/
-
 OP_CALL,/*	A B C	R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */
 OP_TAILCALL,/*	A B C	return R(A)(R(A+1), ... ,R(A+B-1))		*/
 

@@ -291,7 +288,7 @@
 
 OP_CLOSURE,/*	A Bx	R(A) := closure(KPROTO[Bx])			*/
 
-OP_VARARG,/*	A B C  	R(A), R(A+1), ..., R(A+C-2) = vararg		*/
+OP_VARARG,/*	A C  	R(A), R(A+1), ..., R(A+C-2) = vararg		*/
 
 OP_PREPVARARG,/*A 	(adjust vararg parameters)			*/
 

@@ -342,7 +339,7 @@
 ** bit 6: instruction sets 'L->top' for next instruction (when C == 0)
 */
 
-LUAI_DDEC const lu_byte luaP_opmodes[NUM_OPCODES];
+LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];)
 
 #define getOpMode(m)	(cast(enum OpMode, luaP_opmodes[m] & 7))
 #define testAMode(m)	(luaP_opmodes[m] & (1 << 3))

@@ -361,7 +358,7 @@
 #define opmode(ot,it,t,a,m) (((ot)<<6) | ((it)<<5) | ((t)<<4) | ((a)<<3) | (m))
 
 
-LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */
+LUAI_DDEC(const char *const luaP_opnames[NUM_OPCODES+1];)  /* opcode names */
 
 
 /* number of list items to accumulate before a SETLIST instruction */

src/lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 2.179 2018/03/07 15:55:38 roberto Exp $
+** $Id: lparser.c,v 2.181 2018/06/18 17:57:20 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */

@@ -893,11 +893,6 @@
       singlevar(ls, v);
       return;
     }
-    case TK_UNDEF: {
-      luaX_next(ls);
-      init_exp(v, VUNDEF, 0);
-      return;
-    }
     default: {
       luaX_syntaxerror(ls, "unexpected symbol");
     }

@@ -1183,10 +1178,6 @@
   else {  /* assignment -> '=' explist */
     int nexps;
     checknext(ls, '=');
-    if (nvars == 1 && testnext(ls, TK_UNDEF)) {
-      luaK_codeundef(ls->fs, &lh->v);
-      return;
-    }
     nexps = explist(ls, &e);
     if (nexps != nvars)
       adjust_assign(ls, nvars, nexps, &e);

@@ -1652,11 +1643,6 @@
       luaX_next(ls);  /* skip LOCAL */
       if (testnext(ls, TK_FUNCTION))  /* local function? */
         localfunc(ls);
-      else if (testnext(ls, TK_UNDEF))
-        (void)0;  /* ignore */
-      /* old versions may need to declare 'local undef'
-         when using 'undef' with no environment; so this
-         version accepts (and ignores) these declarations */
       else
         localstat(ls);
       break;

@@ -1723,7 +1709,7 @@
   luaD_inctop(L);
   funcstate.f = cl->p = luaF_newproto(L);
   funcstate.f->source = luaS_new(L, name);  /* create and anchor TString */
-  lua_assert(iswhite(funcstate.f));  /* do not need barrier here */
+  luaC_objbarrier(L, funcstate.f, funcstate.f->source);
   lexstate.buff = buff;
   lexstate.dyd = dyd;
   dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;

src/lparser.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.h,v 1.81 2018/03/07 15:55:38 roberto Exp $
+** $Id: lparser.h,v 1.82 2018/04/04 14:23:41 roberto Exp $
 ** Lua Parser
 ** See Copyright Notice in lua.h
 */

@@ -52,8 +52,7 @@
   VRELOC,  /* expression can put result in any register;
               info = instruction pc */
   VCALL,  /* expression is a function call; info = instruction pc */
-  VVARARG,  /* vararg expression; info = instruction pc */
-  VUNDEF  /* the 'undef' "expression" */
+  VVARARG  /* vararg expression; info = instruction pc */
 } expkind;
 
 

src/lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 2.151 2018/02/05 17:11:37 roberto Exp $
+** $Id: lstate.c,v 2.155 2018/06/18 12:08:10 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */

@@ -30,17 +30,6 @@
 
 
 /*
-** a macro to help the creation of a unique random seed when a state is
-** created; the seed is used to randomize hashes.
-*/
-#if !defined(luai_makeseed)
-#include <time.h>
-#define luai_makeseed()		cast_uint(time(NULL))
-#endif
-
-
-
-/*
 ** thread state + extra space
 */
 typedef struct LX {

@@ -63,25 +52,35 @@
 
 
 /*
-** Compute an initial seed as random as possible. Rely on Address Space
-** Layout Randomization (if present) to increase randomness..
+** A macro to create a "random" seed when a state is created;
+** the seed is used to randomize string hashes.
+*/
+#if !defined(luai_makeseed)
+
+#include <time.h>
+
+/*
+** Compute an initial seed with some level of randomness.
+** Rely on Address Space Layout Randomization (if present) and
+** current time.
 */
 #define addbuff(b,p,e) \
   { size_t t = cast_sizet(e); \
     memcpy(b + p, &t, sizeof(t)); p += sizeof(t); }
 
-static unsigned int makeseed (lua_State *L) {
-  char buff[4 * sizeof(size_t)];
-  unsigned int h = luai_makeseed();
+static unsigned int luai_makeseed (lua_State *L) {
+  char buff[3 * sizeof(size_t)];
+  unsigned int h = cast_uint(time(NULL));
   int p = 0;
   addbuff(buff, p, L);  /* heap variable */
   addbuff(buff, p, &h);  /* local variable */
-  addbuff(buff, p, luaO_nilobject);  /* global variable */
   addbuff(buff, p, &lua_newstate);  /* public function */
   lua_assert(p == sizeof(buff));
   return luaS_hash(buff, p, h);
 }
 
+#endif
+
 
 /*
 ** set GCdebt to a new value keeping the value (totalbytes + GCdebt)

@@ -216,7 +215,7 @@
 
 /*
 ** open parts of the state that may cause memory-allocation errors.
-** ('g->version' != NULL flags that the state was completely build)
+** ('ttisnil(&g->nilvalue)'' flags that the state was completely build)
 */
 static void f_luaopen (lua_State *L, void *ud) {
   global_State *g = G(L);

@@ -227,7 +226,7 @@
   luaT_init(L);
   luaX_init(L);
   g->gcrunning = 1;  /* allow gc */
-  g->version = lua_version(NULL);
+  setnilvalue(&g->nilvalue);
   luai_userstateopen(L);
 }
 

@@ -261,7 +260,7 @@
   global_State *g = G(L);
   luaF_close(L, L->stack);  /* close all upvalues for this thread */
   luaC_freeallobjects(L);  /* collect all objects */
-  if (g->version)  /* closing a fully built state? */
+  if (ttisnil(&g->nilvalue))  /* closing a fully built state? */
     luai_userstateclose(L);
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size);
   freestack(L);

@@ -327,13 +326,12 @@
   g->frealloc = f;
   g->ud = ud;
   g->mainthread = L;
-  g->seed = makeseed(L);
+  g->seed = luai_makeseed(L);
   g->gcrunning = 0;  /* no GC while building state */
   g->strt.size = g->strt.nuse = 0;
   g->strt.hash = NULL;
   setnilvalue(&g->l_registry);
   g->panic = NULL;
-  g->version = NULL;
   g->gcstate = GCSpause;
   g->gckind = KGC_INC;
   g->gcemergency = 0;

@@ -346,6 +344,7 @@
   g->twups = NULL;
   g->totalbytes = sizeof(LG);
   g->GCdebt = 0;
+  setivalue(&g->nilvalue, 0);  /* to signal that state is not yet built */
   setgcparam(g->gcpause, LUAI_GCPAUSE);
   setgcparam(g->gcstepmul, LUAI_GCMUL);
   g->gcstepsize = LUAI_GCSTEPSIZE;

src/lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.157 2018/02/25 12:43:52 roberto Exp $
+** $Id: lstate.h,v 2.160 2018/06/18 12:08:10 roberto Exp $
 ** Global State
 ** See Copyright Notice in lua.h
 */

@@ -104,8 +104,8 @@
     int funcidx;  /* called-function index */
     int nyield;  /* number of values yielded */
     struct {  /* info about transfered values (for call/return hooks) */
-      unsigned short fTransfer;  /* offset of first value transfered */
-      unsigned short nTransfer;  /* number of values transfered */
+      unsigned short ftransfer;  /* offset of first value transfered */
+      unsigned short ntransfer;  /* number of values transfered */
     } transferinfo;
   } u2;
   short nresults;  /* expected number of results from this function */

@@ -148,6 +148,7 @@
   lu_mem GCestimate;  /* an estimate of the non-garbage memory in use */
   stringtable strt;  /* hash table for strings */
   TValue l_registry;
+  TValue nilvalue;  /* a nil value */
   unsigned int seed;  /* randomized seed for hashes */
   lu_byte currentwhite;
   lu_byte gcstate;  /* state of garbage collector */

@@ -180,7 +181,6 @@
   struct lua_State *twups;  /* list of threads with open upvalues */
   lua_CFunction panic;  /* to be called in unprotected errors */
   struct lua_State *mainthread;
-  const lua_Number *version;  /* pointer to version number */
   TString *memerrmsg;  /* message for memory-allocation errors */
   TString *tmname[TM_N];  /* array with tag-method names */
   struct Table *mt[LUA_NUMTAGS];  /* metatables for basic types */

src/lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.65 2018/02/20 16:52:50 roberto Exp $
+** $Id: lstring.c,v 2.66 2018/05/30 14:25:52 roberto Exp $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */

@@ -99,7 +99,7 @@
   if (nsize < osize)  /* shrinking table? */
     tablerehash(tb->hash, osize, nsize);  /* depopulate shrinking part */
   newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*);
-  if (newvect == NULL) {  /* reallocation failed? */
+  if (unlikely(newvect == NULL)) {  /* reallocation failed? */
     if (nsize < osize)  /* was it shrinking table? */
       tablerehash(tb->hash, nsize, osize);  /* restore to original size */
     /* leave table as it was */

@@ -182,7 +182,7 @@
 
 
 static void growstrtab (lua_State *L, stringtable *tb) {
-  if (tb->nuse == MAX_INT) {  /* too many strings? */
+  if (unlikely(tb->nuse == MAX_INT)) {  /* too many strings? */
     luaC_fullgc(L, 1);  /* try to free some... */
     if (tb->nuse == MAX_INT)  /* still too many? */
       luaM_error(L);  /* cannot even create a message... */

@@ -233,7 +233,7 @@
     return internshrstr(L, str, l);
   else {
     TString *ts;
-    if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char))
+    if (unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char)))
       luaM_toobig(L);
     ts = luaS_createlngstrobj(L, l);
     memcpy(getstr(ts), str, l * sizeof(char));

@@ -269,7 +269,7 @@
   Udata *u;
   int i;
   GCObject *o;
-  if (s > MAX_SIZE - udatamemoffset(nuvalue))
+  if (unlikely(s > MAX_SIZE - udatamemoffset(nuvalue)))
     luaM_toobig(L);
   o = luaC_newobj(L, LUA_TUSERDATA, sizeudata(nuvalue, s));
   u = gco2u(o);

src/lstrlib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstrlib.c,v 1.262 2018/02/21 17:48:31 roberto Exp $
+** $Id: lstrlib.c,v 1.263 2018/05/25 13:39:32 roberto Exp $
 ** Standard library for string operations and pattern-matching
 ** See Copyright Notice in lua.h
 */

@@ -1522,17 +1522,12 @@
   while (*fmt != '\0') {
     int size, ntoalign;
     KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign);
+    luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1,
+                     "variable-length format");
     size += ntoalign;  /* total space used by option */
     luaL_argcheck(L, totalsize <= MAXSIZE - size, 1,
                      "format result too large");
     totalsize += size;
-    switch (opt) {
-      case Kstring:  /* strings with length count */
-      case Kzstr:    /* zero-terminated string */
-        luaL_argerror(L, 1, "variable-length format");
-        /* call never return, but to avoid warnings: *//* FALLTHROUGH */
-      default:  break;
-    }
   }
   lua_pushinteger(L, (lua_Integer)totalsize);
   return 1;

@@ -1585,8 +1580,8 @@
   while (*fmt != '\0') {
     int size, ntoalign;
     KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign);
-    if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld)
-      luaL_argerror(L, 2, "data string too short");
+    luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2,
+                    "data string too short");
     pos += ntoalign;  /* skip alignment */
     /* stack space for item + next position */
     luaL_checkstack(L, 2, "too many results");

@@ -1615,13 +1610,15 @@
       }
       case Kstring: {
         size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0);
-        luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short");
+        luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short");
         lua_pushlstring(L, data + pos + size, len);
         pos += len;  /* skip string */
         break;
       }
       case Kzstr: {
         size_t len = (int)strlen(data + pos);
+        luaL_argcheck(L, pos + len < ld, 2,
+                         "unfinished string for format 'z'");
         lua_pushlstring(L, data + pos, len);
         pos += len + 1;  /* skip string plus final '\0' */
         break;

src/ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 2.135 2018/02/26 14:16:05 roberto Exp $
+** $Id: ltable.c,v 2.140 2018/06/15 14:18:40 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */

@@ -93,7 +93,8 @@
 };
 
 
-LUAI_DDEF const TValue luaH_emptyobject_ = {EMPTYCONSTANT};
+static const TValue absentkey = {ABSTKEYCONSTANT};
+
 
 
 /*

@@ -192,6 +193,59 @@
 
 
 /*
+** True if value of 'alimit' is equal to the real size of the array
+** part of table 't'. (Otherwise, the array part must be larger than
+** 'alimit'.)
+*/
+#define limitequalsasize(t)	(isrealasize(t) || ispow2((t)->alimit))
+
+
+/*
+** Returns the real size of the 'array' array
+*/
+LUAI_FUNC unsigned int luaH_realasize (const Table *t) {
+  if (limitequalsasize(t))
+    return t->alimit;  /* this is the size */
+  else {
+    unsigned int size = t->alimit;
+    /* compute the smallest power of 2 not smaller than 'n' */
+    size |= (size >> 1);
+    size |= (size >> 2);
+    size |= (size >> 4);
+    size |= (size >> 8);
+    size |= (size >> 16);
+#if (INT_MAX >> 30 >> 1) > 0
+    size |= (size >> 32);  /* int has more than 32 bits */
+#endif
+    size++;
+    lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size);
+    return size;
+  }
+}
+
+
+/*
+** Check whether real size of the array is a power of 2.
+** (If it is not, 'alimit' cannot be changed to any other value
+** without changing the real size.)
+*/
+static int ispow2realasize (const Table *t) {
+  return (!isrealasize(t) || ispow2(t->alimit));
+}
+
+
+static unsigned int setlimittosize (Table *t) {
+  t->alimit = luaH_realasize(t);
+  setrealasize(t);
+  return t->alimit;
+}
+
+
+#define limitasasize(t)	check_exp(isrealasize(t), t->alimit)
+
+
+
+/*
 ** "Generic" get version. (Not that generic: not valid for integers,
 ** which may be in array part, nor for floats with integral values.)
 */

@@ -203,7 +257,7 @@
     else {
       int nx = gnext(n);
       if (nx == 0)
-        return luaH_emptyobject;  /* not found */
+        return &absentkey;  /* not found */
       n += nx;
     }
   }

@@ -227,33 +281,35 @@
 ** elements in the array part, then elements in the hash part. The
 ** beginning of a traversal is signaled by 0.
 */
-static unsigned int findindex (lua_State *L, Table *t, TValue *key) {
+static unsigned int findindex (lua_State *L, Table *t, TValue *key,
+                               unsigned int asize) {
   unsigned int i;
   if (ttisnil(key)) return 0;  /* first iteration */
   i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0;
-  if (i != 0 && i <= t->sizearray)  /* is 'key' inside array part? */
+  if (i != 0 && i <= asize)  /* is 'key' inside array part? */
     return i;  /* yes; that's the index */
   else {
     const TValue *n = getgeneric(t, key);
-    if (n == luaH_emptyobject)
+    if (unlikely(isabstkey(n)))
       luaG_runerror(L, "invalid key to 'next'");  /* key not found */
     i = cast_int(nodefromval(n) - gnode(t, 0));  /* key index in hash table */
     /* hash elements are numbered after array ones */
-    return (i + 1) + t->sizearray;
+    return (i + 1) + asize;
   }
 }
 
 
 int luaH_next (lua_State *L, Table *t, StkId key) {
-  unsigned int i = findindex(L, t, s2v(key));  /* find original element */
-  for (; i < t->sizearray; i++) {  /* try first array part */
+  unsigned int asize = luaH_realasize(t);
+  unsigned int i = findindex(L, t, s2v(key), asize);  /* find original key */
+  for (; i < asize; i++) {  /* try first array part */
     if (!isempty(&t->array[i])) {  /* a non-empty entry? */
       setivalue(s2v(key), i + 1);
       setobj2s(L, key + 1, &t->array[i]);
       return 1;
     }
   }
-  for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) {  /* hash part */
+  for (i -= asize; cast_int(i) < sizenode(t); i++) {  /* hash part */
     if (!isempty(gval(gnode(t, i)))) {  /* a non-empty entry? */
       Node *n = gnode(t, i);
       getnodekey(L, s2v(key), n);

@@ -328,12 +384,13 @@
   unsigned int ttlg;  /* 2^lg */
   unsigned int ause = 0;  /* summation of 'nums' */
   unsigned int i = 1;  /* count to traverse all array keys */
+  unsigned int asize = limitasasize(t);  /* real array size */
   /* traverse each slice */
   for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) {
     unsigned int lc = 0;  /* counter */
     unsigned int lim = ttlg;
-    if (lim > t->sizearray) {
-      lim = t->sizearray;  /* adjust upper limit */
+    if (lim > asize) {
+      lim = asize;  /* adjust upper limit */
       if (i > lim)
         break;  /* no more elements to count */
     }

@@ -450,31 +507,31 @@
                                           unsigned int nhsize) {
   unsigned int i;
   Table newt;  /* to keep the new hash part */
-  unsigned int oldasize = t->sizearray;
+  unsigned int oldasize = setlimittosize(t);
   TValue *newarray;
   /* create new hash part with appropriate size into 'newt' */
   setnodevector(L, &newt, nhsize);
   if (newasize < oldasize) {  /* will array shrink? */
-    t->sizearray = newasize;  /* pretend array has new size... */
+    t->alimit = newasize;  /* pretend array has new size... */
     exchangehashpart(t, &newt);  /* and new hash */
     /* re-insert into the new hash the elements from vanishing slice */
     for (i = newasize; i < oldasize; i++) {
       if (!isempty(&t->array[i]))
         luaH_setint(L, t, i + 1, &t->array[i]);
     }
-    t->sizearray = oldasize;  /* restore current size... */
+    t->alimit = oldasize;  /* restore current size... */
     exchangehashpart(t, &newt);  /* and hash (in case of errors) */
   }
   /* allocate new array */
   newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue);
-  if (newarray == NULL && newasize > 0) {  /* allocation failed? */
+  if (unlikely(newarray == NULL && newasize > 0)) {  /* allocation failed? */
     freehash(L, &newt);  /* release new hash part */
     luaM_error(L);  /* raise error (with array unchanged) */
   }
   /* allocation ok; initialize new part of the array */
   exchangehashpart(t, &newt);  /* 't' has the new hash ('newt' has the old) */
   t->array = newarray;  /* set new array part */
-  t->sizearray = newasize;
+  t->alimit = newasize;
   for (i = oldasize; i < newasize; i++)  /* clear new slice of the array */
      setempty(&t->array[i]);
   /* re-insert elements from old hash part into new parts */

@@ -498,6 +555,7 @@
   int i;
   int totaluse;
   for (i = 0; i <= MAXABITS; i++) nums[i] = 0;  /* reset counts */
+  setlimittosize(t);
   na = numusearray(t, nums);  /* count keys in array part */
   totaluse = na;  /* all those keys are integer keys */
   totaluse += numusehash(t, nums, &na);  /* count keys in hash part */

@@ -524,7 +582,7 @@
   t->metatable = NULL;
   t->flags = cast_byte(~0);
   t->array = NULL;
-  t->sizearray = 0;
+  t->alimit = 0;
   setnodevector(L, t, 0);
   return t;
 }

@@ -532,7 +590,7 @@
 
 void luaH_free (lua_State *L, Table *t) {
   freehash(L, t);
-  luaM_freearray(L, t->array, t->sizearray);
+  luaM_freearray(L, t->array, luaH_realasize(t));
   luaM_free(L, t);
 }
 

@@ -560,7 +618,8 @@
 TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
   Node *mp;
   TValue aux;
-  if (ttisnil(key)) luaG_runerror(L, "table index is nil");
+  if (unlikely(ttisnil(key)))
+    luaG_runerror(L, "table index is nil");
   else if (ttisfloat(key)) {
     lua_Number f = fltvalue(key);
     lua_Integer k;

@@ -568,7 +627,7 @@
       setivalue(&aux, k);
       key = &aux;  /* insert it as an integer */
     }
-    else if (luai_numisnan(f))
+    else if (unlikely(luai_numisnan(f)))
       luaG_runerror(L, "table index is NaN");
   }
   mp = mainpositionTV(t, key);

@@ -611,12 +670,22 @@
 
 
 /*
-** search function for integers
+** Search function for integers. If integer is inside 'alimit', get it
+** directly from the array part. Otherwise, if 'alimit' is not equal to
+** the real size of the array, key still can be in the array part. In
+** this case, try to avoid a call to 'luaH_realasize' when key is just
+** one more than the limit (so that it can be incremented without
+** changing the real size of the array).
 */
 const TValue *luaH_getint (Table *t, lua_Integer key) {
-  /* (1 <= key && key <= t->sizearray) */
-  if (l_castS2U(key) - 1u < t->sizearray)
+  if (l_castS2U(key) - 1u < t->alimit)  /* (1 <= key && key <= t->alimit)? */
+    return &t->array[key - 1];
+  else if (!limitequalsasize(t) &&  /* key still may be in the array part? */
+           (l_castS2U(key) == t->alimit + 1 ||
+            l_castS2U(key) - 1u < luaH_realasize(t))) {
+    t->alimit = cast_uint(key);  /* probably '#t' is here now */
     return &t->array[key - 1];
+  }
   else {
     Node *n = hashint(t, key);
     for (;;) {  /* check whether 'key' is somewhere in the chain */

@@ -628,7 +697,7 @@
         n += nx;
       }
     }
-    return luaH_emptyobject;
+    return &absentkey;
   }
 }
 

@@ -645,7 +714,7 @@
     else {
       int nx = gnext(n);
       if (nx == 0)
-        return luaH_emptyobject;  /* not found */
+        return &absentkey;  /* not found */
       n += nx;
     }
   }

@@ -670,7 +739,7 @@
   switch (ttypetag(key)) {
     case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key));
     case LUA_TNUMINT: return luaH_getint(t, ivalue(key));
-    case LUA_TNIL: return luaH_emptyobject;
+    case LUA_TNIL: return &absentkey;
     case LUA_TNUMFLT: {
       lua_Integer k;
       if (luaV_flttointeger(fltvalue(key), &k, 0)) /* index is an integral? */

@@ -689,7 +758,7 @@
 */
 TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
   const TValue *p = luaH_get(t, key);
-  if (p != luaH_emptyobject)
+  if (!isabstkey(p))
     return cast(TValue *, p);
   else return luaH_newkey(L, t, key);
 }

@@ -698,7 +767,7 @@
 void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
   const TValue *p = luaH_getint(t, key);
   TValue *cell;
-  if (p != luaH_emptyobject)
+  if (!isabstkey(p))
     cell = cast(TValue *, p);
   else {
     TValue k;

@@ -747,33 +816,92 @@
 }
 
 
+static unsigned int binsearch (const TValue *array, unsigned int i,
+                                                    unsigned int j) {
+  while (j - i > 1u) {  /* binary search */
+    unsigned int m = (i + j) / 2;
+    if (isempty(&array[m - 1])) j = m;
+    else i = m;
+  }
+  return i;
+}
+
+
 /*
 ** Try to find a boundary in table 't'. (A 'boundary' is an integer index
 ** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent
 ** and 'maxinteger' if t[maxinteger] is present.)
-** First, try the array part: if there is an array part and its last
-** element is absent, there must be a boundary there; a binary search
-** finds that boundary. Otherwise, if the hash part is empty or does not
-** contain 'j + 1', 'j' is a boundary. Otherwize, call 'hash_search'
-** to find a boundary in the hash part.
+** (In the next explanation, we use Lua indices, that is, with base 1.
+** The code itself uses base 0 when indexing the array part of the table.)
+** The code starts with 'limit', a position in the array part that may
+** be a boundary.
+** (1) If 't[limit]' is empty, there must be a boundary before it.
+** As a common case (e.g., after 't[#t]=nil'), check whether 'hint-1'
+** is present. If so, it is a boundary. Otherwise, do a binary search
+** between 0 and limit to find a boundary. In both cases, try to
+** use this boundary as the new 'limit', as a hint for the next call.
+** (2) If 't[limit]' is not empty and the array has more elements
+** after 'limit', try to find a boundary there. Again, try first
+** the special case (which should be quite frequent) where 'limit+1'
+** is empty, so that 'limit' is a boundary. Otherwise, check the
+** last element of the array part (set it as a new limit). If it is empty,
+** there must be a boundary between the old limit (present) and the new
+** limit (absent), which is found with a binary search. (This boundary
+** always can be a new limit.)
+** (3) The last case is when there are no elements in the array part
+** (limit == 0) or its last element (the new limit) is present.
+** In this case, must check the hash part. If there is no hash part,
+** the boundary is 0. Otherwise, if 'limit+1' is absent, 'limit' is
+** a boundary. Finally, if 'limit+1' is present, call 'hash_search'
+** to find a boundary in the hash part of the table. (In those
+** cases, the boundary is not inside the array part, and therefore
+** cannot be used as a new limit.)
 */
 lua_Unsigned luaH_getn (Table *t) {
-  unsigned int j = t->sizearray;
-  if (j > 0 && isempty(&t->array[j - 1])) {
-    unsigned int i = 0;
-    while (j - i > 1u) {  /* binary search */
-      unsigned int m = (i + j) / 2;
-      if (isempty(&t->array[m - 1])) j = m;
-      else i = m;
-    }
-    return i;
-  }
-  else {  /* 'j' is zero or present in table */
-    if (isdummy(t) || isempty(luaH_getint(t, l_castU2S(j + 1))))
-      return j;  /* 'j + 1' is absent... */
-    else  /* 'j + 1' is also present */
-      return hash_search(t, j);
+  unsigned int limit = t->alimit;
+  if (limit > 0 && isempty(&t->array[limit - 1])) {
+    /* (1) there must be a boundary before 'limit' */
+    if (limit >= 2 && !isempty(&t->array[limit - 2])) {
+      /* 'limit - 1' is a boundary; can it be a new limit? */
+      if (ispow2realasize(t) && !ispow2(limit - 1)) {
+        t->alimit = limit - 1;
+        setnorealasize(t);
+      }
+      return limit - 1;
+    }
+    else {  /* must search for a boundary in [0, limit] */
+      unsigned int boundary = binsearch(t->array, 0, limit);
+      /* can this boundary represent the real size of the array? */
+      if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) {
+        t->alimit = boundary;  /* use it as the new limit */
+        setnorealasize(t);
+      }
+      return boundary;
+    }
   }
+  /* 'limit' is zero or present in table */
+  if (!limitequalsasize(t)) {
+    /* (2) 'limit' > 0 and array has more elements after 'limit' */
+    if (isempty(&t->array[limit]))  /* 'limit + 1' is empty? */
+      return limit;  /* this is the boundary */
+    /* else, try last element in the array */
+    limit = luaH_realasize(t);
+    if (isempty(&t->array[limit - 1])) {  /* empty? */
+      /* there must be a boundary in the array after old limit,
+         and it must be a valid new limit */
+      unsigned int boundary = binsearch(t->array, t->alimit, limit);
+      t->alimit = boundary;
+      return boundary;
+    }
+    /* else, new limit is present in the table; check the hash part */
+  }
+  /* (3) 'limit' is the last element and either is zero or present in table */
+  lua_assert(limit == luaH_realasize(t) &&
+             (limit == 0 || !isempty(&t->array[limit - 1])));
+  if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1))))
+    return limit;  /* 'limit + 1' is absent... */
+  else  /* 'limit + 1' is also present */
+    return hash_search(t, limit);
 }
 
 

src/ltable.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 2.26 2018/02/23 13:13:31 roberto Exp $
+** $Id: ltable.h,v 2.28 2018/06/15 14:14:20 roberto Exp $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */

@@ -21,8 +21,6 @@
 /* true when 't' is using 'dummynode' as its hash part */
 #define isdummy(t)		((t)->lastfree == NULL)
 
-#define luaH_emptyobject	(&luaH_emptyobject_)
-
 
 /* allocated size for hash nodes */
 #define allocsizenode(t)	(isdummy(t) ? 0 : sizenode(t))

@@ -32,9 +30,6 @@
 #define nodefromval(v) 	cast(Node *, (v))
 
 
-LUAI_DDEC const TValue luaH_emptyobject_;
-
-
 LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key);
 LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key,
                                                     TValue *value);

@@ -50,6 +45,7 @@
 LUAI_FUNC void luaH_free (lua_State *L, Table *t);
 LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
 LUAI_FUNC lua_Unsigned luaH_getn (Table *t);
+LUAI_FUNC unsigned int luaH_realasize (const Table *t);
 
 
 #if defined(LUA_DEBUG)

src/ltablib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltablib.c,v 1.95 2018/02/27 18:47:32 roberto Exp $
+** $Id: ltablib.c,v 1.97 2018/04/04 14:23:41 roberto Exp $
 ** Library for Table Manipulation
 ** See Copyright Notice in lua.h
 */

@@ -95,8 +95,8 @@
     lua_geti(L, 1, pos + 1);
     lua_seti(L, 1, pos);  /* t[pos] = t[pos + 1] */
   }
-  lua_pushinteger(L, pos);
-  lua_removekey(L, 1);  /* remove entry t[pos] */
+  lua_pushnil(L);
+  lua_seti(L, 1, pos);  /* remove entry t[pos] */
   return 1;
 }
 

@@ -173,7 +173,7 @@
 ** =======================================================
 */
 
-static int pack (lua_State *L) {
+static int tpack (lua_State *L) {
   int i;
   int n = lua_gettop(L);  /* number of elements to pack */
   lua_createtable(L, n, 1);  /* create result table */

@@ -186,7 +186,7 @@
 }
 
 
-static int unpack (lua_State *L) {
+static int tunpack (lua_State *L) {
   lua_Unsigned n;
   lua_Integer i = luaL_optinteger(L, 2, 1);
   lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1));

@@ -408,8 +408,8 @@
 static const luaL_Reg tab_funcs[] = {
   {"concat", tconcat},
   {"insert", tinsert},
-  {"pack", pack},
-  {"unpack", unpack},
+  {"pack", tpack},
+  {"unpack", tunpack},
   {"remove", tremove},
   {"move", tmove},
   {"sort", sort},

src/ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 2.66 2018/02/27 17:48:28 roberto Exp $
+** $Id: ltm.c,v 2.70 2018/06/15 19:31:22 roberto Exp $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */

@@ -38,7 +38,6 @@
 void luaT_init (lua_State *L) {
   static const char *const luaT_eventname[] = {  /* ORDER TM */
     "__index", "__newindex",
-    "__undef", "__isdef",
     "__gc", "__mode", "__len", "__eq",
     "__add", "__sub", "__mul", "__mod", "__pow",
     "__div", "__idiv",

@@ -81,7 +80,7 @@
     default:
       mt = G(L)->mt[ttype(o)];
   }
-  return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject);
+  return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue);
 }
 
 

@@ -217,7 +216,7 @@
 
 
 void luaT_adjustvarargs (lua_State *L, int nfixparams, CallInfo *ci,
-                         Proto *p) {
+                         const Proto *p) {
   int i;
   int actual = cast_int(L->top - ci->func) - 1;  /* number of arguments */
   int nextra = actual - nfixparams;  /* number of extra arguments */

@@ -250,30 +249,3 @@
     setnilvalue(s2v(where + i));
 }
 
-
-int luaT_keydef (lua_State *L, TValue *obj, TValue *key, int remove) {
-  const TValue *tm;
-  TMS event = remove ? TM_UNDEF : TM_ISDEF;
-  if (!ttistable(obj)) {  /* not a table? */
-    tm = luaT_gettmbyobj(L, obj, event);  /* get its metamethod */
-    if (notm(tm)) {  /* no metamethod? */
-      const char *msg = remove ? "remove key from" : "check key from";
-      luaG_typeerror(L, obj, msg);  /* error */
-    }
-    /* else will call metamethod 'tm' */
-  }
-  else {  /* 'obj' is a table */
-    Table *t = hvalue(obj);
-    tm = fasttm(L, t->metatable, event);
-    if (tm == NULL) {  /* no metamethod? */
-      const TValue *val = luaH_get(t, key);  /* get entry */
-      int res = !isempty(val);  /* true if entry is not empty */
-      if (remove && res)  /* key is present and should be removed? */
-        setempty(cast(TValue*, val));  /* remove it */
-      return res;
-    }
-    /* else will call metamethod 'tm' */
-  }
-  luaT_callTMres(L, tm, obj, key, L->top);
-  return !l_isfalse(s2v(L->top));
-}

src/ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 2.34 2018/02/27 17:48:28 roberto Exp $
+** $Id: ltm.h,v 2.39 2018/06/18 12:51:05 roberto Exp $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */

@@ -9,7 +9,6 @@
 
 
 #include "lobject.h"
-#include "lstate.h"
 
 
 /*

@@ -19,8 +18,6 @@
 typedef enum {
   TM_INDEX,
   TM_NEWINDEX,
-  TM_UNDEF,
-  TM_ISDEF,
   TM_GC,
   TM_MODE,
   TM_LEN,

@@ -51,7 +48,7 @@
 ** Test whether there is no tagmethod.
 ** (Because tagmethods use raw accesses, the result may be an "empty" nil.)
 */
-#define notm(tm)	ttisnilorempty(tm)
+#define notm(tm)	ttisnil(tm)
 
 
 #define gfasttm(g,et,e) ((et) == NULL ? NULL : \

@@ -61,7 +58,7 @@
 
 #define ttypename(x)	luaT_typenames_[(x) + 1]
 
-LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS];
+LUAI_DDEC(const char *const luaT_typenames_[LUA_TOTALTAGS];)
 
 
 LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o);

@@ -87,11 +84,9 @@
                                  int inv, TMS event);
 
 LUAI_FUNC void luaT_adjustvarargs (lua_State *L, int nfixparams,
-                                   struct CallInfo *ci, Proto *p);
+                                   struct CallInfo *ci, const Proto *p);
 LUAI_FUNC void luaT_getvarargs (lua_State *L, struct CallInfo *ci,
                                               StkId where, int wanted);
 
-LUAI_FUNC int luaT_keydef (lua_State *L, TValue *obj, TValue *key, int remove);
-
 
 #endif

src/lua.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.234 2018/03/06 20:30:17 roberto Exp $
+** $Id: lua.c,v 1.235 2018/03/16 14:23:08 roberto Exp $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */

@@ -383,12 +383,15 @@
 
 #include <readline/readline.h>
 #include <readline/history.h>
+#define lua_initreadline(L)  \
+	((void)L, rl_readline_name="lua", rl_inhibit_completion=1)
 #define lua_readline(L,b,p)	((void)L, ((b)=readline(p)) != NULL)
 #define lua_saveline(L,line)	((void)L, add_history(line))
 #define lua_freeline(L,b)	((void)L, free(b))
 
 #else				/* }{ */
 
+#define lua_initreadline(L)  ((void)L)
 #define lua_readline(L,b,p) \
         ((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \
         fgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */

@@ -539,6 +542,7 @@
   int status;
   const char *oldprogname = progname;
   progname = NULL;  /* no 'progname' on errors in interactive mode */
+  lua_initreadline(L);
   while ((status = loadline(L)) != -1) {
     if (status == LUA_OK)
       status = docall(L, 0, LUA_MULTRET);

src/lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.344 2018/03/05 14:15:32 roberto Exp $
+** $Id: lua.h,v 1.347 2018/06/18 12:08:10 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,7 +19,7 @@
 #define LUA_VERSION_MAJOR	"5"
 #define LUA_VERSION_MINOR	"4"
 #define LUA_VERSION_NUM		504
-#define LUA_VERSION_RELEASE	"0" " (work1)"
+#define LUA_VERSION_RELEASE	"0"
 
 #define LUA_VERSION	"Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR
 #define LUA_RELEASE	LUA_VERSION "." LUA_VERSION_RELEASE

@@ -149,7 +149,7 @@
 LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);
 
 
-LUA_API const lua_Number *(lua_version) (lua_State *L);
+LUA_API lua_Number (lua_version) (lua_State *L);
 
 
 /*

@@ -331,9 +331,6 @@
 LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
 LUA_API void      (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
 
-LUA_API void (lua_removekey) (lua_State *L, int idx);
-LUA_API int (lua_keyin) (lua_State *L, int idx);
-
 
 /*
 ** {==============================================================

@@ -461,8 +458,8 @@
   unsigned char nparams;/* (u) number of parameters */
   char isvararg;        /* (u) */
   char istailcall;	/* (t) */
-  unsigned short fTransfer;/* (r) index of first value transfered */
-  unsigned short nTransfer;   /* (r) number of transfered values */
+  unsigned short ftransfer;   /* (r) index of first value transferred */
+  unsigned short ntransfer;   /* (r) number of transferred values */
   char short_src[LUA_IDSIZE]; /* (S) */
   /* private part */
   struct CallInfo *i_ci;  /* active function */

src/luac.c

@@ -1,8 +1,690 @@
+/*
+** $Id: luac.c,v 1.75 2015/03/12 01:58:27 lhf Exp $
+** Lua compiler (saves bytecodes to files; also lists bytecodes)
+** See Copyright Notice in lua.h
+*/
+
+#define luac_c
+#define LUA_CORE
+
+#include "lprefix.h"
+
+#include <ctype.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
+
+#include "lua.h"
+#include "lauxlib.h"
+
+#include "lobject.h"
+#include "lstate.h"
+#include "lundump.h"
+
+static void PrintFunction(const Proto* f, int full);
+#define luaU_print	PrintFunction
+
+#define PROGNAME	"luac"		/* default program name */
+#define OUTPUT		PROGNAME ".out"	/* default output file */
+
+static int listing=0;			/* list bytecodes? */
+static int dumping=1;			/* dump bytecodes? */
+static int stripping=0;			/* strip debug information? */
+static char Output[]={ OUTPUT };	/* default output file name */
+static const char* output=Output;	/* actual output file name */
+static const char* progname=PROGNAME;	/* actual program name */
+
+static void fatal(const char* message)
+{
+ fprintf(stderr,"%s: %s\n",progname,message);
+ exit(EXIT_FAILURE);
+}
+
+static void cannot(const char* what)
+{
+ fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno));
+ exit(EXIT_FAILURE);
+}
+
+static void usage(const char* message)
+{
+ if (*message=='-')
+  fprintf(stderr,"%s: unrecognized option '%s'\n",progname,message);
+ else
+  fprintf(stderr,"%s: %s\n",progname,message);
+ fprintf(stderr,
+  "usage: %s [options] [filenames]\n"
+  "Available options are:\n"
+  "  -l       list (use -l -l for full listing)\n"
+  "  -o name  output to file 'name' (default is \"%s\")\n"
+  "  -p       parse only\n"
+  "  -s       strip debug information\n"
+  "  -v       show version information\n"
+  "  --       stop handling options\n"
+  "  -        stop handling options and process stdin\n"
+  ,progname,Output);
+ exit(EXIT_FAILURE);
+}
+
+#define IS(s)	(strcmp(argv[i],s)==0)
+
+static int doargs(int argc, char* argv[])
+{
+ int i;
+ int version=0;
+ if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0];
+ for (i=1; i<argc; i++)
+ {
+  if (*argv[i]!='-')			/* end of options; keep it */
+   break;
+  else if (IS("--"))			/* end of options; skip it */
+  {
+   ++i;
+   if (version) ++version;
+   break;
+  }
+  else if (IS("-"))			/* end of options; use stdin */
+   break;
+  else if (IS("-l"))			/* list */
+   ++listing;
+  else if (IS("-o"))			/* output file */
+  {
+   output=argv[++i];
+   if (output==NULL || *output==0 || (*output=='-' && output[1]!=0))
+    usage("'-o' needs argument");
+   if (IS("-")) output=NULL;
+  }
+  else if (IS("-p"))			/* parse only */
+   dumping=0;
+  else if (IS("-s"))			/* strip debug information */
+   stripping=1;
+  else if (IS("-v"))			/* show version */
+   ++version;
+  else					/* unknown option */
+   usage(argv[i]);
+ }
+ if (i==argc && (listing || !dumping))
+ {
+  dumping=0;
+  argv[--i]=Output;
+ }
+ if (version)
+ {
+  printf("%s\n",LUA_COPYRIGHT);
+  if (version==argc-1) exit(EXIT_SUCCESS);
+ }
+ return i;
+}
+
+#define FUNCTION "(function()end)();"
+
+static const char* reader(lua_State* L, void* ud, size_t* size)
+{
+ UNUSED(L);
+ if ((*(int*)ud)--)
+ {
+  *size=sizeof(FUNCTION)-1;
+  return FUNCTION;
+ }
+ else
+ {
+  *size=0;
+  return NULL;
+ }
+}
+
+#define toproto(L,i) getproto(s2v(L->top+(i)))
+
+static const Proto* combine(lua_State* L, int n)
+{
+ if (n==1)
+  return toproto(L,-1);
+ else
+ {
+  Proto* f;
+  int i=n;
+  if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1));
+  f=toproto(L,-1);
+  for (i=0; i<n; i++)
+  {
+   f->p[i]=toproto(L,i-n-1);
+   if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0;
+  }
+  f->sizelineinfo=0;
+  return f;
+ }
+}
+
+static int writer(lua_State* L, const void* p, size_t size, void* u)
+{
+ UNUSED(L);
+ return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0);
+}
+
+static int pmain(lua_State* L)
+{
+ int argc=(int)lua_tointeger(L,1);
+ char** argv=(char**)lua_touserdata(L,2);
+ const Proto* f;
+ int i;
+ if (!lua_checkstack(L,argc)) fatal("too many input files");
+ for (i=0; i<argc; i++)
+ {
+  const char* filename=IS("-") ? NULL : argv[i];
+  if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1));
+ }
+ f=combine(L,argc);
+ if (listing) luaU_print(f,listing>1);
+ if (dumping)
+ {
+  FILE* D= (output==NULL) ? stdout : fopen(output,"wb");
+  if (D==NULL) cannot("open");
+  lua_lock(L);
+  luaU_dump(L,f,writer,D,stripping);
+  lua_unlock(L);
+  if (ferror(D)) cannot("write");
+  if (fclose(D)) cannot("close");
+ }
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ lua_State* L;
+ int i=doargs(argc,argv);
+ argc-=i; argv+=i;
+ if (argc<=0) usage("no input files given");
+ L=luaL_newstate();
+ if (L==NULL) fatal("cannot create state: not enough memory");
+ lua_pushcfunction(L,&pmain);
+ lua_pushinteger(L,argc);
+ lua_pushlightuserdata(L,argv);
+ if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1));
+ lua_close(L);
+ return EXIT_SUCCESS;
+}
+
+/*
+** print bytecodes
+*/
+
+#include <ctype.h>
+#include <stdio.h>
+
+#define luac_c
+#define LUA_CORE
+#define LUAI_DEFOPNAMES
+
+#include "ldebug.h"
+#include "lobject.h"
+#include "lopcodes.c"
+
+#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-")
+#define VOID(p) ((const void*)(p))
+#define getfuncline(f,pc) luaG_getfuncline((Proto *)f,pc)
+
+static void PrintString(const TString* ts)
+{
+ const char* s=getstr(ts);
+ size_t i,n=tsslen(ts);
+ printf("\"");
+ for (i=0; i<n; i++)
+ {
+  int c=(int)(unsigned char)s[i];
+  switch (c)
+  {
+   case '"':
+	printf("\\\"");
+	break;
+   case '\\':
+   	printf("\\\\");
+	break;
+   case '\a':
+   	printf("\\a");
+	break;
+   case '\b':
+   	printf("\\b");
+	break;
+   case '\f':
+   	printf("\\f");
+	break;
+   case '\n':
+   	printf("\\n");
+	break;
+   case '\r':
+   	printf("\\r");
+	break;
+   case '\t':
+   	printf("\\t");
+	break;
+   case '\v':
+   	printf("\\v");
+	break;
+   default:
+	if (isprint(c)) printf("%c",c); else printf("\\%03d",c);
+	break;
+  }
+ }
+ printf("\"");
+}
+
+static void PrintConstant(const Proto* f, int i)
+{
+ const TValue* o=&f->k[i];
+ switch (ttypetag(o))
+ {
+  case LUA_TNIL:
+	printf("nil");
+	break;
+  case LUA_TBOOLEAN:
+	printf(bvalue(o) ? "true" : "false");
+	break;
+  case LUA_TNUMFLT:
+	{
+	char buff[100];
+	sprintf(buff,LUA_NUMBER_FMT,fltvalue(o));
+	printf("%s",buff);
+	if (buff[strspn(buff,"-0123456789")]=='\0') printf(".0");
+	break;
+	}
+  case LUA_TNUMINT:
+	printf(LUA_INTEGER_FMT,ivalue(o));
+	break;
+  case LUA_TSHRSTR:
+  case LUA_TLNGSTR:
+	PrintString(tsvalue(o));
+	break;
+  default:				/* cannot happen */
+	printf("? type=%d",ttypetag(o));
+	break;
+ }
+}
+
+static void PrintCode(const Proto* f)
+{
+ const Instruction* code=f->code;
+ int pc,n=f->sizecode;
+ for (pc=0; pc<n; pc++)
+ {
+  Instruction i=code[pc];
+  OpCode o=GET_OPCODE(i);
+  int a=GETARG_A(i);
+  int b=GETARG_B(i);
+  int c=GETARG_C(i);
+  int ax=GETARG_Ax(i);
+  int bx=GETARG_Bx(i);
+  int sb=GETARG_sB(i);
+  int sc=GETARG_sC(i);
+  int sbx=GETARG_sBx(i);
+  int isk=GETARG_k(i);
+  int line=getfuncline(f,pc);
+  printf("\t%d\t",pc+1);
+  if (line>0) printf("[%d]\t",line); else printf("[-]\t");
+  printf("%-9s\t",luaP_opnames[o]);
+  switch (o)
+  {
+   case OP_MOVE:
+	printf("%d %d",a,b);
+	break;
+   case OP_LOADI:
+	printf("%d %d",a,sbx);
+	break;
+   case OP_LOADF:
+	printf("%d %d",a,sbx);
+	break;
+   case OP_LOADK:
+	printf("%d %d",a,bx);
+	printf("\t; "); PrintConstant(f,bx);
+	break;
+   case OP_LOADKX:
+	printf("%d",a);
+	break;
+   case OP_LOADBOOL:
+	printf("%d %d %d",a,b,c);
+	if (c) printf("\t; to %d",pc+2);
+	break;
+   case OP_LOADNIL:
+	printf("%d %d",a,b);
+	printf("\t; %d out",b+1);
+	break;
+   case OP_GETUPVAL:
+	printf("%d %d",a,b);
+	printf("\t; %s",UPVALNAME(b));
+	break;
+   case OP_SETUPVAL:
+	printf("%d %d",a,b);
+	printf("\t; %s",UPVALNAME(b));
+	break;
+   case OP_GETTABUP:
+	printf("%d %d %d",a,b,c);
+	printf("\t; %s",UPVALNAME(b));
+	printf(" "); PrintConstant(f,c);
+	break;
+   case OP_GETTABLE:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_GETI:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_GETFIELD:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c);
+	break;
+   case OP_SETTABUP:
+	printf("%d %d %d%s",a,b,c, isk ? "k" : "");
+	printf("\t; %s",UPVALNAME(a));
+	printf(" "); PrintConstant(f,b);
+	if (isk) { printf(" "); PrintConstant(f,c); }
+	break;
+   case OP_SETTABLE:
+	printf("%d %d %d%s",a,b,c, isk ? "k" : "");
+	if (isk) { printf("\t; "); PrintConstant(f,c); }
+	break;
+   case OP_SETI:
+	printf("%d %d %d%s",a,b,c, isk ? "k" : "");
+	if (isk) { printf("\t; "); PrintConstant(f,c); }
+	break;
+   case OP_SETFIELD:
+	printf("%d %d %d%s",a,b,c, isk ? "k" : "");
+	printf("\t; "); PrintConstant(f,b);
+	if (isk) { printf(" "); PrintConstant(f,c); }
+	break;
+   case OP_NEWTABLE:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_SELF:
+	printf("%d %d %d%s",a,b,c, isk ? "k" : "");
+	if (isk) { printf("\t; "); PrintConstant(f,c); }
+	break;
+   case OP_ADDI:
+	printf("%d %d %d",a,b,sc);
+	break;
+   case OP_SUBI:
+	printf("%d %d %d",a,b,sc);
+	break;
+   case OP_MULI:
+	printf("%d %d %d",a,b,sc);
+	break;
+   case OP_MODI:
+	printf("%d %d %d",a,b,sc);
+	break;
+   case OP_POWI:
+	printf("%d %d %d",a,b,sc);
+	break;
+   case OP_DIVI:
+	printf("%d %d %d",a,b,sc);
+	break;
+   case OP_IDIVI:
+	printf("%d %d %d",a,b,sc);
+	break;
+   case OP_BANDK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c); 
+	break;
+   case OP_BORK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c); 
+	break;
+   case OP_BXORK:
+	printf("%d %d %d",a,b,c);
+	printf("\t; "); PrintConstant(f,c); 
+	break;
+   case OP_SHRI:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_SHLI:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_ADD:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_SUB:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_MUL:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_MOD:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_POW:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_DIV:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_IDIV:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_BAND:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_BOR:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_BXOR:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_SHL:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_SHR:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_UNM:
+	printf("%d %d",a,b);
+	break;
+   case OP_BNOT:
+	printf("%d %d",a,b);
+	break;
+   case OP_NOT:
+	printf("%d %d",a,b);
+	break;
+   case OP_LEN:
+	printf("%d %d",a,b);
+	break;
+   case OP_CONCAT:
+	printf("%d %d",a,b);
+	break;
+   case OP_CLOSE:
+	printf("%d",a);
+	break;
+   case OP_JMP:
+	printf("%d",GETARG_sJ(i));
+	printf("\t; to %d",GETARG_sJ(i)+pc+2);
+	break;
+   case OP_EQ:
+	printf("%d %d %d",a,b,isk);
+	break;
+   case OP_LT:
+	printf("%d %d %d",a,b,isk);
+	break;
+   case OP_LE:
+	printf("%d %d %d",a,b,isk);
+	break;
+   case OP_EQK:
+	printf("%d %d %d",a,b,isk);
+	printf("\t; "); PrintConstant(f,b);
+	break;
+   case OP_EQI:
+	printf("%d %d %d",a,sb,isk);
+	break;
+   case OP_LTI:
+	printf("%d %d %d",a,sb,isk);
+	break;
+   case OP_LEI:
+	printf("%d %d %d",a,sb,isk);
+	break;
+   case OP_GTI:
+	printf("%d %d %d",a,sb,isk);
+	break;
+   case OP_GEI:
+	printf("%d %d %d",a,sb,isk);
+	break;
+   case OP_TEST:
+	printf("%d %d",a,isk);
+	break;
+   case OP_TESTSET:
+	printf("%d %d %d",a,b,isk);
+	break;
+   case OP_CALL:
+	printf("%d %d %d",a,b,c);
+	printf("\t; ");
+   	if (b==0) printf("all in "); else printf("%d in ",b-1);
+   	if (c==0) printf("all out"); else printf("%d out",c-1);
+	break;
+   case OP_TAILCALL:
+	printf("%d %d %d",a,b,c);
+	printf("\t; %d in",b-1);
+	break;
+   case OP_RETURN:
+	printf("%d %d %d",a,b,c);
+	printf("\t; ");
+   	if (b==0) printf("all out"); else printf("%d out",b-1);
+	break;
+   case OP_RETURN0:
+	break;
+   case OP_RETURN1:
+	printf("%d",a);
+	break;
+   case OP_FORLOOP1:
+	printf("%d %d",a,bx);
+	printf("\t; to %d",pc-bx+2);
+	break;
+   case OP_FORPREP1:
+	printf("%d %d",a,bx);
+	printf("\t; to %d",pc+bx+2);
+	break;
+   case OP_FORLOOP:
+	printf("%d %d",a,bx);
+	printf("\t; to %d",pc-bx+2);
+	break;
+   case OP_FORPREP:
+	printf("%d %d",a,bx);
+	printf("\t; to %d",pc+bx+2);
+	break;
+   case OP_TFORCALL:
+	printf("%d %d",a,c);
+	break;
+   case OP_TFORLOOP:
+	printf("%d %d",a,bx);
+	printf("\t; to %d",pc-bx+2);
+	break;
+   case OP_SETLIST:
+	printf("%d %d %d",a,b,c);
+	break;
+   case OP_CLOSURE:
+	printf("%d %d",a,bx);
+	printf("\t; %p",VOID(f->p[bx]));
+	break;
+   case OP_VARARG:
+	printf("%d %d",a,c);
+	printf("\t; ");
+   	if (c==0) printf("all out"); else printf("%d out",c-1);
+	break;
+   case OP_PREPVARARG:
+	printf("%d",a);
+	break;
+   case OP_EXTRAARG:
+	printf("%d",ax);
+	printf("\t; "); PrintConstant(f,ax);
+	break;
+  }
+  printf("\n");
+ }
+}
+
+static void riPrintCode(const Proto* p)
+{
+ const Instruction* code=p->code;
+ int pc,n=p->sizecode;
+ for (pc=0; pc<n; pc++)
+ {
+  Instruction i = code[pc];
+  OpCode o = GET_OPCODE(i);
+  const char *name = luaP_opnames[o];
+  int line = luaG_getfuncline(p, pc);
+  printf("(%4d) %4d - ", line, pc);
+  switch (getOpMode(o)) {
+    case iABC:
+      printf("%-12s%4d %4d %4d%s", name,
+              GETARG_A(i), GETARG_B(i), GETARG_C(i),
+              GETARG_k(i) ? " (k)" : "");
+      break;
+    case iABx:
+      printf("%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i));
+      break;
+    case iAsBx:
+      printf("%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i));
+      break;
+    case iAx:
+      printf("%-12s%4d", name, GETARG_Ax(i));
+      break;
+    case isJ:
+      printf("%-12s%4d (%1d)", name, GETARG_sJ(i), !!GETARG_m(i));
+      break;
+  }
+ printf("\n");
+ }
+}
+
+#define SS(x)	((x==1)?"":"s")
+#define S(x)	(int)(x),SS(x)
+
+static void PrintHeader(const Proto* f)
+{
+ const char* s=f->source ? getstr(f->source) : "=?";
+ if (*s=='@' || *s=='=')
+  s++;
+ else if (*s==LUA_SIGNATURE[0])
+  s="(bstring)";
+ else
+  s="(string)";
+ printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n",
+	(f->linedefined==0)?"main":"function",s,
+	f->linedefined,f->lastlinedefined,
+	S(f->sizecode),VOID(f));
+ printf("%d%s param%s, %d slot%s, %d upvalue%s, ",
+	(int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams),
+	S(f->maxstacksize),S(f->sizeupvalues));
+ printf("%d local%s, %d constant%s, %d function%s\n",
+	S(f->sizelocvars),S(f->sizek),S(f->sizep));
+}
+
+static void PrintDebug(const Proto* f)
+{
+ int i,n;
+ n=f->sizek;
+ printf("constants (%d) for %p:\n",n,VOID(f));
+ for (i=0; i<n; i++)
+ {
+  printf("\t%d\t",i+1);
+  PrintConstant(f,i);
+  printf("\n");
+ }
+ n=f->sizelocvars;
+ printf("locals (%d) for %p:\n",n,VOID(f));
+ for (i=0; i<n; i++)
+ {
+  printf("\t%d\t%s\t%d\t%d\n",
+  i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1);
+ }
+ n=f->sizeupvalues;
+ printf("upvalues (%d) for %p:\n",n,VOID(f));
+ for (i=0; i<n; i++)
+ {
+  printf("\t%d\t%s\t%d\t%d\n",
+  i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx);
+ }
+}
 
-int main(void)
+static void PrintFunction(const Proto* f, int full)
 {
- fprintf(stderr,"luac: not yet ready\n");
- return EXIT_FAILURE;
+ int i,n=f->sizep;
+ PrintHeader(f);
+ riPrintCode(f);
+ PrintCode(f);
+ if (full) PrintDebug(f);
+ for (i=0; i<n; i++) PrintFunction(f->p[i],full);
 }

src/luaconf.h

@@ -1,5 +1,5 @@
 /*
-** $Id: luaconf.h,v 1.267 2018/03/09 14:56:02 roberto Exp $
+** $Id: luaconf.h,v 1.270 2018/06/18 12:51:05 roberto Exp $
 ** Configuration file for Lua
 ** See Copyright Notice in lua.h
 */

@@ -254,16 +254,20 @@
 #endif				/* } */
 
 
-/* more often than not the libs go together with the core */
+/*
+** More often than not the libs go together with the core;
+** Functions from the auxiliary library must be exported,
+** but opening functions do not.
+*/
 #define LUALIB_API	LUA_API
-#define LUAMOD_API	LUALIB_API
+#define LUAMOD_API	LUAI_FUNC
 
 
 /*
 @@ LUAI_FUNC is a mark for all extern functions that are not to be
 ** exported to outside modules.
-@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables
-** that are not to be exported to outside modules (LUAI_DDEF for
+@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables,
+** none of which to be exported to outside modules (LUAI_DDEF for
 ** definitions and LUAI_DDEC for declarations).
 ** CHANGE them if you need to mark them in some special way. Elf/gcc
 ** (versions 3.2 and later) mark them as "hidden" to optimize access

@@ -280,7 +284,7 @@
 #define LUAI_FUNC	extern
 #endif				/* } */
 
-#define LUAI_DDEC	LUAI_FUNC
+#define LUAI_DDEC(dec)	LUAI_FUNC dec
 #define LUAI_DDEF	/* empty */
 
 /* }================================================================== */

@@ -447,6 +451,7 @@
 @@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER.
 @@ LUA_MININTEGER is the minimum value for a LUA_INTEGER.
 @@ LUA_MAXUNSIGNED is the maximum value for a LUA_UNSIGNED.
+@@ LUA_UNSIGNEDBITS is the number of bits in a LUA_UNSIGNED.
 @@ lua_integer2str converts an integer to a string.
 */
 

@@ -468,6 +473,8 @@
 
 #define LUA_MAXUNSIGNED		(~(lua_Unsigned)0)
 
+#define LUA_UNSIGNEDBITS	(sizeof(LUA_UNSIGNED) * CHAR_BIT)
+
 
 /* now the variable definitions */
 

@@ -696,21 +703,13 @@
 
 /*
 @@ LUAI_MAXALIGN defines fields that, when used in a union, ensure
-** "maximum" alignment for the other items in that union.
+** maximum alignment for the other items in that union.
 */
 #define LUAI_MAXALIGN  lua_Number n; double u; void *s; lua_Integer i; long l
 
 /* }================================================================== */
 
 
-/*
-@@ LUA_QL describes how error messages quote program elements.
-** Lua does not use these macros anymore; they are here for
-** compatibility only.
-*/
-#define LUA_QL(x)	"'" x "'"
-#define LUA_QS		LUA_QL("%s")
-
 
 
 

src/lundump.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lundump.c,v 2.49 2017/12/07 18:59:52 roberto Exp $
+** $Id: lundump.c,v 2.50 2018/06/01 16:45:58 roberto Exp $
 ** load precompiled Lua chunks
 ** See Copyright Notice in lua.h
 */

@@ -36,7 +36,7 @@
 } LoadState;
 
 
-static l_noret error(LoadState *S, const char *why) {
+static l_noret error (LoadState *S, const char *why) {
   luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why);
   luaD_throw(S->L, LUA_ERRSYNTAX);
 }

@@ -95,7 +95,10 @@
 }
 
 
-static TString *LoadString (LoadState *S) {
+/*
+** Load a nullable string
+*/
+static TString *LoadStringN (LoadState *S) {
   size_t size = LoadSize(S);
   if (size == 0)
     return NULL;

@@ -112,6 +115,17 @@
 }
 
 
+/*
+** Load a non-nullable string.
+*/
+static TString *LoadString (LoadState *S) {
+  TString *st = LoadStringN(S);
+  if (st == NULL)
+    error(S, "bad format for constant string");
+  return st;
+}
+
+
 static void LoadCode (LoadState *S, Proto *f) {
   int n = LoadInt(S);
   f->code = luaM_newvectorchecked(S->L, n, Instruction);

@@ -203,18 +217,18 @@
   for (i = 0; i < n; i++)
     f->locvars[i].varname = NULL;
   for (i = 0; i < n; i++) {
-    f->locvars[i].varname = LoadString(S);
+    f->locvars[i].varname = LoadStringN(S);
     f->locvars[i].startpc = LoadInt(S);
     f->locvars[i].endpc = LoadInt(S);
   }
   n = LoadInt(S);
   for (i = 0; i < n; i++)
-    f->upvalues[i].name = LoadString(S);
+    f->upvalues[i].name = LoadStringN(S);
 }
 
 
 static void LoadFunction (LoadState *S, Proto *f, TString *psource) {
-  f->source = LoadString(S);
+  f->source = LoadStringN(S);
   if (f->source == NULL)  /* no source in dump? */
     f->source = psource;  /* reuse parent's source */
   f->linedefined = LoadInt(S);

src/lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.350 2018/03/07 15:55:38 roberto Exp $
+** $Id: lvm.c,v 2.359 2018/06/18 17:58:21 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -36,7 +36,11 @@
 ** and compatible compilers.
 */
 #if !defined(LUA_USE_JUMPTABLE)
-#define LUA_USE_JUMPTABLE	defined(__GNUC__)
+#if defined(__GNUC__)
+#define LUA_USE_JUMPTABLE	1
+#else
+#define LUA_USE_JUMPTABLE	0
+#endif
 #endif
 
 

@@ -46,24 +50,28 @@
 
 
 /*
-** 'l_intfitsf' checks whether a given integer can be converted to a
-** float without rounding. Used in comparisons.
+** 'l_intfitsf' checks whether a given integer is in the range that
+** can be converted to a float without rounding. Used in comparisons.
 */
+
 /* number of bits in the mantissa of a float */
 #define NBM		(l_mathlim(MANT_DIG))
 
 /*
-** Check whether some integers may not fit in a float, that is, whether
-** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger).
-** (The shifts are done in parts to avoid shifting by more than the size
+** Check whether some integers may not fit in a float, testing whether
+** (maxinteger >> NBM) > 0. (That implies (1 << NBM) <= maxinteger.)
+** (The shifts are done in parts, to avoid shifting by more than the size
 ** of an integer. In a worst case, NBM == 113 for long double and
-** sizeof(integer) == 32.)
+** sizeof(long) == 32.)
 */
 #if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \
 	>> (NBM - (3 * (NBM / 4))))  >  0
 
-#define l_intfitsf(i)  \
-  (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM))
+/* limit for integers that fit in a float */
+#define MAXINTFITSF	((lua_Unsigned)1 << NBM)
+
+/* check whether 'i' is in the interval [-MAXINTFITSF, MAXINTFITSF] */
+#define l_intfitsf(i)	((MAXINTFITSF + l_castS2U(i)) <= (2 * MAXINTFITSF))
 
 #else  /* all integers fit in a float precisely */
 

@@ -188,7 +196,7 @@
     if (slot == NULL) {  /* 't' is not a table? */
       lua_assert(!ttistable(t));
       tm = luaT_gettmbyobj(L, t, TM_INDEX);
-      if (notm(tm))
+      if (unlikely(notm(tm)))
         luaG_typeerror(L, t, "index");  /* no metamethod */
       /* else will try the metamethod */
     }

@@ -219,9 +227,9 @@
 /*
 ** Finish a table assignment 't[key] = val'.
 ** If 'slot' is NULL, 't' is not a table.  Otherwise, 'slot' points
-** to the entry 't[key]', or to 'luaH_emptyobject' if there is no such
-** entry.  (The value at 'slot' must be empty, otherwise 'luaV_fastget'
-** would have done the job.)
+** to the entry 't[key]', or to a value with an absent key if there
+** is no such entry.  (The value at 'slot' must be empty, otherwise
+** 'luaV_fastget' would have done the job.)
 */
 void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
                      TValue *val, const TValue *slot) {

@@ -233,7 +241,7 @@
       lua_assert(isempty(slot));  /* slot must be empty */
       tm = fasttm(L, h->metatable, TM_NEWINDEX);  /* get metamethod */
       if (tm == NULL) {  /* no metamethod? */
-        if (slot == luaH_emptyobject)  /* no previous entry? */
+        if (isabstkey(slot))  /* no previous entry? */
           slot = luaH_newkey(L, h, key);  /* create one */
         /* no metamethod and (now) there is an entry with given key */
         setobj2t(L, cast(TValue *, slot), val);  /* set its new value */

@@ -245,7 +253,7 @@
     }
     else {  /* not a table; check metamethod */
       tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
-      if (notm(tm))
+      if (unlikely(notm(tm)))
         luaG_typeerror(L, t, "index");
     }
     /* try the metamethod */

@@ -481,7 +489,7 @@
     case LUA_TNIL: return 1;
     case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2));
     case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2));
-    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */
+    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1! */
     case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);
     case LUA_TLCF: return fvalue(t1) == fvalue(t2);
     case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2));

@@ -553,7 +561,7 @@
       /* collect total length and number of strings */
       for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
         size_t l = vslen(s2v(top - n - 1));
-        if (l >= (MAX_SIZE/sizeof(char)) - tl)
+        if (unlikely(l >= (MAX_SIZE/sizeof(char)) - tl))
           luaG_runerror(L, "string length overflow");
         tl += l;
       }

@@ -597,7 +605,7 @@
     }
     default: {  /* try metamethod */
       tm = luaT_gettmbyobj(L, rb, TM_LEN);
-      if (notm(tm))  /* no metamethod? */
+      if (unlikely(notm(tm)))  /* no metamethod? */
         luaG_typeerror(L, rb, "get length of");
       break;
     }

@@ -614,7 +622,7 @@
 */
 lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) {
   if (l_castS2U(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
-    if (n == 0)
+    if (unlikely(n == 0))
       luaG_runerror(L, "attempt to divide by zero");
     return intop(-, 0, m);   /* n==-1; avoid overflow with 0x80000...//-1 */
   }

@@ -634,7 +642,7 @@
 */
 lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) {
   if (l_castS2U(n) + 1u <= 1u) {  /* special cases: -1 or 0 */
-    if (n == 0)
+    if (unlikely(n == 0))
       luaG_runerror(L, "attempt to perform 'n%%0'");
     return 0;   /* m % -1 == 0; avoid overflow with 0x80000...%-1 */
   }

@@ -704,7 +712,7 @@
       ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx);
     else  /* get upvalue from enclosing function */
       ncl->upvals[i] = encup[uv[i].idx];
-    /* new closure is white, so we do not need a barrier here */
+    luaC_objbarrier(L, ncl, ncl->upvals[i]);
   }
   if (p->cachemiss >= MAXMISS)  /* too many missings? */
     p->cache = NULL;  /* give up cache */

@@ -859,15 +867,12 @@
 
 /* fetch an instruction and prepare its execution */
 #define vmfetch()	{ \
-  i = *(pc++); \
-  if (trap) { \
-    if (!(L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT))) \
-      trap = ci->u.l.trap = 0;  /* no need to stop again */ \
-    else { savepc(L); luaG_traceexec(L); } \
-    updatebase(ci);  /* the trap may be just for that */ \
+  if (trap) {  /* stack reallocation or hooks? */ \
+    trap = luaG_traceexec(L, pc);  /* handle hooks */ \
+    updatebase(ci);  /* correct stack */ \
   } \
+  i = *(pc++); \
   ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \
-  vra = s2v(ra); \
 }
 
 #define vmdispatch(o)	switch(o)

@@ -891,7 +896,7 @@
   pc = ci->u.l.savedpc;
   if (trap) {
     if (cl->p->is_vararg)
-      trap = 0;  /* hooks will start with PREPVARARG instruction */
+      trap = 0;  /* hooks will start after PREPVARARG instruction */
     else if (pc == cl->p->code)  /* first instruction (not resuming)? */
       luaD_hookcall(L, ci);
     ci->u.l.trap = 1;  /* there may be other hooks */

@@ -902,7 +907,6 @@
     int cond;  /* flag for conditional jumps */
     Instruction i;  /* instruction being executed */
     StkId ra;  /* instruction's A register */
-    TValue *vra;  /* corresponding value */
     vmfetch();
     lua_assert(base == ci->func + 1);
     lua_assert(base <= L->top && L->top < L->stack + L->stacksize);

@@ -919,12 +923,12 @@
       }
       vmcase(OP_LOADI) {
         lua_Integer b = GETARG_sBx(i);
-        setivalue(vra, b);
+        setivalue(s2v(ra), b);
         vmbreak;
       }
       vmcase(OP_LOADF) {
         int b = GETARG_sBx(i);
-        setfltvalue(vra, cast_num(b));
+        setfltvalue(s2v(ra), cast_num(b));
         vmbreak;
       }
       vmcase(OP_LOADKX) {

@@ -934,7 +938,7 @@
         vmbreak;
       }
       vmcase(OP_LOADBOOL) {
-        setbvalue(vra, GETARG_B(i));
+        setbvalue(s2v(ra), GETARG_B(i));
         if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */
         vmbreak;
       }

@@ -952,8 +956,8 @@
       }
       vmcase(OP_SETUPVAL) {
         UpVal *uv = cl->upvals[GETARG_B(i)];
-        setobj(L, uv->v, vra);
-        luaC_barrier(L, uv, vra);
+        setobj(L, uv->v, s2v(ra));
+        luaC_barrier(L, uv, s2v(ra));
         vmbreak;
       }
       vmcase(OP_GETTABUP) {

@@ -1027,25 +1031,25 @@
         TValue *rc = RKC(i);  /* value */
         lua_Unsigned n;
         if (ttisinteger(rb)  /* fast track for integers? */
-            ? (n = ivalue(rb), luaV_fastgeti(L, vra, n, slot))
-            : luaV_fastget(L, vra, rb, slot, luaH_get)) {
-          luaV_finishfastset(L, vra, slot, rc);
+            ? (n = ivalue(rb), luaV_fastgeti(L, s2v(ra), n, slot))
+            : luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) {
+          luaV_finishfastset(L, s2v(ra), slot, rc);
         }
         else
-          Protect(luaV_finishset(L, vra, rb, rc, slot));
+          Protect(luaV_finishset(L, s2v(ra), rb, rc, slot));
         vmbreak;
       }
       vmcase(OP_SETI) {
         const TValue *slot;
         int c = GETARG_B(i);
         TValue *rc = RKC(i);
-        if (luaV_fastgeti(L, vra, c, slot)) {
-          luaV_finishfastset(L, vra, slot, rc);
+        if (luaV_fastgeti(L, s2v(ra), c, slot)) {
+          luaV_finishfastset(L, s2v(ra), slot, rc);
         }
         else {
           TValue key;
           setivalue(&key, c);
-          Protect(luaV_finishset(L, vra, &key, rc, slot));
+          Protect(luaV_finishset(L, s2v(ra), &key, rc, slot));
         }
         vmbreak;
       }

@@ -1054,11 +1058,11 @@
         TValue *rb = KB(i);
         TValue *rc = RKC(i);
         TString *key = tsvalue(rb);  /* key must be a string */
-        if (luaV_fastget(L, vra, key, slot, luaH_getshortstr)) {
-          luaV_finishfastset(L, vra, slot, rc);
+        if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) {
+          luaV_finishfastset(L, s2v(ra), slot, rc);
         }
         else
-          Protect(luaV_finishset(L, vra, rb, rc, slot));
+          Protect(luaV_finishset(L, s2v(ra), rb, rc, slot));
         vmbreak;
       }
       vmcase(OP_NEWTABLE) {

@@ -1091,10 +1095,10 @@
         int ic = GETARG_sC(i);
         lua_Number nb;
         if (ttisinteger(rb)) {
-          setivalue(vra, intop(+, ivalue(rb), ic));
+          setivalue(s2v(ra), intop(+, ivalue(rb), ic));
         }
         else if (tonumberns(rb, nb)) {
-          setfltvalue(vra, luai_numadd(L, nb, cast_num(ic)));
+          setfltvalue(s2v(ra), luai_numadd(L, nb, cast_num(ic)));
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, GETARG_k(i), ra, TM_ADD));

@@ -1105,10 +1109,10 @@
         int ic = GETARG_sC(i);
         lua_Number nb;
         if (ttisinteger(rb)) {
-          setivalue(vra, intop(-, ivalue(rb), ic));
+          setivalue(s2v(ra), intop(-, ivalue(rb), ic));
         }
         else if (tonumberns(rb, nb)) {
-          setfltvalue(vra, luai_numsub(L, nb, cast_num(ic)));
+          setfltvalue(s2v(ra), luai_numsub(L, nb, cast_num(ic)));
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_SUB));

@@ -1119,10 +1123,10 @@
         int ic = GETARG_sC(i);
         lua_Number nb;
         if (ttisinteger(rb)) {
-          setivalue(vra, intop(*, ivalue(rb), ic));
+          setivalue(s2v(ra), intop(*, ivalue(rb), ic));
         }
         else if (tonumberns(rb, nb)) {
-          setfltvalue(vra, luai_nummul(L, nb, cast_num(ic)));
+          setfltvalue(s2v(ra), luai_nummul(L, nb, cast_num(ic)));
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, GETARG_k(i), ra, TM_MUL));

@@ -1133,13 +1137,13 @@
         int ic = GETARG_sC(i);
         lua_Number nb;
         if (ttisinteger(rb)) {
-          setivalue(vra, luaV_mod(L, ivalue(rb), ic));
+          setivalue(s2v(ra), luaV_mod(L, ivalue(rb), ic));
         }
         else if (tonumberns(rb, nb)) {
           lua_Number m;
           lua_Number nc = cast_num(ic);
           luai_nummod(L, nb, nc, m);
-          setfltvalue(vra, m);
+          setfltvalue(s2v(ra), m);
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_MOD));

@@ -1151,7 +1155,7 @@
         lua_Number nb;
         if (tonumberns(rb, nb)) {
           lua_Number nc = cast_num(ic);
-          setfltvalue(vra, luai_numpow(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numpow(L, nb, nc));
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_POW));

@@ -1163,7 +1167,7 @@
         lua_Number nb;
         if (tonumberns(rb, nb)) {
           lua_Number nc = cast_num(ic);
-          setfltvalue(vra, luai_numdiv(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_DIV));

@@ -1174,11 +1178,11 @@
         int ic = GETARG_sC(i);
         lua_Number nb;
         if (ttisinteger(rb)) {
-          setivalue(vra, luaV_div(L, ivalue(rb), ic));
+          setivalue(s2v(ra), luaV_div(L, ivalue(rb), ic));
         }
         else if (tonumberns(rb, nb)) {
           lua_Number nc = cast_num(ic);
-          setfltvalue(vra, luai_numdiv(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, 0, ra, TM_IDIV));

@@ -1190,10 +1194,10 @@
         lua_Number nb; lua_Number nc;
         if (ttisinteger(rb) && ttisinteger(rc)) {
           lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(vra, intop(+, ib, ic));
+          setivalue(s2v(ra), intop(+, ib, ic));
         }
         else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(vra, luai_numadd(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numadd(L, nb, nc));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD));

@@ -1205,10 +1209,10 @@
         lua_Number nb; lua_Number nc;
         if (ttisinteger(rb) && ttisinteger(rc)) {
           lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(vra, intop(-, ib, ic));
+          setivalue(s2v(ra), intop(-, ib, ic));
         }
         else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(vra, luai_numsub(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numsub(L, nb, nc));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB));

@@ -1220,10 +1224,10 @@
         lua_Number nb; lua_Number nc;
         if (ttisinteger(rb) && ttisinteger(rc)) {
           lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(vra, intop(*, ib, ic));
+          setivalue(s2v(ra), intop(*, ib, ic));
         }
         else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(vra, luai_nummul(L, nb, nc));
+          setfltvalue(s2v(ra), luai_nummul(L, nb, nc));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL));

@@ -1234,7 +1238,7 @@
         TValue *rc = vRC(i);
         lua_Number nb; lua_Number nc;
         if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(vra, luai_numdiv(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numdiv(L, nb, nc));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV));

@@ -1245,7 +1249,7 @@
         TValue *p2 = KC(i);
         lua_Integer i1;
         if (tointegerns(p1, &i1)) {
-          setivalue(vra, intop(&, i1, ivalue(p2)));
+          setivalue(s2v(ra), intop(&, i1, ivalue(p2)));
         }
         else
           Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BAND));

@@ -1256,7 +1260,7 @@
         TValue *p2 = KC(i);
         lua_Integer i1;
         if (tointegerns(p1, &i1)) {
-          setivalue(vra, intop(|, i1, ivalue(p2)));
+          setivalue(s2v(ra), intop(|, i1, ivalue(p2)));
         }
         else
           Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BOR));

@@ -1267,7 +1271,7 @@
         TValue *p2 = KC(i);
         lua_Integer i1;
         if (tointegerns(p1, &i1)) {
-          setivalue(vra, intop(^, i1, ivalue(p2)));
+          setivalue(s2v(ra), intop(^, i1, ivalue(p2)));
         }
         else
           Protect(luaT_trybinassocTM(L, p1, p2, ra, TESTARG_k(i), TM_BXOR));

@@ -1278,7 +1282,7 @@
         TValue *rc = vRC(i);
         lua_Integer ib; lua_Integer ic;
         if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(vra, intop(&, ib, ic));
+          setivalue(s2v(ra), intop(&, ib, ic));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND));

@@ -1289,7 +1293,7 @@
         TValue *rc = vRC(i);
         lua_Integer ib; lua_Integer ic;
         if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(vra, intop(|, ib, ic));
+          setivalue(s2v(ra), intop(|, ib, ic));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR));

@@ -1300,7 +1304,7 @@
         TValue *rc = vRC(i);
         lua_Integer ib; lua_Integer ic;
         if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(vra, intop(^, ib, ic));
+          setivalue(s2v(ra), intop(^, ib, ic));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR));

@@ -1311,7 +1315,7 @@
         int ic = GETARG_sC(i);
         lua_Integer ib;
         if (tointegerns(rb, &ib)) {
-          setivalue(vra, luaV_shiftl(ib, -ic));
+          setivalue(s2v(ra), luaV_shiftl(ib, -ic));
         }
         else {
           TMS ev = TM_SHR;

@@ -1327,7 +1331,7 @@
         int ic = GETARG_sC(i);
         lua_Integer ib;
         if (tointegerns(rb, &ib)) {
-          setivalue(vra, luaV_shiftl(ic, ib));
+          setivalue(s2v(ra), luaV_shiftl(ic, ib));
         }
         else
           Protect(luaT_trybiniTM(L, rb, ic, 1, ra, TM_SHL));

@@ -1338,7 +1342,7 @@
         TValue *rc = vRC(i);
         lua_Integer ib; lua_Integer ic;
         if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(vra, luaV_shiftl(ib, ic));
+          setivalue(s2v(ra), luaV_shiftl(ib, ic));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL));

@@ -1349,7 +1353,7 @@
         TValue *rc = vRC(i);
         lua_Integer ib; lua_Integer ic;
         if (tointegerns(rb, &ib) && tointegerns(rc, &ic)) {
-          setivalue(vra, luaV_shiftl(ib, -ic));
+          setivalue(s2v(ra), luaV_shiftl(ib, -ic));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR));

@@ -1361,12 +1365,12 @@
         lua_Number nb; lua_Number nc;
         if (ttisinteger(rb) && ttisinteger(rc)) {
           lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(vra, luaV_mod(L, ib, ic));
+          setivalue(s2v(ra), luaV_mod(L, ib, ic));
         }
         else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
           lua_Number m;
           luai_nummod(L, nb, nc, m);
-          setfltvalue(vra, m);
+          setfltvalue(s2v(ra), m);
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD));

@@ -1378,10 +1382,10 @@
         lua_Number nb; lua_Number nc;
         if (ttisinteger(rb) && ttisinteger(rc)) {
           lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc);
-          setivalue(vra, luaV_div(L, ib, ic));
+          setivalue(s2v(ra), luaV_div(L, ib, ic));
         }
         else if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(vra, luai_numidiv(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numidiv(L, nb, nc));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV));

@@ -1392,7 +1396,7 @@
         TValue *rc = vRC(i);
         lua_Number nb; lua_Number nc;
         if (tonumberns(rb, nb) && tonumberns(rc, nc)) {
-          setfltvalue(vra, luai_numpow(L, nb, nc));
+          setfltvalue(s2v(ra), luai_numpow(L, nb, nc));
         }
         else
           Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW));

@@ -1403,10 +1407,10 @@
         lua_Number nb;
         if (ttisinteger(rb)) {
           lua_Integer ib = ivalue(rb);
-          setivalue(vra, intop(-, 0, ib));
+          setivalue(s2v(ra), intop(-, 0, ib));
         }
         else if (tonumberns(rb, nb)) {
-          setfltvalue(vra, luai_numunm(L, nb));
+          setfltvalue(s2v(ra), luai_numunm(L, nb));
         }
         else
           Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM));

@@ -1416,7 +1420,7 @@
         TValue *rb = vRB(i);
         lua_Integer ib;
         if (tointegerns(rb, &ib)) {
-          setivalue(vra, intop(^, ~l_castS2U(0), ib));
+          setivalue(s2v(ra), intop(^, ~l_castS2U(0), ib));
         }
         else
           Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT));

@@ -1425,7 +1429,7 @@
       vmcase(OP_NOT) {
         TValue *rb = vRB(i);
         int nrb = l_isfalse(rb);  /* next assignment may change this value */
-        setbvalue(vra, nrb);
+        setbvalue(s2v(ra), nrb);
         vmbreak;
       }
       vmcase(OP_LEN) {

@@ -1449,45 +1453,45 @@
       }
       vmcase(OP_EQ) {
         TValue *rb = vRB(i);
-        Protect(cond = luaV_equalobj(L, vra, rb));
+        Protect(cond = luaV_equalobj(L, s2v(ra), rb));
         docondjump();
         vmbreak;
       }
       vmcase(OP_LT) {
         TValue *rb = vRB(i);
-        if (ttisinteger(vra) && ttisinteger(rb))
-          cond = (ivalue(vra) < ivalue(rb));
-        else if (ttisnumber(vra) && ttisnumber(rb))
-          cond = LTnum(vra, rb);
+        if (ttisinteger(s2v(ra)) && ttisinteger(rb))
+          cond = (ivalue(s2v(ra)) < ivalue(rb));
+        else if (ttisnumber(s2v(ra)) && ttisnumber(rb))
+          cond = LTnum(s2v(ra), rb);
         else
-          Protect(cond = lessthanothers(L, vra, rb));
+          Protect(cond = lessthanothers(L, s2v(ra), rb));
         docondjump();
         vmbreak;
       }
       vmcase(OP_LE) {
         TValue *rb = vRB(i);
-        if (ttisinteger(vra) && ttisinteger(rb))
-          cond = (ivalue(vra) <= ivalue(rb));
-        else if (ttisnumber(vra) && ttisnumber(rb))
-          cond = LEnum(vra, rb);
+        if (ttisinteger(s2v(ra)) && ttisinteger(rb))
+          cond = (ivalue(s2v(ra)) <= ivalue(rb));
+        else if (ttisnumber(s2v(ra)) && ttisnumber(rb))
+          cond = LEnum(s2v(ra), rb);
         else
-          Protect(cond = lessequalothers(L, vra, rb));
+          Protect(cond = lessequalothers(L, s2v(ra), rb));
         docondjump();
         vmbreak;
       }
       vmcase(OP_EQK) {
         TValue *rb = KB(i);
         /* basic types do not use '__eq'; we can use raw equality */
-        cond = luaV_equalobj(NULL, vra, rb);
+        cond = luaV_equalobj(NULL, s2v(ra), rb);
         docondjump();
         vmbreak;
       }
       vmcase(OP_EQI) {
         int im = GETARG_sB(i);
-        if (ttisinteger(vra))
-          cond = (ivalue(vra) == im);
-        else if (ttisfloat(vra))
-          cond = luai_numeq(fltvalue(vra), cast_num(im));
+        if (ttisinteger(s2v(ra)))
+          cond = (ivalue(s2v(ra)) == im);
+        else if (ttisfloat(s2v(ra)))
+          cond = luai_numeq(fltvalue(s2v(ra)), cast_num(im));
         else
           cond = 0;  /* other types cannot be equal to a number */
         docondjump();

@@ -1495,50 +1499,50 @@
       }
       vmcase(OP_LTI) {
         int im = GETARG_sB(i);
-        if (ttisinteger(vra))
-          cond = (ivalue(vra) < im);
-        else if (ttisfloat(vra))
-          cond = luai_numlt(fltvalue(vra), cast_num(im));
+        if (ttisinteger(s2v(ra)))
+          cond = (ivalue(s2v(ra)) < im);
+        else if (ttisfloat(s2v(ra)))
+          cond = luai_numlt(fltvalue(s2v(ra)), cast_num(im));
         else
-          Protect(cond = luaT_callorderiTM(L, vra, im, 0, TM_LT));
+          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 0, TM_LT));
         docondjump();
         vmbreak;
       }
       vmcase(OP_LEI) {
         int im = GETARG_sB(i);
-        if (ttisinteger(vra))
-          cond = (ivalue(vra) <= im);
-        else if (ttisfloat(vra))
-          cond = luai_numle(fltvalue(vra), cast_num(im));
+        if (ttisinteger(s2v(ra)))
+          cond = (ivalue(s2v(ra)) <= im);
+        else if (ttisfloat(s2v(ra)))
+          cond = luai_numle(fltvalue(s2v(ra)), cast_num(im));
         else
-          Protect(cond = luaT_callorderiTM(L, vra, im, 0, TM_LE));
+          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 0, TM_LE));
         docondjump();
         vmbreak;
       }
       vmcase(OP_GTI) {
         int im = GETARG_sB(i);
-        if (ttisinteger(vra))
-          cond = (im < ivalue(vra));
-        else if (ttisfloat(vra))
-          cond = luai_numlt(cast_num(im), fltvalue(vra));
+        if (ttisinteger(s2v(ra)))
+          cond = (im < ivalue(s2v(ra)));
+        else if (ttisfloat(s2v(ra)))
+          cond = luai_numlt(cast_num(im), fltvalue(s2v(ra)));
         else
-          Protect(cond = luaT_callorderiTM(L, vra, im, 1, TM_LT));
+          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 1, TM_LT));
         docondjump();
         vmbreak;
       }
       vmcase(OP_GEI) {
         int im = GETARG_sB(i);
-        if (ttisinteger(vra))
-          cond = (im <= ivalue(vra));
-        else if (ttisfloat(vra))
-          cond = luai_numle(cast_num(im), fltvalue(vra));
+        if (ttisinteger(s2v(ra)))
+          cond = (im <= ivalue(s2v(ra)));
+        else if (ttisfloat(s2v(ra)))
+          cond = luai_numle(cast_num(im), fltvalue(s2v(ra)));
         else
-          Protect(cond = luaT_callorderiTM(L, vra, im, 1, TM_LE));
+          Protect(cond = luaT_callorderiTM(L, s2v(ra), im, 1, TM_LE));
         docondjump();
         vmbreak;
       }
       vmcase(OP_TEST) {
-        cond = !l_isfalse(vra);
+        cond = !l_isfalse(s2v(ra));
         docondjump();
         vmbreak;
       }

@@ -1552,18 +1556,6 @@
         }
         vmbreak;
       }
-      vmcase(OP_UNDEF) {
-        TValue *rb = vRB(i);
-        luaT_keydef(L, vra, rb, 1);
-        vmbreak;
-      }
-      vmcase(OP_ISDEF) {
-        TValue *rb = vRB(i);
-        TValue *rc = vRC(i);
-        int res = luaT_keydef(L, rb, rc, 0);
-        setbvalue(vra, res == GETARG_k(i));
-        vmbreak;
-      }
       vmcase(OP_CALL) {
         int b = GETARG_B(i);
         int nresults = GETARG_C(i) - 1;

@@ -1587,11 +1579,11 @@
             delta = ci->u.l.nextraargs + nparams1;
           luaF_close(L, base);  /* close upvalues from current call */
         }
-        if (!ttisfunction(vra)) {  /* not a function? */
+        if (!ttisfunction(s2v(ra))) {  /* not a function? */
           luaD_tryfuncTM(L, ra);  /* try '__call' metamethod */
           b++;  /* there is now one extra argument */
         }
-        if (!ttisLclosure(vra)) {  /* C function? */
+        if (!ttisLclosure(s2v(ra))) {  /* C function? */
           luaD_call(L, ra, LUA_MULTRET);  /* call it */
           updatetrap(ci);
           if (trap) {  /* stack may have been relocated */

@@ -1599,7 +1591,7 @@
             ra = RA(i);
           }
           ci->func -= delta;
-          luaD_poscall(L, ci, ra, cast_int(L->top - ra));
+          luaD_poscall(L, ci, cast_int(L->top - ra));
           return;
         }
         else {  /* Lua tail call */

@@ -1610,20 +1602,25 @@
         vmbreak;
       }
       vmcase(OP_RETURN) {
-        int b = GETARG_B(i);
-        int n = (b != 0 ? b - 1 : cast_int(L->top - ra));
+        int n = GETARG_B(i) - 1;  /* number of results */
+        if (n < 0)  /* not fixed? */
+          n = cast_int(L->top - ra);  /* get what is available */
+        else
+          L->top = ra + n;  /* set call for 'luaD_poscall' */
         if (TESTARG_k(i)) {
           int nparams1 = GETARG_C(i);
           if (nparams1)  /* vararg function? */
             ci->func -= ci->u.l.nextraargs + nparams1;
           luaF_close(L, base);  /* there may be open upvalues */
         }
-        halfProtect(luaD_poscall(L, ci, ra, n));
+        halfProtect(luaD_poscall(L, ci, n));
         return;
       }
       vmcase(OP_RETURN0) {
-        if (L->hookmask)
-          halfProtect(luaD_poscall(L, ci, ra, 0));  /* no hurry... */
+        if (L->hookmask) {
+          L->top = ra;
+          halfProtect(luaD_poscall(L, ci, 0));  /* no hurry... */
+        }
         else {
           int nres = ci->nresults;
           L->ci = ci->previous;  /* back to caller */

@@ -1634,8 +1631,10 @@
         return;
       }
       vmcase(OP_RETURN1) {
-        if (L->hookmask)
-          halfProtect(luaD_poscall(L, ci, ra, 1));  /* no hurry... */
+        if (L->hookmask) {
+          L->top = ra + 1;
+          halfProtect(luaD_poscall(L, ci, 1));  /* no hurry... */
+        }
         else {
           int nres = ci->nresults;
           L->ci = ci->previous;  /* back to caller */

@@ -1651,22 +1650,22 @@
         return;
       }
       vmcase(OP_FORLOOP1) {
-        lua_Integer idx = intop(+, ivalue(vra), 1); /* increment index */
+        lua_Integer idx = intop(+, ivalue(s2v(ra)), 1); /* increment index */
         lua_Integer limit = ivalue(s2v(ra + 1));
         if (idx <= limit) {
           pc -= GETARG_Bx(i);  /* jump back */
-          chgivalue(vra, idx);  /* update internal index... */
+          chgivalue(s2v(ra), idx);  /* update internal index... */
           setivalue(s2v(ra + 3), idx);  /* ...and external index */
         }
         updatetrap(ci);
         vmbreak;
       }
       vmcase(OP_FORPREP1) {
-        TValue *init = vra;
+        TValue *init = s2v(ra);
         TValue *plimit = s2v(ra + 1);
         lua_Integer ilimit, initv;
         int stopnow;
-        if (!forlimit(plimit, &ilimit, 1, &stopnow)) {
+        if (unlikely(!forlimit(plimit, &ilimit, 1, &stopnow))) {
             savestate(L, ci);  /* for the error message */
             luaG_runerror(L, "'for' limit must be a number");
         }

@@ -1677,25 +1676,25 @@
         vmbreak;
       }
       vmcase(OP_FORLOOP) {
-        if (ttisinteger(vra)) {  /* integer loop? */
+        if (ttisinteger(s2v(ra))) {  /* integer loop? */
           lua_Integer step = ivalue(s2v(ra + 2));
-          lua_Integer idx = intop(+, ivalue(vra), step); /* increment index */
+          lua_Integer idx = intop(+, ivalue(s2v(ra)), step); /* new index */
           lua_Integer limit = ivalue(s2v(ra + 1));
           if ((0 < step) ? (idx <= limit) : (limit <= idx)) {
             pc -= GETARG_Bx(i);  /* jump back */
-            chgivalue(vra, idx);  /* update internal index... */
+            chgivalue(s2v(ra), idx);  /* update internal index... */
             setivalue(s2v(ra + 3), idx);  /* ...and external index */
           }
         }
         else {  /* floating loop */
           lua_Number step = fltvalue(s2v(ra + 2));
           lua_Number limit = fltvalue(s2v(ra + 1));
-          lua_Number idx = fltvalue(vra);
+          lua_Number idx = fltvalue(s2v(ra));
           idx = luai_numadd(L, idx, step);  /* inc. index */
           if (luai_numlt(0, step) ? luai_numle(idx, limit)
                                   : luai_numle(limit, idx)) {
             pc -= GETARG_Bx(i);  /* jump back */
-            chgfltvalue(vra, idx);  /* update internal index... */
+            chgfltvalue(s2v(ra), idx);  /* update internal index... */
             setfltvalue(s2v(ra + 3), idx);  /* ...and external index */
           }
         }

@@ -1703,7 +1702,7 @@
         vmbreak;
       }
       vmcase(OP_FORPREP) {
-        TValue *init = vra;
+        TValue *init = s2v(ra);
         TValue *plimit = s2v(ra + 1);
         TValue *pstep = s2v(ra + 2);
         lua_Integer ilimit;

@@ -1718,13 +1717,13 @@
         else {  /* try making all values floats */
           lua_Number ninit; lua_Number nlimit; lua_Number nstep;
           savestate(L, ci);  /* in case of errors */
-          if (!tonumber(plimit, &nlimit))
+          if (unlikely(!tonumber(plimit, &nlimit)))
             luaG_runerror(L, "'for' limit must be a number");
           setfltvalue(plimit, nlimit);
-          if (!tonumber(pstep, &nstep))
+          if (unlikely(!tonumber(pstep, &nstep)))
             luaG_runerror(L, "'for' step must be a number");
           setfltvalue(pstep, nstep);
-          if (!tonumber(init, &ninit))
+          if (unlikely(!tonumber(init, &ninit)))
             luaG_runerror(L, "'for' initial value must be a number");
           setfltvalue(init, luai_numsub(L, ninit, nstep));
         }

@@ -1765,9 +1764,9 @@
         if (c == 0) {
           c = GETARG_Ax(*pc); pc++;
         }
-        h = hvalue(vra);
+        h = hvalue(s2v(ra));
         last = ((c-1)*LFIELDS_PER_FLUSH) + n;
-        if (last > h->sizearray)  /* needs more space? */
+        if (last > luaH_realasize(h))  /* needs more space? */
           luaH_resizearray(L, h, last);  /* preallocate it at once */
         for (; n > 0; n--) {
           TValue *val = s2v(ra + n);

@@ -1791,7 +1790,7 @@
       }
       vmcase(OP_VARARG) {
         int n = GETARG_C(i) - 1;  /* required results */
-        ProtectNT(luaT_getvarargs(L, ci, ra, n));
+        Protect(luaT_getvarargs(L, ci, ra, n));
         vmbreak;
       }
       vmcase(OP_PREPVARARG) {

src/lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 2.51 2018/02/23 13:13:31 roberto Exp $
+** $Id: lvm.h,v 2.52 2018/06/15 14:14:20 roberto Exp $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */

@@ -84,7 +84,7 @@
 #define luaV_fastgeti(L,t,k,slot) \
   (!ttistable(t)  \
    ? (slot = NULL, 0)  /* not a table; 'slot' is NULL and result is 0 */  \
-   : (slot = (l_castS2U(k) - 1u < hvalue(t)->sizearray) \
+   : (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \
               ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
       !isempty(slot)))  /* result not empty? */