mirror of
https://github.com/love2d/megasource.git
synced 2026-08-19 20:20:11 +02:00
Update LuaJIT to LuaJIT/LuaJIT@03080b7
This commit is contained in:
@@ -33,7 +33,8 @@ DPREFIX= $(DESTDIR)$(PREFIX)
|
|||||||
INSTALL_BIN= $(DPREFIX)/bin
|
INSTALL_BIN= $(DPREFIX)/bin
|
||||||
INSTALL_LIB= $(DPREFIX)/$(MULTILIB)
|
INSTALL_LIB= $(DPREFIX)/$(MULTILIB)
|
||||||
INSTALL_SHARE= $(DPREFIX)/share
|
INSTALL_SHARE= $(DPREFIX)/share
|
||||||
INSTALL_INC= $(DPREFIX)/include/luajit-$(MAJVER).$(MINVER)
|
INSTALL_DEFINC= $(DPREFIX)/include/luajit-$(MAJVER).$(MINVER)
|
||||||
|
INSTALL_INC= $(INSTALL_DEFINC)
|
||||||
|
|
||||||
INSTALL_LJLIBD= $(INSTALL_SHARE)/luajit-$(VERSION)
|
INSTALL_LJLIBD= $(INSTALL_SHARE)/luajit-$(VERSION)
|
||||||
INSTALL_JITLIB= $(INSTALL_LJLIBD)/jit
|
INSTALL_JITLIB= $(INSTALL_LJLIBD)/jit
|
||||||
@@ -78,6 +79,9 @@ UNINSTALL= $(RM)
|
|||||||
LDCONFIG= ldconfig -n 2>/dev/null
|
LDCONFIG= ldconfig -n 2>/dev/null
|
||||||
SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|" \
|
SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|" \
|
||||||
-e "s|^multilib=.*|multilib=$(MULTILIB)|"
|
-e "s|^multilib=.*|multilib=$(MULTILIB)|"
|
||||||
|
ifneq ($(INSTALL_DEFINC),$(INSTALL_INC))
|
||||||
|
SED_PC+= -e "s|^includedir=.*|includedir=$(INSTALL_INC)|"
|
||||||
|
endif
|
||||||
|
|
||||||
FILE_T= luajit
|
FILE_T= luajit
|
||||||
FILE_A= libluajit.a
|
FILE_A= libluajit.a
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ overhead. In conjunction with the FFI library, they allow zero-copy
|
|||||||
operations.
|
operations.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The string buffer libary also includes a high-performance
|
The string buffer library also includes a high-performance
|
||||||
<a href="serialize">serializer</a> for Lua objects.
|
<a href="serialize">serializer</a> for Lua objects.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -434,8 +434,8 @@ unsupported object types, circular references or deeply nested tables.
|
|||||||
<h3 id="buffer_decode"><tt>obj = buffer.decode(str)<br>
|
<h3 id="buffer_decode"><tt>obj = buffer.decode(str)<br>
|
||||||
obj = buf:decode()</tt></h3>
|
obj = buf:decode()</tt></h3>
|
||||||
<p>
|
<p>
|
||||||
The stand-alone function de-serializes (decodes) the string
|
The stand-alone function deserializes (decodes) the string
|
||||||
<tt>str</tt>, the buffer method de-serializes one object from the
|
<tt>str</tt>, the buffer method deserializes one object from the
|
||||||
buffer. Both return a Lua object <tt>obj</tt>.
|
buffer. Both return a Lua object <tt>obj</tt>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -449,7 +449,7 @@ data after decoding a single top-level object. The buffer method leaves
|
|||||||
any left-over data in the buffer.
|
any left-over data in the buffer.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Attempting to de-serialize an FFI type will throw an error, if the FFI
|
Attempting to deserialize an FFI type will throw an error, if the FFI
|
||||||
library is not built-in or has not been loaded, yet.
|
library is not built-in or has not been loaded, yet.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -462,7 +462,7 @@ the following members (all optional):
|
|||||||
<li>
|
<li>
|
||||||
<tt>dict</tt> is a Lua table holding a <b>dictionary of strings</b> that
|
<tt>dict</tt> is a Lua table holding a <b>dictionary of strings</b> that
|
||||||
commonly occur as table keys of objects you are serializing. These keys
|
commonly occur as table keys of objects you are serializing. These keys
|
||||||
are compactly encoded as indexes during serialization. A well chosen
|
are compactly encoded as indexes during serialization. A well-chosen
|
||||||
dictionary saves space and improves serialization performance.
|
dictionary saves space and improves serialization performance.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@@ -473,7 +473,7 @@ for the table objects you are serializing.
|
|||||||
<p>
|
<p>
|
||||||
<tt>dict</tt> needs to be an array of strings and <tt>metatable</tt> needs
|
<tt>dict</tt> needs to be an array of strings and <tt>metatable</tt> needs
|
||||||
to be an array of tables. Both starting at index 1 and without holes (no
|
to be an array of tables. Both starting at index 1 and without holes (no
|
||||||
<tt>nil</tt> inbetween). The tables are anchored in the buffer object and
|
<tt>nil</tt> in between). The tables are anchored in the buffer object and
|
||||||
internally modified into a two-way index (don't do this yourself, just pass
|
internally modified into a two-way index (don't do this yourself, just pass
|
||||||
a plain array). The tables must not be modified after they have been passed
|
a plain array). The tables must not be modified after they have been passed
|
||||||
to <tt>buffer.new()</tt>.
|
to <tt>buffer.new()</tt>.
|
||||||
@@ -624,7 +624,7 @@ errors are best caught with an outer wrapper for larger parts of code.
|
|||||||
There's not much one can do after that, anyway.
|
There's not much one can do after that, anyway.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
OTOH you may want to catch some errors individually. Buffer methods need
|
OTOH, you may want to catch some errors individually. Buffer methods need
|
||||||
to receive the buffer object as the first argument. The Lua colon-syntax
|
to receive the buffer object as the first argument. The Lua colon-syntax
|
||||||
<tt>obj:method()</tt> does that implicitly. But to wrap a method with
|
<tt>obj:method()</tt> does that implicitly. But to wrap a method with
|
||||||
<tt>pcall()</tt>, the arguments need to be passed like this:
|
<tt>pcall()</tt>, the arguments need to be passed like this:
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ Turn the whole JIT compiler on or off or flush the whole cache of compiled code.
|
|||||||
This sets the mode for the function at the stack index <tt>idx</tt> or
|
This sets the mode for the function at the stack index <tt>idx</tt> or
|
||||||
the parent of the calling function (<tt>idx = 0</tt>). It either
|
the parent of the calling function (<tt>idx = 0</tt>). It either
|
||||||
enables JIT compilation for a function, disables it and flushes any
|
enables JIT compilation for a function, disables it and flushes any
|
||||||
already compiled code or only flushes already compiled code. This
|
already compiled code, or only flushes already compiled code. This
|
||||||
applies recursively to all sub-functions of the function with
|
applies recursively to all sub-functions of the function with
|
||||||
<tt>LUAJIT_MODE_ALLFUNC</tt> or only to the sub-functions with
|
<tt>LUAJIT_MODE_ALLFUNC</tt> or only to the sub-functions with
|
||||||
<tt>LUAJIT_MODE_ALLSUBFUNC</tt>.
|
<tt>LUAJIT_MODE_ALLSUBFUNC</tt>.
|
||||||
@@ -126,7 +126,7 @@ traces which link to it.
|
|||||||
This mode defines a wrapper function for calls to C functions. If
|
This mode defines a wrapper function for calls to C functions. If
|
||||||
called with <tt>LUAJIT_MODE_ON</tt>, the stack index at <tt>idx</tt>
|
called with <tt>LUAJIT_MODE_ON</tt>, the stack index at <tt>idx</tt>
|
||||||
must be a <tt>lightuserdata</tt> object holding a pointer to the wrapper
|
must be a <tt>lightuserdata</tt> object holding a pointer to the wrapper
|
||||||
function. From now on all C functions are called through the wrapper
|
function. From now on, all C functions are called through the wrapper
|
||||||
function. If called with <tt>LUAJIT_MODE_OFF</tt> this mode is turned
|
function. If called with <tt>LUAJIT_MODE_OFF</tt> this mode is turned
|
||||||
off and all C functions are directly called.
|
off and all C functions are directly called.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ call the binding function. Phew!
|
|||||||
<h2 id="cdata">Motivating Example: Using C Data Structures</h2>
|
<h2 id="cdata">Motivating Example: Using C Data Structures</h2>
|
||||||
<p>
|
<p>
|
||||||
The FFI library allows you to create and access C data
|
The FFI library allows you to create and access C data
|
||||||
structures. Of course the main use for this is for interfacing with
|
structures. Of course, the main use for this is for interfacing with
|
||||||
C functions. But they can be used stand-alone, too.
|
C functions. But they can be used stand-alone, too.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -169,7 +169,7 @@ implemented with a big table holding lots of tiny tables. This imposes
|
|||||||
both a substantial memory overhead as well as a performance overhead.
|
both a substantial memory overhead as well as a performance overhead.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Here's a sketch of a library that operates on color images plus a
|
Here's a sketch of a library that operates on color images, plus a
|
||||||
simple benchmark. First, the plain Lua version:
|
simple benchmark. First, the plain Lua version:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code">
|
||||||
@@ -184,7 +184,7 @@ local function image_ramp_green(n)
|
|||||||
return img
|
return img
|
||||||
end
|
end
|
||||||
|
|
||||||
local function image_to_grey(img, n)
|
local function image_to_gray(img, n)
|
||||||
for i=1,n do
|
for i=1,n do
|
||||||
local y = floor(0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue)
|
local y = floor(0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue)
|
||||||
img[i].red = y; img[i].green = y; img[i].blue = y
|
img[i].red = y; img[i].green = y; img[i].blue = y
|
||||||
@@ -194,14 +194,14 @@ end
|
|||||||
local N = 400*400
|
local N = 400*400
|
||||||
local img = image_ramp_green(N)
|
local img = image_ramp_green(N)
|
||||||
for i=1,1000 do
|
for i=1,1000 do
|
||||||
image_to_grey(img, N)
|
image_to_gray(img, N)
|
||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
This creates a table with 160.000 pixels, each of which is a table
|
This creates a table with 160.000 pixels, each of which is a table
|
||||||
holding four number values in the range of 0-255. First an image with
|
holding four number values in the range of 0-255. First, an image with
|
||||||
a green ramp is created (1D for simplicity), then the image is
|
a green ramp is created (1D for simplicity), then the image is
|
||||||
converted to greyscale 1000 times. Yes, that's silly, but I was in
|
converted to grayscale 1000 times. Yes, that's silly, but I was in
|
||||||
need of a simple example ...
|
need of a simple example ...
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -308,7 +308,7 @@ be more compact and faster. This is certainly true (by a factor of
|
|||||||
~1.7x). Switching to a struct-of-arrays would help, too.
|
~1.7x). Switching to a struct-of-arrays would help, too.
|
||||||
</p>
|
</p>
|
||||||
<p style="font-size: 8pt;">
|
<p style="font-size: 8pt;">
|
||||||
However the resulting code would be less idiomatic and rather
|
However, the resulting code would be less idiomatic and rather
|
||||||
error-prone. And it still doesn't get even close to the performance of
|
error-prone. And it still doesn't get even close to the performance of
|
||||||
the FFI version of the code. Also, high-level data structures cannot
|
the FFI version of the code. Also, high-level data structures cannot
|
||||||
be easily passed to other C functions, especially I/O functions,
|
be easily passed to other C functions, especially I/O functions,
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ separated by semicolons. The trailing semicolon for a single
|
|||||||
declaration may be omitted.
|
declaration may be omitted.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Please note that external symbols are only <em>declared</em>, but they
|
Please note, that external symbols are only <em>declared</em>, but they
|
||||||
are <em>not bound</em> to any specific address, yet. Binding is
|
are <em>not bound</em> to any specific address, yet. Binding is
|
||||||
achieved with C library namespaces (see below).
|
achieved with C library namespaces (see below).
|
||||||
</p>
|
</p>
|
||||||
@@ -209,7 +209,7 @@ parse the cdecl only once and get its ctype with
|
|||||||
<tt>ffi.typeof()</tt>. Then use the ctype as a constructor repeatedly.
|
<tt>ffi.typeof()</tt>. Then use the ctype as a constructor repeatedly.
|
||||||
</p>
|
</p>
|
||||||
<p style="font-size: 8pt;">
|
<p style="font-size: 8pt;">
|
||||||
Please note that an anonymous <tt>struct</tt> declaration implicitly
|
Please note, that an anonymous <tt>struct</tt> declaration implicitly
|
||||||
creates a new and distinguished ctype every time you use it for
|
creates a new and distinguished ctype every time you use it for
|
||||||
<tt>ffi.new()</tt>. This is probably <b>not</b> what you want,
|
<tt>ffi.new()</tt>. This is probably <b>not</b> what you want,
|
||||||
especially if you create more than one cdata object. Different anonymous
|
especially if you create more than one cdata object. Different anonymous
|
||||||
@@ -256,12 +256,12 @@ afterwards. Neither the contents of the <tt>metatable</tt> nor the
|
|||||||
contents of an <tt>__index</tt> table (if any) may be modified
|
contents of an <tt>__index</tt> table (if any) may be modified
|
||||||
afterwards. The associated metatable automatically applies to all uses
|
afterwards. The associated metatable automatically applies to all uses
|
||||||
of this type, no matter how the objects are created or where they
|
of this type, no matter how the objects are created or where they
|
||||||
originate from. Note that pre-defined operations on types have
|
originate from. Note that predefined operations on types have
|
||||||
precedence (e.g. declared field names cannot be overridden).
|
precedence (e.g. declared field names cannot be overridden).
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
All standard Lua metamethods are implemented. These are called directly,
|
All standard Lua metamethods are implemented. These are called directly,
|
||||||
without shortcuts and on any mix of types. For binary operations, the
|
without shortcuts, and on any mix of types. For binary operations, the
|
||||||
left operand is checked first for a valid ctype metamethod. The
|
left operand is checked first for a valid ctype metamethod. The
|
||||||
<tt>__gc</tt> metamethod only applies to <tt>struct</tt>/<tt>union</tt>
|
<tt>__gc</tt> metamethod only applies to <tt>struct</tt>/<tt>union</tt>
|
||||||
types and performs an implicit <a href="#ffi_gc"><tt>ffi.gc()</tt></a>
|
types and performs an implicit <a href="#ffi_gc"><tt>ffi.gc()</tt></a>
|
||||||
@@ -492,7 +492,7 @@ have some extra methods:
|
|||||||
<p>
|
<p>
|
||||||
Free the resources associated with a callback. The associated Lua
|
Free the resources associated with a callback. The associated Lua
|
||||||
function is unanchored and may be garbage collected. The callback
|
function is unanchored and may be garbage collected. The callback
|
||||||
function pointer is no longer valid and must not be called anymore
|
function pointer is no longer valid and must not be called again
|
||||||
(it may be reused by a subsequently created callback).
|
(it may be reused by a subsequently created callback).
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ footprint. It's used by the <a href="ext_ffi_api.html">ffi.* library
|
|||||||
functions</a> to declare C types or external symbols.
|
functions</a> to declare C types or external symbols.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
It's only purpose is to parse C declarations, as found e.g. in
|
Its only purpose is to parse C declarations, as found e.g. in
|
||||||
C header files. Although it does evaluate constant expressions,
|
C header files. Although it does evaluate constant expressions,
|
||||||
it's <em>not</em> a C compiler. The body of <tt>inline</tt>
|
it's <em>not</em> a C compiler. The body of <tt>inline</tt>
|
||||||
C function definitions is simply ignored.
|
C function definitions is simply ignored.
|
||||||
@@ -165,7 +165,7 @@ function declarations.</li>
|
|||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
The following C types are pre-defined by the C parser (like
|
The following C types are predefined by the C parser (like
|
||||||
a <tt>typedef</tt>, except re-declarations will be ignored):
|
a <tt>typedef</tt>, except re-declarations will be ignored):
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -583,9 +583,9 @@ ffi.new("struct nested", {x=1,y={2,3}}) --> x = 1, y.a = 2, y.b = 3
|
|||||||
|
|
||||||
<h2 id="cdata_ops">Operations on cdata Objects</h2>
|
<h2 id="cdata_ops">Operations on cdata Objects</h2>
|
||||||
<p>
|
<p>
|
||||||
All of the standard Lua operators can be applied to cdata objects or a
|
All standard Lua operators can be applied to cdata objects or a
|
||||||
mix of a cdata object and another Lua object. The following list shows
|
mix of a cdata object and another Lua object. The following list shows
|
||||||
the pre-defined operations.
|
the predefined operations.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Reference types are dereferenced <em>before</em> performing each of
|
Reference types are dereferenced <em>before</em> performing each of
|
||||||
@@ -593,7 +593,7 @@ the operations below — the operation is applied to the
|
|||||||
C type pointed to by the reference.
|
C type pointed to by the reference.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The pre-defined operations are always tried first before deferring to a
|
The predefined operations are always tried first before deferring to a
|
||||||
metamethod or index table (if any) for the corresponding ctype (except
|
metamethod or index table (if any) for the corresponding ctype (except
|
||||||
for <tt>__new</tt>). An error is raised if the metamethod lookup or
|
for <tt>__new</tt>). An error is raised if the metamethod lookup or
|
||||||
index table lookup fails.
|
index table lookup fails.
|
||||||
@@ -643,7 +643,7 @@ assigning to an index of a vector raises an error.</li>
|
|||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
A ctype object can be indexed with a string key, too. The only
|
A ctype object can be indexed with a string key, too. The only
|
||||||
pre-defined operation is reading scoped constants of
|
predefined operation is reading scoped constants of
|
||||||
<tt>struct</tt>/<tt>union</tt> types. All other accesses defer
|
<tt>struct</tt>/<tt>union</tt> types. All other accesses defer
|
||||||
to the corresponding metamethods or index tables (if any).
|
to the corresponding metamethods or index tables (if any).
|
||||||
</p>
|
</p>
|
||||||
@@ -656,7 +656,7 @@ certain optimizations.
|
|||||||
<p>
|
<p>
|
||||||
As a consequence, the <em>elements</em> of complex numbers and
|
As a consequence, the <em>elements</em> of complex numbers and
|
||||||
vectors are immutable. But the elements of an aggregate holding these
|
vectors are immutable. But the elements of an aggregate holding these
|
||||||
types <em>may</em> be modified of course. I.e. you cannot assign to
|
types <em>may</em> be modified, of course. I.e. you cannot assign to
|
||||||
<tt>foo.c.im</tt>, but you can assign a (newly created) complex number
|
<tt>foo.c.im</tt>, but you can assign a (newly created) complex number
|
||||||
to <tt>foo.c</tt>.
|
to <tt>foo.c</tt>.
|
||||||
</p>
|
</p>
|
||||||
@@ -675,8 +675,8 @@ through unions is explicitly detected and allowed.
|
|||||||
to <tt>ffi.new(ct, ...)</tt>, unless a <tt>__new</tt> metamethod is
|
to <tt>ffi.new(ct, ...)</tt>, unless a <tt>__new</tt> metamethod is
|
||||||
defined. The <tt>__new</tt> metamethod is called with the ctype object
|
defined. The <tt>__new</tt> metamethod is called with the ctype object
|
||||||
plus any other arguments passed to the constructor. Note that you have to
|
plus any other arguments passed to the constructor. Note that you have to
|
||||||
use <tt>ffi.new</tt> inside of it, since calling <tt>ct(...)</tt> would
|
use <tt>ffi.new</tt> inside the metamethod, since calling <tt>ct(...)</tt>
|
||||||
cause infinite recursion.</li>
|
would cause infinite recursion.</li>
|
||||||
|
|
||||||
<li><b>C function call</b>: a cdata function or cdata function
|
<li><b>C function call</b>: a cdata function or cdata function
|
||||||
pointer can be called. The passed arguments are
|
pointer can be called. The passed arguments are
|
||||||
@@ -687,7 +687,7 @@ variable argument part of vararg C function use
|
|||||||
C function is called and the return value (if any) is
|
C function is called and the return value (if any) is
|
||||||
<a href="#convert_tolua">converted to a Lua object</a>.<br>
|
<a href="#convert_tolua">converted to a Lua object</a>.<br>
|
||||||
On Windows/x86 systems, <tt>__stdcall</tt> functions are automatically
|
On Windows/x86 systems, <tt>__stdcall</tt> functions are automatically
|
||||||
detected and a function declared as <tt>__cdecl</tt> (the default) is
|
detected, and a function declared as <tt>__cdecl</tt> (the default) is
|
||||||
silently fixed up after the first call.</li>
|
silently fixed up after the first call.</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
@@ -697,7 +697,7 @@ silently fixed up after the first call.</li>
|
|||||||
|
|
||||||
<li><b>Pointer arithmetic</b>: a cdata pointer/array and a cdata
|
<li><b>Pointer arithmetic</b>: a cdata pointer/array and a cdata
|
||||||
number or a Lua number can be added or subtracted. The number must be
|
number or a Lua number can be added or subtracted. The number must be
|
||||||
on the right hand side for a subtraction. The result is a pointer of
|
on the right-hand side for a subtraction. The result is a pointer of
|
||||||
the same type with an address plus or minus the number value
|
the same type with an address plus or minus the number value
|
||||||
multiplied by the element size in bytes. An error is raised if the
|
multiplied by the element size in bytes. An error is raised if the
|
||||||
element size is undefined.</li>
|
element size is undefined.</li>
|
||||||
@@ -712,7 +712,7 @@ operators (<tt>+ - * / % ^</tt> and unary
|
|||||||
minus) can be applied to two cdata numbers, or a cdata number and a
|
minus) can be applied to two cdata numbers, or a cdata number and a
|
||||||
Lua number. If one of them is an <tt>uint64_t</tt>, the other side is
|
Lua number. If one of them is an <tt>uint64_t</tt>, the other side is
|
||||||
converted to an <tt>uint64_t</tt> and an unsigned arithmetic operation
|
converted to an <tt>uint64_t</tt> and an unsigned arithmetic operation
|
||||||
is performed. Otherwise both sides are converted to an
|
is performed. Otherwise, both sides are converted to an
|
||||||
<tt>int64_t</tt> and a signed arithmetic operation is performed. The
|
<tt>int64_t</tt> and a signed arithmetic operation is performed. The
|
||||||
result is a boxed 64 bit cdata object.<br>
|
result is a boxed 64 bit cdata object.<br>
|
||||||
|
|
||||||
@@ -759,7 +759,7 @@ which is compatible with any other pointer type.</li>
|
|||||||
<li><b>64 bit integer comparison</b>: two cdata numbers, or a
|
<li><b>64 bit integer comparison</b>: two cdata numbers, or a
|
||||||
cdata number and a Lua number can be compared with each other. If one
|
cdata number and a Lua number can be compared with each other. If one
|
||||||
of them is an <tt>uint64_t</tt>, the other side is converted to an
|
of them is an <tt>uint64_t</tt>, the other side is converted to an
|
||||||
<tt>uint64_t</tt> and an unsigned comparison is performed. Otherwise
|
<tt>uint64_t</tt> and an unsigned comparison is performed. Otherwise,
|
||||||
both sides are converted to an <tt>int64_t</tt> and a signed
|
both sides are converted to an <tt>int64_t</tt> and a signed
|
||||||
comparison is performed.<br>
|
comparison is performed.<br>
|
||||||
|
|
||||||
@@ -784,9 +784,9 @@ keys!</b>
|
|||||||
A cdata object is treated like any other garbage-collected object and
|
A cdata object is treated like any other garbage-collected object and
|
||||||
is hashed and compared by its address for table indexing. Since
|
is hashed and compared by its address for table indexing. Since
|
||||||
there's no interning for cdata value types, the same value may be
|
there's no interning for cdata value types, the same value may be
|
||||||
boxed in different cdata objects with different addresses. Thus
|
boxed in different cdata objects with different addresses. Thus,
|
||||||
<tt>t[1LL+1LL]</tt> and <tt>t[2LL]</tt> usually <b>do not</b> point to
|
<tt>t[1LL+1LL]</tt> and <tt>t[2LL]</tt> usually <b>do not</b> point to
|
||||||
the same hash slot and they certainly <b>do not</b> point to the same
|
the same hash slot, and they certainly <b>do not</b> point to the same
|
||||||
hash slot as <tt>t[2]</tt>.
|
hash slot as <tt>t[2]</tt>.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -808,7 +808,7 @@ the resulting Lua number as a key when indexing tables.<br>
|
|||||||
One obvious benefit: <tt>t[tonumber(2LL)]</tt> <b>does</b> point to
|
One obvious benefit: <tt>t[tonumber(2LL)]</tt> <b>does</b> point to
|
||||||
the same slot as <tt>t[2]</tt>.</li>
|
the same slot as <tt>t[2]</tt>.</li>
|
||||||
|
|
||||||
<li>Otherwise use either <tt>tostring()</tt> on 64 bit integers
|
<li>Otherwise, use either <tt>tostring()</tt> on 64 bit integers
|
||||||
or complex numbers or combine multiple fields of a cdata aggregate to
|
or complex numbers or combine multiple fields of a cdata aggregate to
|
||||||
a Lua string (e.g. with
|
a Lua string (e.g. with
|
||||||
<a href="ext_ffi_api.html#ffi_string"><tt>ffi.string()</tt></a>). Then
|
<a href="ext_ffi_api.html#ffi_string"><tt>ffi.string()</tt></a>). Then
|
||||||
@@ -816,7 +816,7 @@ use the resulting Lua string as a key when indexing tables.</li>
|
|||||||
|
|
||||||
<li>Create your own specialized hash table implementation using the
|
<li>Create your own specialized hash table implementation using the
|
||||||
C types provided by the FFI library, just like you would in
|
C types provided by the FFI library, just like you would in
|
||||||
C code. Ultimately this may give much better performance than the
|
C code. Ultimately, this may give much better performance than the
|
||||||
other alternatives or what a generic by-value hash table could
|
other alternatives or what a generic by-value hash table could
|
||||||
possibly provide.</li>
|
possibly provide.</li>
|
||||||
|
|
||||||
@@ -882,7 +882,7 @@ garbage collector will automatically free the memory used by it (at
|
|||||||
the end of the next GC cycle).
|
the end of the next GC cycle).
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Please note that pointers themselves are cdata objects, however they
|
Please note, that pointers themselves are cdata objects, however they
|
||||||
are <b>not</b> followed by the garbage collector. So e.g. if you
|
are <b>not</b> followed by the garbage collector. So e.g. if you
|
||||||
assign a cdata array to a pointer, you must keep the cdata object
|
assign a cdata array to a pointer, you must keep the cdata object
|
||||||
holding the array alive as long as the pointer is still in use:
|
holding the array alive as long as the pointer is still in use:
|
||||||
@@ -931,18 +931,18 @@ of the function pointer and the Lua function object (closure).
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
This can happen implicitly due to the usual conversions, e.g. when
|
This can happen implicitly due to the usual conversions, e.g. when
|
||||||
passing a Lua function to a function pointer argument. Or you can use
|
passing a Lua function to a function pointer argument. Or, you can use
|
||||||
<tt>ffi.cast()</tt> to explicitly cast a Lua function to a
|
<tt>ffi.cast()</tt> to explicitly cast a Lua function to a
|
||||||
C function pointer.
|
C function pointer.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Currently only certain C function types can be used as callback
|
Currently, only certain C function types can be used as callback
|
||||||
functions. Neither C vararg functions nor functions with
|
functions. Neither C vararg functions nor functions with
|
||||||
pass-by-value aggregate argument or result types are supported. There
|
pass-by-value aggregate argument or result types are supported. There
|
||||||
are no restrictions for the kind of Lua functions that can be called
|
are no restrictions on the kind of Lua functions that can be called
|
||||||
from the callback — no checks for the proper number of arguments
|
from the callback — no checks for the proper number of arguments
|
||||||
are made. The return value of the Lua function will be converted to the
|
are made. The return value of the Lua function will be converted to the
|
||||||
result type and an error will be thrown for invalid conversions.
|
result type, and an error will be thrown for invalid conversions.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
It's allowed to throw errors across a callback invocation, but it's not
|
It's allowed to throw errors across a callback invocation, but it's not
|
||||||
@@ -1003,7 +1003,7 @@ convention cannot be automatically detected, unlike for
|
|||||||
<tt>__stdcall</tt> calls <em>to</em> Windows functions.
|
<tt>__stdcall</tt> calls <em>to</em> Windows functions.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
For some use cases it's necessary to free up the resources or to
|
For some use cases, it's necessary to free up the resources or to
|
||||||
dynamically redirect callbacks. Use an explicit cast to a
|
dynamically redirect callbacks. Use an explicit cast to a
|
||||||
C function pointer and keep the resulting cdata object. Then use
|
C function pointer and keep the resulting cdata object. Then use
|
||||||
the <a href="ext_ffi_api.html#callback_free"><tt>cb:free()</tt></a>
|
the <a href="ext_ffi_api.html#callback_free"><tt>cb:free()</tt></a>
|
||||||
@@ -1056,7 +1056,7 @@ GUI application, which waits for user input most of the time, anyway.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
For new designs <b>avoid push-style APIs</b>: a C function repeatedly
|
For new designs <b>avoid push-style APIs</b>: a C function repeatedly
|
||||||
calling a callback for each result. Instead <b>use pull-style APIs</b>:
|
calling a callback for each result. Instead, <b>use pull-style APIs</b>:
|
||||||
call a C function repeatedly to get a new result. Calls from Lua
|
call a C function repeatedly to get a new result. Calls from Lua
|
||||||
to C via the FFI are much faster than the other way round. Most well-designed
|
to C via the FFI are much faster than the other way round. Most well-designed
|
||||||
libraries already use pull-style APIs (read/write, get/put).
|
libraries already use pull-style APIs (read/write, get/put).
|
||||||
@@ -1075,7 +1075,7 @@ function.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Indexing a C library namespace object with a symbol name (a Lua
|
Indexing a C library namespace object with a symbol name (a Lua
|
||||||
string) automatically binds it to the library. First the symbol type
|
string) automatically binds it to the library. First, the symbol type
|
||||||
is resolved — it must have been declared with
|
is resolved — it must have been declared with
|
||||||
<a href="ext_ffi_api.html#ffi_cdef"><tt>ffi.cdef</tt></a>. Then the
|
<a href="ext_ffi_api.html#ffi_cdef"><tt>ffi.cdef</tt></a>. Then the
|
||||||
symbol address is resolved by searching for the symbol name in the
|
symbol address is resolved by searching for the symbol name in the
|
||||||
@@ -1130,7 +1130,7 @@ Performance notice: the JIT compiler specializes to the identity of
|
|||||||
namespace objects and to the strings used to index it. This
|
namespace objects and to the strings used to index it. This
|
||||||
effectively turns function cdata objects into constants. It's not
|
effectively turns function cdata objects into constants. It's not
|
||||||
useful and actually counter-productive to explicitly cache these
|
useful and actually counter-productive to explicitly cache these
|
||||||
function objects, e.g. <tt>local strlen = ffi.C.strlen</tt>. OTOH it
|
function objects, e.g. <tt>local strlen = ffi.C.strlen</tt>. OTOH, it
|
||||||
<em>is</em> useful to cache the namespace itself, e.g. <tt>local C =
|
<em>is</em> useful to cache the namespace itself, e.g. <tt>local C =
|
||||||
ffi.C</tt>.
|
ffi.C</tt>.
|
||||||
</p>
|
</p>
|
||||||
@@ -1155,14 +1155,14 @@ This behavior is inevitable, since the goal is to provide full
|
|||||||
interoperability with C code. Adding extra safety measures, like
|
interoperability with C code. Adding extra safety measures, like
|
||||||
bounds checks, would be futile. There's no way to detect
|
bounds checks, would be futile. There's no way to detect
|
||||||
misdeclarations of C functions, since shared libraries only
|
misdeclarations of C functions, since shared libraries only
|
||||||
provide symbol names, but no type information. Likewise there's no way
|
provide symbol names, but no type information. Likewise, there's no way
|
||||||
to infer the valid range of indexes for a returned pointer.
|
to infer the valid range of indexes for a returned pointer.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Again: the FFI library is a low-level library. This implies it needs
|
Again: the FFI library is a low-level library. This implies it needs
|
||||||
to be used with care, but it's flexibility and performance often
|
to be used with care, but it's flexibility and performance often
|
||||||
outweigh this concern. If you're a C or C++ developer, it'll be easy
|
outweigh this concern. If you're a C or C++ developer, it'll be easy
|
||||||
to apply your existing knowledge. OTOH writing code for the FFI
|
to apply your existing knowledge. OTOH, writing code for the FFI
|
||||||
library is not for the faint of heart and probably shouldn't be the
|
library is not for the faint of heart and probably shouldn't be the
|
||||||
first exercise for someone with little experience in Lua, C or C++.
|
first exercise for someone with little experience in Lua, C or C++.
|
||||||
</p>
|
</p>
|
||||||
@@ -1190,7 +1190,7 @@ currently incomplete:
|
|||||||
<li>C declarations are not passed through a C pre-processor,
|
<li>C declarations are not passed through a C pre-processor,
|
||||||
yet.</li>
|
yet.</li>
|
||||||
<li>The C parser is able to evaluate most constant expressions
|
<li>The C parser is able to evaluate most constant expressions
|
||||||
commonly found in C header files. However it doesn't handle the
|
commonly found in C header files. However, it doesn't handle the
|
||||||
full range of C expression semantics and may fail for some
|
full range of C expression semantics and may fail for some
|
||||||
obscure constructs.</li>
|
obscure constructs.</li>
|
||||||
<li><tt>static const</tt> declarations only work for integer types
|
<li><tt>static const</tt> declarations only work for integer types
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ of its functions:
|
|||||||
local ffi = require("ffi")
|
local ffi = require("ffi")
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
Please note this doesn't define an <tt>ffi</tt> variable in the table
|
Please note, this doesn't define an <tt>ffi</tt> variable in the table
|
||||||
of globals — you really need to use the local variable. The
|
of globals — you really need to use the local variable. The
|
||||||
<tt>require</tt> function ensures the library is only loaded once.
|
<tt>require</tt> function ensures the library is only loaded once.
|
||||||
</p>
|
</p>
|
||||||
@@ -194,7 +194,7 @@ don't need to declare them as such.
|
|||||||
<span class="mark">⑤</span> The <tt>poll()</tt>
|
<span class="mark">⑤</span> The <tt>poll()</tt>
|
||||||
function takes a couple more arguments we're not going to use. You can
|
function takes a couple more arguments we're not going to use. You can
|
||||||
simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
|
simply use <tt>nil</tt> to pass a <tt>NULL</tt> pointer and <tt>0</tt>
|
||||||
for the <tt>nfds</tt> parameter. Please note that the
|
for the <tt>nfds</tt> parameter. Please note, that the
|
||||||
number <tt>0</tt> <em>does not convert to a pointer value</em>,
|
number <tt>0</tt> <em>does not convert to a pointer value</em>,
|
||||||
unlike in C++. You really have to pass pointers to pointer arguments
|
unlike in C++. You really have to pass pointers to pointer arguments
|
||||||
and numbers to number arguments.
|
and numbers to number arguments.
|
||||||
@@ -291,12 +291,12 @@ Here's the step-by-step explanation:
|
|||||||
<p>
|
<p>
|
||||||
<span class="mark">①</span> This defines some of the
|
<span class="mark">①</span> This defines some of the
|
||||||
C functions provided by zlib. For the sake of this example, some
|
C functions provided by zlib. For the sake of this example, some
|
||||||
type indirections have been reduced and it uses the pre-defined
|
type indirections have been reduced and it uses the predefined
|
||||||
fixed-size integer types, while still adhering to the zlib API/ABI.
|
fixed-size integer types, while still adhering to the zlib API/ABI.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="mark">②</span> This loads the zlib shared
|
<span class="mark">②</span> This loads the zlib shared
|
||||||
library. On POSIX systems it's named <tt>libz.so</tt> and usually
|
library. On POSIX systems, it's named <tt>libz.so</tt> and usually
|
||||||
comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
|
comes pre-installed. Since <tt>ffi.load()</tt> automatically adds any
|
||||||
missing standard prefixes/suffixes, we can simply load the
|
missing standard prefixes/suffixes, we can simply load the
|
||||||
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
|
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
|
||||||
@@ -324,7 +324,7 @@ actual length that was used.
|
|||||||
<p>
|
<p>
|
||||||
In C you'd pass in the address of a local variable
|
In C you'd pass in the address of a local variable
|
||||||
(<tt>&buflen</tt>). But since there's no address-of operator in
|
(<tt>&buflen</tt>). But since there's no address-of operator in
|
||||||
Lua, we'll just pass in a one-element array. Conveniently it can be
|
Lua, we'll just pass in a one-element array. Conveniently, it can be
|
||||||
initialized with the maximum buffer size in one step. Calling the
|
initialized with the maximum buffer size in one step. Calling the
|
||||||
actual <tt>zlib.compress2</tt> function is then straightforward.
|
actual <tt>zlib.compress2</tt> function is then straightforward.
|
||||||
</p>
|
</p>
|
||||||
@@ -348,7 +348,7 @@ for garbage collection and string interning.
|
|||||||
<span class="mark">⑥</span> The <tt>uncompress</tt>
|
<span class="mark">⑥</span> The <tt>uncompress</tt>
|
||||||
functions does the exact opposite of the <tt>compress</tt> function.
|
functions does the exact opposite of the <tt>compress</tt> function.
|
||||||
The compressed data doesn't include the size of the original string,
|
The compressed data doesn't include the size of the original string,
|
||||||
so this needs to be passed in. Otherwise no surprises here.
|
so this needs to be passed in. Otherwise, no surprises here.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="mark">⑦</span> The code, that makes use
|
<span class="mark">⑦</span> The code, that makes use
|
||||||
@@ -382,7 +382,7 @@ Ok, so the <tt>ffi.*</tt> functions generally accept cdata objects
|
|||||||
wherever you'd want to use a number. That's why we get a away with
|
wherever you'd want to use a number. That's why we get a away with
|
||||||
passing <tt>n</tt> to <tt>ffi.string()</tt> above. But other Lua
|
passing <tt>n</tt> to <tt>ffi.string()</tt> above. But other Lua
|
||||||
library functions or modules don't know how to deal with this. So for
|
library functions or modules don't know how to deal with this. So for
|
||||||
maximum portability one needs to use <tt>tonumber()</tt> on returned
|
maximum portability, one needs to use <tt>tonumber()</tt> on returned
|
||||||
<tt>long</tt> results before passing them on. Otherwise the
|
<tt>long</tt> results before passing them on. Otherwise the
|
||||||
application might work on some systems, but would fail in a POSIX/x64
|
application might work on some systems, but would fail in a POSIX/x64
|
||||||
environment.
|
environment.
|
||||||
@@ -454,7 +454,7 @@ the origin.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="mark">④</span> If we run out of operators, we can
|
<span class="mark">④</span> If we run out of operators, we can
|
||||||
define named methods, too. Here the <tt>__index</tt> table defines an
|
define named methods, too. Here, the <tt>__index</tt> table defines an
|
||||||
<tt>area</tt> function. For custom indexing needs, one might want to
|
<tt>area</tt> function. For custom indexing needs, one might want to
|
||||||
define <tt>__index</tt> and <tt>__newindex</tt> <em>functions</em> instead.
|
define <tt>__index</tt> and <tt>__newindex</tt> <em>functions</em> instead.
|
||||||
</p>
|
</p>
|
||||||
@@ -468,13 +468,13 @@ be used e.g. to create an array of points. The metamethods automatically
|
|||||||
apply to any and all uses of this type.
|
apply to any and all uses of this type.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Please note that the association with a metatable is permanent and
|
Please note, that the association with a metatable is permanent and
|
||||||
<b>the metatable must not be modified afterwards!</b> Ditto for the
|
<b>the metatable must not be modified afterwards!</b> Ditto for the
|
||||||
<tt>__index</tt> table.
|
<tt>__index</tt> table.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span class="mark">⑥</span> Here are some simple usage examples
|
<span class="mark">⑥</span> Here are some simple usage examples
|
||||||
for the point type and their expected results. The pre-defined
|
for the point type and their expected results. The predefined
|
||||||
operations (such as <tt>a.x</tt>) can be freely mixed with the newly
|
operations (such as <tt>a.x</tt>) can be freely mixed with the newly
|
||||||
defined metamethods. Note that <tt>area</tt> is a method and must be
|
defined metamethods. Note that <tt>area</tt> is a method and must be
|
||||||
called with the Lua syntax for methods: <tt>a:area()</tt>, not
|
called with the Lua syntax for methods: <tt>a:area()</tt>, not
|
||||||
@@ -483,7 +483,7 @@ called with the Lua syntax for methods: <tt>a:area()</tt>, not
|
|||||||
<p>
|
<p>
|
||||||
The C type metamethod mechanism is most useful when used in
|
The C type metamethod mechanism is most useful when used in
|
||||||
conjunction with C libraries that are written in an object-oriented
|
conjunction with C libraries that are written in an object-oriented
|
||||||
style. Creators return a pointer to a new instance and methods take an
|
style. Creators return a pointer to a new instance, and methods take an
|
||||||
instance pointer as the first argument. Sometimes you can just point
|
instance pointer as the first argument. Sometimes you can just point
|
||||||
<tt>__index</tt> to the library namespace and <tt>__gc</tt> to the
|
<tt>__index</tt> to the library namespace and <tt>__gc</tt> to the
|
||||||
destructor and you're done. But often enough you'll want to add
|
destructor and you're done. But often enough you'll want to add
|
||||||
@@ -569,7 +569,7 @@ end
|
|||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
This turns them into indirect calls and generates bigger and slower
|
This turns them into indirect calls and generates bigger and slower
|
||||||
machine code. Instead you'll want to cache the namespace itself and
|
machine code. Instead, you'll want to cache the namespace itself and
|
||||||
rely on the JIT compiler to eliminate the lookups:
|
rely on the JIT compiler to eliminate the lookups:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<pre class="code">
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ Contains the target architecture name:
|
|||||||
|
|
||||||
<h2 id="jit_opt"><tt>jit.opt.*</tt> — JIT compiler optimization control</h2>
|
<h2 id="jit_opt"><tt>jit.opt.*</tt> — JIT compiler optimization control</h2>
|
||||||
<p>
|
<p>
|
||||||
This sub-module provides the backend for the <tt>-O</tt> command line
|
This submodule provides the backend for the <tt>-O</tt> command line
|
||||||
option.
|
option.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -174,7 +174,7 @@ which was one of the ways to enable optimization.
|
|||||||
|
|
||||||
<h2 id="jit_util"><tt>jit.util.*</tt> — JIT compiler introspection</h2>
|
<h2 id="jit_util"><tt>jit.util.*</tt> — JIT compiler introspection</h2>
|
||||||
<p>
|
<p>
|
||||||
This sub-module holds functions to introspect the bytecode, generated
|
This submodule holds functions to introspect the bytecode, generated
|
||||||
traces, the IR and the generated machine code. The functionality
|
traces, the IR and the generated machine code. The functionality
|
||||||
provided by this module is still in flux and therefore undocumented.
|
provided by this module is still in flux and therefore undocumented.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ To see how much time is spent in different VM states or
|
|||||||
Combinations of <tt>v/z</tt> with <tt>f/F/l</tt> produce two-level
|
Combinations of <tt>v/z</tt> with <tt>f/F/l</tt> produce two-level
|
||||||
views, e.g. <tt>-jp=vf</tt> or <tt>-jp=fv</tt>. This shows the time
|
views, e.g. <tt>-jp=vf</tt> or <tt>-jp=fv</tt>. This shows the time
|
||||||
spent in a VM state or zone vs. hotspots. This can be used to answer
|
spent in a VM state or zone vs. hotspots. This can be used to answer
|
||||||
questions like "Which time consuming functions are only interpreted?" or
|
questions like "Which time-consuming functions are only interpreted?" or
|
||||||
"What's the garbage collector overhead for a specific function?".
|
"What's the garbage collector overhead for a specific function?".
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -217,7 +217,7 @@ local profile = require("jit.profile")
|
|||||||
This module can be used to implement your own higher-level profiler.
|
This module can be used to implement your own higher-level profiler.
|
||||||
A typical profiling run starts the profiler, captures stack dumps in
|
A typical profiling run starts the profiler, captures stack dumps in
|
||||||
the profiler callback, adds them to a hash table to aggregate the number
|
the profiler callback, adds them to a hash table to aggregate the number
|
||||||
of samples, stops the profiler and then analyzes all of the captured
|
of samples, stops the profiler and then analyzes all captured
|
||||||
stack dumps. Other parameters can be sampled in the profiler callback,
|
stack dumps. Other parameters can be sampled in the profiler callback,
|
||||||
too. But it's important not to spend too much time in the callback,
|
too. But it's important not to spend too much time in the callback,
|
||||||
since this may skew the statistics.
|
since this may skew the statistics.
|
||||||
@@ -271,9 +271,9 @@ returns a string with a stack dump for the <tt>thread</tt> (coroutine),
|
|||||||
formatted according to the <tt>fmt</tt> argument:
|
formatted according to the <tt>fmt</tt> argument:
|
||||||
</p>
|
</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>p</tt> — Preserve the full path for module names. Otherwise
|
<li><tt>p</tt> — Preserve the full path for module names. Otherwise,
|
||||||
only the file name is used.</li>
|
only the file name is used.</li>
|
||||||
<li><tt>f</tt> — Dump the function name if it can be derived. Otherwise
|
<li><tt>f</tt> — Dump the function name if it can be derived. Otherwise,
|
||||||
use module:line.</li>
|
use module:line.</li>
|
||||||
<li><tt>F</tt> — Ditto, but dump module:name.</li>
|
<li><tt>F</tt> — Ditto, but dump module:name.</li>
|
||||||
<li><tt>l</tt> — Dump module:line.</li>
|
<li><tt>l</tt> — Dump module:line.</li>
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ or LuaJIT.
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
LuaJIT extends the standard Lua VM with new functionality and adds
|
LuaJIT extends the standard Lua VM with new functionality and adds
|
||||||
several extension modules. Please note this page is only about
|
several extension modules. Please note, this page is only about
|
||||||
<em>functional</em> enhancements and not about performance enhancements,
|
<em>functional</em> enhancements and not about performance enhancements,
|
||||||
such as the optimized VM, the faster interpreter or the JIT compiler.
|
such as the optimized VM, the faster interpreter or the JIT compiler.
|
||||||
</p>
|
</p>
|
||||||
@@ -197,7 +197,7 @@ usage. See also the
|
|||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The generated bytecode is portable and can be loaded on any architecture
|
The generated bytecode is portable and can be loaded on any architecture
|
||||||
that LuaJIT supports, independent of word size or endianess. However the
|
that LuaJIT supports, independent of word size or endianess. However, the
|
||||||
bytecode compatibility versions must match. Bytecode stays compatible
|
bytecode compatibility versions must match. Bytecode stays compatible
|
||||||
for dot releases (x.y.0 → x.y.1), but may change with major or
|
for dot releases (x.y.0 → x.y.1), but may change with major or
|
||||||
minor releases (2.0 → 2.1) or between any beta release. Foreign
|
minor releases (2.0 → 2.1) or between any beta release. Foreign
|
||||||
@@ -229,7 +229,7 @@ avoids managing backlinks, saves an allocation and the overhead of
|
|||||||
incremental array/hash part growth.
|
incremental array/hash part growth.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Please note this function is meant for very specific situations. In most
|
Please note, this function is meant for very specific situations. In most
|
||||||
cases it's better to replace the (usually single) link with a new table
|
cases it's better to replace the (usually single) link with a new table
|
||||||
and let the GC do its work.
|
and let the GC do its work.
|
||||||
</p>
|
</p>
|
||||||
@@ -239,7 +239,7 @@ and let the GC do its work.
|
|||||||
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
|
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
|
||||||
<tt>math.random()</tt> and <tt>math.randomseed()</tt>. The quality of
|
<tt>math.random()</tt> and <tt>math.randomseed()</tt>. The quality of
|
||||||
the PRNG results is much superior compared to the standard Lua
|
the PRNG results is much superior compared to the standard Lua
|
||||||
implementation which uses the platform-specific ANSI rand().
|
implementation, which uses the platform-specific ANSI rand().
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The PRNG generates the same sequences from the same seeds on all
|
The PRNG generates the same sequences from the same seeds on all
|
||||||
@@ -257,7 +257,7 @@ Important: Neither this nor any other PRNG based on the simplistic
|
|||||||
<h3 id="io"><tt>io.*</tt> functions handle 64 bit file offsets</h3>
|
<h3 id="io"><tt>io.*</tt> functions handle 64 bit file offsets</h3>
|
||||||
<p>
|
<p>
|
||||||
The file I/O functions in the standard <tt>io.*</tt> library handle
|
The file I/O functions in the standard <tt>io.*</tt> library handle
|
||||||
64 bit file offsets. In particular this means it's possible
|
64 bit file offsets. In particular, this means it's possible
|
||||||
to open files larger than 2 Gigabytes and to reposition or obtain
|
to open files larger than 2 Gigabytes and to reposition or obtain
|
||||||
the current file position for offsets beyond 2 GB
|
the current file position for offsets beyond 2 GB
|
||||||
(<tt>fp:seek()</tt> method).
|
(<tt>fp:seek()</tt> method).
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ Direct3D version 10 or higher do not show this behavior anymore.
|
|||||||
Consider testing your application with older versions, too.<br>
|
Consider testing your application with older versions, too.<br>
|
||||||
|
|
||||||
Similarly, the Borland/Delphi runtime modifies the FPU control word and
|
Similarly, the Borland/Delphi runtime modifies the FPU control word and
|
||||||
enables FP exceptions. Of course this violates the Windows ABI, too.
|
enables FP exceptions. Of course, this violates the Windows ABI, too.
|
||||||
Please check the Delphi docs for the Set8087CW method.</dd>
|
Please check the Delphi docs for the Set8087CW method.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ Please check the Delphi docs for the Set8087CW method.</dd>
|
|||||||
ignored by compiled code. If your program is running in a tight loop
|
ignored by compiled code. If your program is running in a tight loop
|
||||||
and never falls back to the interpreter, the debug hook never runs and
|
and never falls back to the interpreter, the debug hook never runs and
|
||||||
can't throw the "interrupted!" error.<br>
|
can't throw the "interrupted!" error.<br>
|
||||||
You have to press Ctrl-C twice to get stop your program. That's similar
|
You have to press Ctrl-C twice to stop your program. That's similar
|
||||||
to when it's stuck running inside a C function under the Lua interpreter.</dd>
|
to when it's stuck running inside a C function under the Lua interpreter.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ so it doesn't rely on the key order. Or sort the table keys, if you must.</dd>
|
|||||||
<dl id="sandbox">
|
<dl id="sandbox">
|
||||||
<dt>Q: Can Lua code be safely sandboxed?</dt>
|
<dt>Q: Can Lua code be safely sandboxed?</dt>
|
||||||
<dd>
|
<dd>
|
||||||
Maybe for an extremly restricted subset of Lua and if you relentlessly
|
Maybe for an extremely restricted subset of Lua and if you relentlessly
|
||||||
scrutinize every single interface function you offer to the untrusted code.<br>
|
scrutinize every single interface function you offer to the untrusted code.<br>
|
||||||
|
|
||||||
Although Lua provides some sandboxing functionality (<tt>setfenv()</tt>, hooks),
|
Although Lua provides some sandboxing functionality (<tt>setfenv()</tt>, hooks),
|
||||||
|
|||||||
+241
-92
@@ -14,25 +14,20 @@ table.compat {
|
|||||||
}
|
}
|
||||||
table.compat td {
|
table.compat td {
|
||||||
border: 1px solid #bfcfff;
|
border: 1px solid #bfcfff;
|
||||||
height: 2.5em;
|
height: 1.5em;
|
||||||
}
|
}
|
||||||
table.compat tr.compathead td {
|
table.compat tr.compathead td {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border-bottom: 2px solid #bfcfff;
|
border-bottom: 2px solid #bfcfff;
|
||||||
}
|
}
|
||||||
tr.compathead td.compatos {
|
td.compatname, td.compatver {
|
||||||
vertical-align: top;
|
width: 10%;
|
||||||
}
|
}
|
||||||
table.compat td.compatcpu {
|
td.compatbits {
|
||||||
width: 18%;
|
width: 5%;
|
||||||
border-right: 2px solid #bfcfff;
|
|
||||||
}
|
}
|
||||||
td.compatos {
|
td.compatx {
|
||||||
width: 21%;
|
width: 21%;
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
td.compatno {
|
|
||||||
background-color: #d0d0d0;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -95,62 +90,204 @@ For the impatient (on POSIX systems):
|
|||||||
<pre class="code">
|
<pre class="code">
|
||||||
make && sudo make install
|
make && sudo make install
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="req">Requirements</h2>
|
||||||
|
<h3 id="systems">Systems</h3>
|
||||||
<p>
|
<p>
|
||||||
LuaJIT currently builds out-of-the box on most systems.
|
LuaJIT currently builds out-of-the box on most systems:
|
||||||
Here's the compatibility matrix for the supported combinations of
|
|
||||||
operating systems, CPUs and compilers:
|
|
||||||
</p>
|
</p>
|
||||||
<table class="compat">
|
<table class="compat">
|
||||||
<tr class="compathead">
|
<tr class="compathead">
|
||||||
<td class="compatcpu">CPU / OS</td>
|
<td class="compatname">OS</td>
|
||||||
<td class="compatos"><a href="#posix">Linux</a> or<br><a href="#android">Android</a></td>
|
<td class="compatver">Min. Version</td>
|
||||||
<td class="compatos"><a href="#posix">*BSD, Other</a></td>
|
<td class="compatx">Requirements</td>
|
||||||
<td class="compatos"><a href="#posix">macOS 10.4+</a> or<br><a href="#ios">iOS 3.0+</a></td>
|
<td class="compatx">LuaJIT Versions</td>
|
||||||
<td class="compatos"><a href="#windows">Windows 7<br>or later</a></td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd separate">
|
<tr class="odd separate">
|
||||||
<td class="compatcpu">x86 (32 bit)</td>
|
<td class="compatname"><a href="#windows">Windows</a></td>
|
||||||
<td class="compatos">GCC 4.2+</td>
|
<td class="compatver">7</td>
|
||||||
<td class="compatos">GCC 4.2+</td>
|
<td class="compatx">x86 or x64, ARM64: TBA</td>
|
||||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
<td class="compatx">v2.0 –</td>
|
||||||
<td class="compatos">MSVC<br>MinGW, Cygwin</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="compatcpu">x64 (64 bit)</td>
|
<td class="compatname"><a href="#posix">Linux</a></td>
|
||||||
<td class="compatos">GCC 4.2+</td>
|
<td class="compatver"> </td>
|
||||||
<td class="compatos">GCC 4.2+<br>ORBIS (<a href="#ps4">PS4</a>)</td>
|
<td class="compatx"> </td>
|
||||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
<td class="compatx">v2.0 –</td>
|
||||||
<td class="compatos">MSVC<br>Durango (<a href="#xboxone">Xbox One</a>)</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd">
|
<tr class="odd">
|
||||||
<td class="compatcpu"><a href="#cross2">ARMv5+<br>ARM9E+</a></td>
|
<td class="compatname"><a href="#posix">*BSD</a></td>
|
||||||
<td class="compatos">GCC 4.2+</td>
|
<td class="compatver"> </td>
|
||||||
<td class="compatos">GCC 4.2+<br>PSP2 (<a href="#psvita">PS VITA</a>)</td>
|
<td class="compatx"> </td>
|
||||||
<td class="compatos">XCode 5.0+<br>Clang</td>
|
<td class="compatx">v2.0 –</td>
|
||||||
<td class="compatos compatno"> </td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="compatcpu"><a href="#cross2">ARM64<br>ARM64be</a></td>
|
<td class="compatname"><a href="#posix">macOS (OSX)</a></td>
|
||||||
<td class="compatos">GCC 4.8+</td>
|
<td class="compatver">10.4</td>
|
||||||
<td class="compatos compatno"> </td>
|
<td class="compatx"> </td>
|
||||||
<td class="compatos">XCode 6.0+<br>Clang 3.5+</td>
|
<td class="compatx">v2.1 –</td>
|
||||||
<td class="compatos compatno"> </td>
|
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="odd">
|
<tr class="odd">
|
||||||
<td class="compatcpu"><a href="#cross2">PPC</a></td>
|
<td class="compatname"><a href="#posix">POSIX</a></td>
|
||||||
<td class="compatos">GCC 4.3+</td>
|
<td class="compatver"> </td>
|
||||||
<td class="compatos">GCC 4.3+<br>GCC 4.1 (<a href="#ps3">PS3</a>)</td>
|
<td class="compatx">mmap, dlopen</td>
|
||||||
<td class="compatos compatno"> </td>
|
<td class="compatx">v2.0 –</td>
|
||||||
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
|
</tr>
|
||||||
|
<tr class="even separate">
|
||||||
|
<td class="compatname"><a href="#android">Android</a></td>
|
||||||
|
<td class="compatver">4.0</td>
|
||||||
|
<td class="compatx">Recent Android NDK</td>
|
||||||
|
<td class="compatx">v2.0 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname"><a href="#ios">iOS</a></td>
|
||||||
|
<td class="compatver">3.0</td>
|
||||||
|
<td class="compatx">Xcode iOS SDK</td>
|
||||||
|
<td class="compatx">v2.1 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even separate">
|
||||||
|
<td class="compatname"><a href="#consoles">PS3</a></td>
|
||||||
|
<td class="compatver"> </td>
|
||||||
|
<td class="compatx">PS3 SDK</td>
|
||||||
|
<td class="compatx">v2.0 – v2.1 EOL</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname"><a href="#consoles">PS4</a></td>
|
||||||
|
<td class="compatver"> </td>
|
||||||
|
<td class="compatx">PS4 SDK (ORBIS)</td>
|
||||||
|
<td class="compatx">v2.0 –</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="even">
|
<tr class="even">
|
||||||
<td class="compatcpu"><a href="#cross2">MIPS32<br>MIPS64<br>MIPS64r6</a></td>
|
<td class="compatname"><a href="#consoles">PS5</a></td>
|
||||||
<td class="compatos">GCC 4.3+</td>
|
<td class="compatver"> </td>
|
||||||
<td class="compatos">GCC 4.3+</td>
|
<td class="compatx">PS5 SDK (PROSPERO)</td>
|
||||||
<td class="compatos compatno"> </td>
|
<td class="compatx">v2.1 –</td>
|
||||||
<td class="compatos compatno"> </td>
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname"><a href="#consoles">PS Vita</a></td>
|
||||||
|
<td class="compatver"> </td>
|
||||||
|
<td class="compatx">PS Vita SDK (PSP2)</td>
|
||||||
|
<td class="compatx">v2.0 – v2.1 EOL</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname"><a href="#consoles">Xbox 360</a></td>
|
||||||
|
<td class="compatver"> </td>
|
||||||
|
<td class="compatx">Xbox 360 SDK (XEDK)</td>
|
||||||
|
<td class="compatx">v2.0 – v2.1 EOL</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname"><a href="#consoles">Xbox One</a></td>
|
||||||
|
<td class="compatver"> </td>
|
||||||
|
<td class="compatx">Xbox One SDK (DURANGO)</td>
|
||||||
|
<td class="compatx">v2.1 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname"><a href="#consoles">Nintendo Switch</a></td>
|
||||||
|
<td class="compatver"> </td>
|
||||||
|
<td class="compatx">NintendoSDK + NX Addon</td>
|
||||||
|
<td class="compatx">v2.1 –</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
<p>
|
||||||
|
The codebase has compatibility defines for some more systems, but
|
||||||
|
without official support.
|
||||||
|
</p>
|
||||||
|
<h3 id="toolchains">Toolchains</h3>
|
||||||
|
<p>
|
||||||
|
Building LuaJIT requires a recent toolchain based on GCC, Clang/LLVM or
|
||||||
|
MSVC++.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The Makefile-based build system requires GNU Make and supports
|
||||||
|
cross-builds. Batch files are provided for MSVC++ builds and console
|
||||||
|
cross-builds.
|
||||||
|
</p>
|
||||||
|
<h3 id="architectures">CPU Architectures</h3>
|
||||||
|
<table class="compat">
|
||||||
|
<tr class="compathead">
|
||||||
|
<td class="compatname">CPU</td>
|
||||||
|
<td class="compatbits">Bits</td>
|
||||||
|
<td class="compatx">Requirements</td>
|
||||||
|
<td class="compatx">Variants</td>
|
||||||
|
<td class="compatx">LuaJIT Versions</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd separate">
|
||||||
|
<td class="compatname">x86</td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx">v2.1+: SSE2</td>
|
||||||
|
<td class="compatx"> </td>
|
||||||
|
<td class="compatx">v2.0 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname">x64</td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx"> </td>
|
||||||
|
<td class="compatx"> </td>
|
||||||
|
<td class="compatx">v2.0 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname">ARM</td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx">ARMv5+, ARM9E+</td>
|
||||||
|
<td class="compatx">hard-fp + soft-fp</td>
|
||||||
|
<td class="compatx">v2.0 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname">ARM64</td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx"> </td>
|
||||||
|
<td class="compatx">ARM64le + ARM64be</td>
|
||||||
|
<td class="compatx">v2.1 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname">PPC32</td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx"> </td>
|
||||||
|
<td class="compatx">hard-fp + soft-fp</td>
|
||||||
|
<td class="compatx">v2.0 – v2.1 EOL</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname">PPC/e500</td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx">e500v2</td>
|
||||||
|
<td class="compatx"> </td>
|
||||||
|
<td class="compatx">v2.0 EOL</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname">MIPS32</td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx">MIPS32r1 – r5</td>
|
||||||
|
<td class="compatx">hard-fp + soft-fp</td>
|
||||||
|
<td class="compatx">v2.0 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname">MIPS64</td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx">MIPS64r1 – r5</td>
|
||||||
|
<td class="compatx">hard-fp + soft-fp</td>
|
||||||
|
<td class="compatx">v2.1 –</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname">MIPS64</td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx">MIPS64r6</td>
|
||||||
|
<td class="compatx">hard-fp + soft-fp</td>
|
||||||
|
<td class="compatx">v2.1 EOL</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname">RISC-V</td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx">RVA22+</td>
|
||||||
|
<td class="compatx"> </td>
|
||||||
|
<td class="compatx">TBA</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p>
|
||||||
|
There are no plans to add historic architectures or to continue support
|
||||||
|
for end-of-life (EOL) architectures, for which no new CPUs are commonly
|
||||||
|
available anymore. Likewise, there are no plans to support marginal
|
||||||
|
and/or de-facto-dead architectures.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2>Configuring LuaJIT</h2>
|
<h2>Configuring LuaJIT</h2>
|
||||||
<p>
|
<p>
|
||||||
@@ -191,7 +328,7 @@ The recommended way to fetch the latest version is to do a pull from
|
|||||||
the git repository.
|
the git repository.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Alternatively download the latest source package of LuaJIT (pick the .tar.gz).
|
Alternatively, download the latest source package of LuaJIT (pick the .tar.gz).
|
||||||
Move it to a directory of your choice, open a terminal window and change
|
Move it to a directory of your choice, open a terminal window and change
|
||||||
to this directory. Now unpack the archive and change to the newly created
|
to this directory. Now unpack the archive and change to the newly created
|
||||||
directory (replace XX.YY.ZZ with the version you downloaded):
|
directory (replace XX.YY.ZZ with the version you downloaded):
|
||||||
@@ -411,7 +548,7 @@ NDKCROSS=$NDKBIN/aarch64-linux-android-
|
|||||||
NDKCC=$NDKBIN/aarch64-linux-android21-clang
|
NDKCC=$NDKBIN/aarch64-linux-android21-clang
|
||||||
make CROSS=$NDKCROSS \
|
make CROSS=$NDKCROSS \
|
||||||
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
||||||
TARGET_LD=$NDKCC TARGET_AR=$NDKBIN/llvm-ar
|
TARGET_LD=$NDKCC TARGET_AR="$NDKBIN/llvm-ar rcus" \
|
||||||
TARGET_STRIP=$NDKBIN/llvm-strip
|
TARGET_STRIP=$NDKBIN/llvm-strip
|
||||||
|
|
||||||
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB)
|
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB)
|
||||||
@@ -421,7 +558,7 @@ NDKCROSS=$NDKBIN/arm-linux-androideabi-
|
|||||||
NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang
|
NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang
|
||||||
make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
|
make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
|
||||||
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
|
||||||
TARGET_LD=$NDKCC TARGET_AR=$NDKBIN/llvm-ar
|
TARGET_LD=$NDKCC TARGET_AR="$NDKBIN/llvm-ar rcus" \
|
||||||
TARGET_STRIP=$NDKBIN/llvm-strip
|
TARGET_STRIP=$NDKBIN/llvm-strip
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
@@ -446,8 +583,7 @@ make DEFAULT_CC=clang CROSS="$(dirname $ICC)/" \
|
|||||||
<h3 id="consoles">Cross-compiling for consoles</h3>
|
<h3 id="consoles">Cross-compiling for consoles</h3>
|
||||||
<p>
|
<p>
|
||||||
Building LuaJIT for consoles requires both a supported host compiler
|
Building LuaJIT for consoles requires both a supported host compiler
|
||||||
(x86 or x64) and a cross-compiler (to PPC or ARM) from the official
|
(x86 or x64) and a cross-compiler from the official console SDK.
|
||||||
console SDK.
|
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
Due to restrictions on consoles, the JIT compiler is disabled and only
|
Due to restrictions on consoles, the JIT compiler is disabled and only
|
||||||
@@ -468,45 +604,58 @@ To cross-compile for <b id="ps3">PS3</b> from a Linux host (requires
|
|||||||
make HOST_CC="gcc -m32" CROSS=ppu-lv2-
|
make HOST_CC="gcc -m32" CROSS=ppu-lv2-
|
||||||
</pre>
|
</pre>
|
||||||
<p>
|
<p>
|
||||||
To cross-compile for <b id="ps4">PS4</b> from a Windows host,
|
To cross-compile for the other consoles from a Windows host, open a
|
||||||
open a "Visual Studio .NET Command Prompt" (64 bit host compiler),
|
"Native Tools Command Prompt for VS". You need to choose either the 32
|
||||||
<tt>cd</tt> to the directory where you've unpacked the sources and
|
or the 64 bit version of the host compiler to match the target.
|
||||||
run the following commands:
|
Then <tt>cd</tt> to the <tt>src</tt> directory below where you've
|
||||||
|
unpacked the sources and run the build command given in the table:
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
<table class="compat">
|
||||||
cd src
|
<tr class="compathead">
|
||||||
ps4build
|
<td class="compatname">Console</td>
|
||||||
</pre>
|
<td class="compatbits">Bits</td>
|
||||||
|
<td class="compatx">Build Command</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd separate">
|
||||||
|
<td class="compatname"><b id="ps4">PS4</b></td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx"><tt>ps4build</tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname"><b id="ps5">PS5</b></td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx"><tt>ps5build</tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname"><b id="psvita">PS Vita</b></td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx"><tt>psvitabuild</tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname"><b id="xbox360">Xbox 360</b></td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx"><tt>xedkbuild</tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname"><b id="xboxone">Xbox One</b></td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx"><tt>xb1build</tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="even">
|
||||||
|
<td class="compatname"><b id="nx32">Nintendo Switch NX32</b></td>
|
||||||
|
<td class="compatbits">32</td>
|
||||||
|
<td class="compatx"><tt>nxbuild</tt></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td class="compatname"><b id="nx64">Nintendo Switch NX64</b></td>
|
||||||
|
<td class="compatbits">64</td>
|
||||||
|
<td class="compatx"><tt>nxbuild</tt></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
<p>
|
<p>
|
||||||
To cross-compile for <b id="psvita">PS Vita</b> from a Windows host,
|
Please check out the comments in the corresponding <tt>*.bat</tt>
|
||||||
open a "Visual Studio .NET Command Prompt" (32 bit host compiler),
|
file for more options.
|
||||||
<tt>cd</tt> to the directory where you've unpacked the sources and
|
|
||||||
run the following commands:
|
|
||||||
</p>
|
</p>
|
||||||
<pre class="code">
|
|
||||||
cd src
|
|
||||||
psvitabuild
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
To cross-compile for <b id="xbox360">Xbox 360</b> from a Windows host,
|
|
||||||
open a "Visual Studio .NET Command Prompt" (32 bit host compiler),
|
|
||||||
<tt>cd</tt> to the directory where you've unpacked the sources and run
|
|
||||||
the following commands:
|
|
||||||
</p>
|
|
||||||
<pre class="code">
|
|
||||||
cd src
|
|
||||||
xedkbuild
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
To cross-compile for <b id="xboxone">Xbox One</b> from a Windows host,
|
|
||||||
open a "Visual Studio .NET Command Prompt" (64 bit host compiler),
|
|
||||||
<tt>cd</tt> to the directory where you've unpacked the sources and run
|
|
||||||
the following commands:
|
|
||||||
</p>
|
|
||||||
<pre class="code">
|
|
||||||
cd src
|
|
||||||
xb1build
|
|
||||||
</pre>
|
|
||||||
|
|
||||||
<h2 id="embed">Embedding LuaJIT</h2>
|
<h2 id="embed">Embedding LuaJIT</h2>
|
||||||
<p>
|
<p>
|
||||||
@@ -548,7 +697,7 @@ allocator from your system (no support for this on 64 bit architectures).</
|
|||||||
of calling <tt>luaopen_base</tt> etc. directly.</li>
|
of calling <tt>luaopen_base</tt> etc. directly.</li>
|
||||||
<li>To change or extend the list of standard libraries to load, copy
|
<li>To change or extend the list of standard libraries to load, copy
|
||||||
<tt>src/lib_init.c</tt> to your project and modify it accordingly.
|
<tt>src/lib_init.c</tt> to your project and modify it accordingly.
|
||||||
Make sure the <tt>jit</tt> library is loaded or the JIT compiler
|
Make sure the <tt>jit</tt> library is loaded, or the JIT compiler
|
||||||
will not be activated.</li>
|
will not be activated.</li>
|
||||||
<li>The <tt>bit.*</tt> module for bitwise operations
|
<li>The <tt>bit.*</tt> module for bitwise operations
|
||||||
is already built-in. There's no need to statically link
|
is already built-in. There's no need to statically link
|
||||||
@@ -567,7 +716,7 @@ in unspeakable ways.
|
|||||||
There should be absolutely no need to patch <tt>luaconf.h</tt> or any
|
There should be absolutely no need to patch <tt>luaconf.h</tt> or any
|
||||||
of the Makefiles. And please do not hand-pick files for your packages —
|
of the Makefiles. And please do not hand-pick files for your packages —
|
||||||
simply use whatever <tt>make install</tt> creates. There's a reason
|
simply use whatever <tt>make install</tt> creates. There's a reason
|
||||||
for all of the files <em>and</em> directories it creates.
|
for all the files <em>and</em> directories it creates.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The build system uses GNU make and auto-detects most settings based on
|
The build system uses GNU make and auto-detects most settings based on
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ LuaJIT is Copyright © 2005-2022 Mike Pall, released under the
|
|||||||
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
|
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
|
||||||
</table>
|
</table>
|
||||||
<table class="feature os os3">
|
<table class="feature os os3">
|
||||||
<tr><td>PS3</td><td>PS4</td><td>PS Vita</td><td>Xbox 360</td><td>Xbox One</td></tr>
|
<tr><td>PS3</td><td>PS4<br>PS5</td><td>PS Vita</td><td>Xbox 360</td><td>Xbox One</td><td>Nintendo<br>Switch</td></tr>
|
||||||
</table>
|
</table>
|
||||||
<table class="feature compiler">
|
<table class="feature compiler">
|
||||||
<tr><td>GCC</td><td>Clang<br>LLVM</td><td>MSVC</td></tr>
|
<tr><td>GCC</td><td>Clang<br>LLVM</td><td>MSVC</td></tr>
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ are accepted:
|
|||||||
<li><tt>-t type</tt> — Set output file type (default: auto-detect from output name).</li>
|
<li><tt>-t type</tt> — Set output file type (default: auto-detect from output name).</li>
|
||||||
<li><tt>-a arch</tt> — Override architecture for object files (default: native).</li>
|
<li><tt>-a arch</tt> — Override architecture for object files (default: native).</li>
|
||||||
<li><tt>-o os</tt> — Override OS for object files (default: native).</li>
|
<li><tt>-o os</tt> — Override OS for object files (default: native).</li>
|
||||||
|
<li><tt>-F name</tt> — Override filename (default: input filename).</li>
|
||||||
<li><tt>-e chunk</tt> — Use chunk string as input.</li>
|
<li><tt>-e chunk</tt> — Use chunk string as input.</li>
|
||||||
<li><tt>-</tt> (a single minus sign) — Use stdin as input and/or stdout as output.</li>
|
<li><tt>-</tt> (a single minus sign) — Use stdin as input and/or stdout as output.</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -184,7 +185,7 @@ written in Lua. They are mainly used for debugging the JIT compiler
|
|||||||
itself. For a description of their options and output format, please
|
itself. For a description of their options and output format, please
|
||||||
read the comment block at the start of their source.
|
read the comment block at the start of their source.
|
||||||
They can be found in the <tt>lib</tt> directory of the source
|
They can be found in the <tt>lib</tt> directory of the source
|
||||||
distribution or installed under the <tt>jit</tt> directory. By default
|
distribution or installed under the <tt>jit</tt> directory. By default,
|
||||||
this is <tt>/usr/local/share/luajit-XX.YY.ZZ>/jit</tt> on POSIX
|
this is <tt>/usr/local/share/luajit-XX.YY.ZZ>/jit</tt> on POSIX
|
||||||
systems (replace XX.YY.ZZ by the installed version).
|
systems (replace XX.YY.ZZ by the installed version).
|
||||||
</p>
|
</p>
|
||||||
@@ -216,7 +217,7 @@ to a specific value.
|
|||||||
You can either use this option multiple times (like <tt>-Ocse
|
You can either use this option multiple times (like <tt>-Ocse
|
||||||
-O-dce -Ohotloop=10</tt>) or separate several settings with a comma
|
-O-dce -Ohotloop=10</tt>) or separate several settings with a comma
|
||||||
(like <tt>-O+cse,-dce,hotloop=10</tt>). The settings are applied from
|
(like <tt>-O+cse,-dce,hotloop=10</tt>). The settings are applied from
|
||||||
left to right and later settings override earlier ones. You can freely
|
left to right, and later settings override earlier ones. You can freely
|
||||||
mix the three forms, but note that setting an optimization level
|
mix the three forms, but note that setting an optimization level
|
||||||
overrides all earlier flags.
|
overrides all earlier flags.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ Known incompatibilities and issues in LuaJIT 2.0:
|
|||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
There are some differences in <b>implementation-defined</b> behavior.
|
There are some differences in <b>implementation-defined</b> behavior.
|
||||||
These either have a good reason, are arbitrary design choices
|
These either have a good reason, are arbitrary design choices,
|
||||||
or are due to quirks in the VM. The latter cases may get fixed if a
|
or are due to quirks in the VM. The latter cases may get fixed if a
|
||||||
demonstrable need is shown.
|
demonstrable need is shown.
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -158,10 +158,10 @@ void dasm_setup(Dst_DECL, const void *actionlist)
|
|||||||
#ifdef DASM_CHECKS
|
#ifdef DASM_CHECKS
|
||||||
#define CK(x, st) \
|
#define CK(x, st) \
|
||||||
do { if (!(x)) { \
|
do { if (!(x)) { \
|
||||||
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
|
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||||
#define CKPL(kind, st) \
|
#define CKPL(kind, st) \
|
||||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||||
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
|
D->status = DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||||
#else
|
#else
|
||||||
#define CK(x, st) ((void)0)
|
#define CK(x, st) ((void)0)
|
||||||
#define CKPL(kind, st) ((void)0)
|
#define CKPL(kind, st) ((void)0)
|
||||||
@@ -190,7 +190,9 @@ static int dasm_imm13(int lo, int hi)
|
|||||||
unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
|
unsigned long long n = (((unsigned long long)hi) << 32) | (unsigned int)lo;
|
||||||
unsigned long long m = 1ULL, a, b, c;
|
unsigned long long m = 1ULL, a, b, c;
|
||||||
if (n & 1) { n = ~n; inv = 1; }
|
if (n & 1) { n = ~n; inv = 1; }
|
||||||
a = n & -n; b = (n+a)&-(n+a); c = (n+a-b)&-(n+a-b);
|
a = n & (unsigned long long)-(long long)n;
|
||||||
|
b = (n+a)&(unsigned long long)-(long long)(n+a);
|
||||||
|
c = (n+a-b)&(unsigned long long)-(long long)(n+a-b);
|
||||||
xa = dasm_ffs(a); xb = dasm_ffs(b);
|
xa = dasm_ffs(a); xb = dasm_ffs(b);
|
||||||
if (c) {
|
if (c) {
|
||||||
w = dasm_ffs(c) - xa;
|
w = dasm_ffs(c) - xa;
|
||||||
@@ -406,7 +408,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
|
|
||||||
#ifdef DASM_CHECKS
|
#ifdef DASM_CHECKS
|
||||||
#define CK(x, st) \
|
#define CK(x, st) \
|
||||||
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
|
do { if (!(x)) return DASM_S_##st|(int)(p-D->actionlist-1); } while (0)
|
||||||
#else
|
#else
|
||||||
#define CK(x, st) ((void)0)
|
#define CK(x, st) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
@@ -438,7 +440,7 @@ int dasm_encode(Dst_DECL, void *buffer)
|
|||||||
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
|
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
|
||||||
goto patchrel;
|
goto patchrel;
|
||||||
case DASM_ALIGN:
|
case DASM_ALIGN:
|
||||||
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
|
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xd503201f;
|
||||||
break;
|
break;
|
||||||
case DASM_REL_LG:
|
case DASM_REL_LG:
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
@@ -554,7 +556,7 @@ int dasm_checkstep(Dst_DECL, int secmatch)
|
|||||||
}
|
}
|
||||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||||
D->section != &D->sections[secmatch])
|
D->section != &D->sections[secmatch])
|
||||||
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
|
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
|
||||||
return D->status;
|
return D->status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ local map_cond = {
|
|||||||
|
|
||||||
local parse_reg_type
|
local parse_reg_type
|
||||||
|
|
||||||
local function parse_reg(expr, shift)
|
local function parse_reg(expr, shift, no_vreg)
|
||||||
if not expr then werror("expected register name") end
|
if not expr then werror("expected register name") end
|
||||||
local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
|
local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
|
||||||
if not tname then
|
if not tname then
|
||||||
@@ -281,7 +281,7 @@ local function parse_reg(expr, shift)
|
|||||||
elseif parse_reg_type ~= vrt then
|
elseif parse_reg_type ~= vrt then
|
||||||
werror("register size mismatch")
|
werror("register size mismatch")
|
||||||
end
|
end
|
||||||
if shift then waction("VREG", shift, vreg) end
|
if not no_vreg then waction("VREG", shift, vreg) end
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
werror("bad register name `"..expr.."'")
|
werror("bad register name `"..expr.."'")
|
||||||
@@ -638,7 +638,7 @@ local function alias_bfx(p)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function alias_bfiz(p)
|
local function alias_bfiz(p)
|
||||||
parse_reg(p[1], 0)
|
parse_reg(p[1], 0, true)
|
||||||
if parse_reg_type == "w" then
|
if parse_reg_type == "w" then
|
||||||
p[3] = "#(32-("..p[3]:sub(2).."))%32"
|
p[3] = "#(32-("..p[3]:sub(2).."))%32"
|
||||||
p[4] = "#("..p[4]:sub(2)..")-1"
|
p[4] = "#("..p[4]:sub(2)..")-1"
|
||||||
@@ -649,7 +649,7 @@ local function alias_bfiz(p)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local alias_lslimm = op_alias("ubfm_4", function(p)
|
local alias_lslimm = op_alias("ubfm_4", function(p)
|
||||||
parse_reg(p[1], 0)
|
parse_reg(p[1], 0, true)
|
||||||
local sh = p[3]:sub(2)
|
local sh = p[3]:sub(2)
|
||||||
if parse_reg_type == "w" then
|
if parse_reg_type == "w" then
|
||||||
p[3] = "#(32-("..sh.."))%32"
|
p[3] = "#(32-("..sh.."))%32"
|
||||||
|
|||||||
@@ -155,10 +155,10 @@ void dasm_setup(Dst_DECL, const void *actionlist)
|
|||||||
#ifdef DASM_CHECKS
|
#ifdef DASM_CHECKS
|
||||||
#define CK(x, st) \
|
#define CK(x, st) \
|
||||||
do { if (!(x)) { \
|
do { if (!(x)) { \
|
||||||
D->status = DASM_S_##st|(p-D->actionlist-1); return; } } while (0)
|
D->status = DASM_S_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||||
#define CKPL(kind, st) \
|
#define CKPL(kind, st) \
|
||||||
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
do { if ((size_t)((char *)pl-(char *)D->kind##labels) >= D->kind##size) { \
|
||||||
D->status = DASM_S_RANGE_##st|(p-D->actionlist-1); return; } } while (0)
|
D->status = DASM_S_RANGE_##st|(int)(p-D->actionlist-1); return; } } while (0)
|
||||||
#else
|
#else
|
||||||
#define CK(x, st) ((void)0)
|
#define CK(x, st) ((void)0)
|
||||||
#define CKPL(kind, st) ((void)0)
|
#define CKPL(kind, st) ((void)0)
|
||||||
@@ -314,7 +314,7 @@ int dasm_link(Dst_DECL, size_t *szp)
|
|||||||
|
|
||||||
#ifdef DASM_CHECKS
|
#ifdef DASM_CHECKS
|
||||||
#define CK(x, st) \
|
#define CK(x, st) \
|
||||||
do { if (!(x)) return DASM_S_##st|(p-D->actionlist-1); } while (0)
|
do { if (!(x)) return DASM_S_##st|(int)(p-D->actionlist-1); } while (0)
|
||||||
#else
|
#else
|
||||||
#define CK(x, st) ((void)0)
|
#define CK(x, st) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
@@ -417,7 +417,7 @@ int dasm_checkstep(Dst_DECL, int secmatch)
|
|||||||
}
|
}
|
||||||
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
if (D->status == DASM_S_OK && secmatch >= 0 &&
|
||||||
D->section != &D->sections[secmatch])
|
D->section != &D->sections[secmatch])
|
||||||
D->status = DASM_S_MATCH_SEC|(D->section-D->sections);
|
D->status = DASM_S_MATCH_SEC|(int)(D->section-D->sections);
|
||||||
return D->status;
|
return D->status;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,8 +18,10 @@
|
|||||||
#include "lj_obj.h"
|
#include "lj_obj.h"
|
||||||
#include "lj_gc.h"
|
#include "lj_gc.h"
|
||||||
#include "lj_bc.h"
|
#include "lj_bc.h"
|
||||||
|
#if LJ_HASJIT
|
||||||
#include "lj_ir.h"
|
#include "lj_ir.h"
|
||||||
#include "lj_ircall.h"
|
#include "lj_ircall.h"
|
||||||
|
#endif
|
||||||
#include "lj_frame.h"
|
#include "lj_frame.h"
|
||||||
#include "lj_dispatch.h"
|
#include "lj_dispatch.h"
|
||||||
#if LJ_HASFFI
|
#if LJ_HASFFI
|
||||||
@@ -250,6 +252,7 @@ BCDEF(BCNAME)
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if LJ_HASJIT
|
||||||
const char *const ir_names[] = {
|
const char *const ir_names[] = {
|
||||||
#define IRNAME(name, m, m1, m2) #name,
|
#define IRNAME(name, m, m1, m2) #name,
|
||||||
IRDEF(IRNAME)
|
IRDEF(IRNAME)
|
||||||
@@ -290,7 +293,9 @@ static const char *const trace_errors[] = {
|
|||||||
#include "lj_traceerr.h"
|
#include "lj_traceerr.h"
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LJ_HASJIT
|
||||||
static const char *lower(char *buf, const char *s)
|
static const char *lower(char *buf, const char *s)
|
||||||
{
|
{
|
||||||
char *p = buf;
|
char *p = buf;
|
||||||
@@ -301,6 +306,7 @@ static const char *lower(char *buf, const char *s)
|
|||||||
*p = '\0';
|
*p = '\0';
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Emit C source code for bytecode-related definitions. */
|
/* Emit C source code for bytecode-related definitions. */
|
||||||
static void emit_bcdef(BuildCtx *ctx)
|
static void emit_bcdef(BuildCtx *ctx)
|
||||||
@@ -318,7 +324,9 @@ static void emit_bcdef(BuildCtx *ctx)
|
|||||||
/* Emit VM definitions as Lua code for debug modules. */
|
/* Emit VM definitions as Lua code for debug modules. */
|
||||||
static void emit_vmdef(BuildCtx *ctx)
|
static void emit_vmdef(BuildCtx *ctx)
|
||||||
{
|
{
|
||||||
|
#if LJ_HASJIT
|
||||||
char buf[80];
|
char buf[80];
|
||||||
|
#endif
|
||||||
int i;
|
int i;
|
||||||
fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n");
|
fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\n\n");
|
||||||
fprintf(ctx->fp, "return {\n\n");
|
fprintf(ctx->fp, "return {\n\n");
|
||||||
@@ -327,6 +335,7 @@ static void emit_vmdef(BuildCtx *ctx)
|
|||||||
for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]);
|
for (i = 0; bc_names[i]; i++) fprintf(ctx->fp, "%-6s", bc_names[i]);
|
||||||
fprintf(ctx->fp, "\",\n\n");
|
fprintf(ctx->fp, "\",\n\n");
|
||||||
|
|
||||||
|
#if LJ_HASJIT
|
||||||
fprintf(ctx->fp, "irnames = \"");
|
fprintf(ctx->fp, "irnames = \"");
|
||||||
for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]);
|
for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]);
|
||||||
fprintf(ctx->fp, "\",\n\n");
|
fprintf(ctx->fp, "\",\n\n");
|
||||||
@@ -355,6 +364,7 @@ static void emit_vmdef(BuildCtx *ctx)
|
|||||||
for (i = 0; trace_errors[i]; i++)
|
for (i = 0; trace_errors[i]; i++)
|
||||||
fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]);
|
fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]);
|
||||||
fprintf(ctx->fp, "},\n\n");
|
fprintf(ctx->fp, "},\n\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Argument parsing ---------------------------------------------------- */
|
/* -- Argument parsing ---------------------------------------------------- */
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "buildvm.h"
|
#include "buildvm.h"
|
||||||
#include "lj_obj.h"
|
#include "lj_obj.h"
|
||||||
|
#if LJ_HASJIT
|
||||||
#include "lj_ir.h"
|
#include "lj_ir.h"
|
||||||
|
|
||||||
/* Context for the folding hash table generator. */
|
/* Context for the folding hash table generator. */
|
||||||
@@ -226,4 +227,10 @@ void emit_fold(BuildCtx *ctx)
|
|||||||
|
|
||||||
makehash(ctx);
|
makehash(ctx);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void emit_fold(BuildCtx *ctx)
|
||||||
|
{
|
||||||
|
UNUSED(ctx);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -4,42 +4,67 @@ static const int libbc_endian = 0;
|
|||||||
|
|
||||||
static const uint8_t libbc_code[] = {
|
static const uint8_t libbc_code[] = {
|
||||||
#if LJ_FR2
|
#if LJ_FR2
|
||||||
0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0,
|
/* math.deg */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,241,135,158,166,3,
|
||||||
0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3,
|
220,203,178,130,4,
|
||||||
16,0,5,0,21,1,0,0,76,1,2,0,0,2,10,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3,
|
/* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20,
|
||||||
0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,8,5,0,59,9,5,0,66,6,3,2,10,6,0,0,88,7,1,
|
198,190,199,252,3,
|
||||||
128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,11,0,0,0,16,16,0,12,0,16,1,9,0,43,2,
|
/* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
|
||||||
0,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,9,5,0,18,10,6,0,66,7,3,2,10,7,
|
/* table.foreachi */ 0,2,10,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,
|
||||||
0,0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12,
|
BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0,
|
||||||
0,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128,
|
BC_MOV,8,5,0,BC_TGETR,9,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128,
|
||||||
8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14,
|
BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0,
|
||||||
0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
|
/* table.foreach */ 0,2,11,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI,
|
||||||
0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
|
2,0,0,BC_MOV,3,0,0,BC_KNUM,4,0,0,BC_JMP,5,7,128,BC_MOV,7,1,0,BC_MOV,9,5,0,
|
||||||
2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16,
|
BC_MOV,10,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0,
|
||||||
3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3,
|
BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15,
|
||||||
0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0,
|
/* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
|
||||||
41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128,
|
/* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0,
|
||||||
18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,
|
0,BC_JMP,3,7,128,BC_ISEQN,2,0,0,BC_JMP,3,23,128,BC_TGETR,3,2,0,BC_KPRI,4,0,0,
|
||||||
6,252,127,76,4,2,0,0
|
BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0,
|
||||||
|
BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0,
|
||||||
|
BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7,
|
||||||
|
BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0,
|
||||||
|
BC_RET1,3,2,0,BC_RET0,0,1,0,0,2,
|
||||||
|
/* table.move */ 0,5,12,0,0,0,35,BC_ISTYPE,0,12,0,BC_ISTYPE,1,14,0,BC_ISTYPE,
|
||||||
|
2,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE,
|
||||||
|
4,12,0,BC_ISGT,1,2,0,BC_JMP,5,24,128,BC_SUBVV,5,1,3,BC_ISLT,2,3,0,BC_JMP,6,4,
|
||||||
|
128,BC_ISLE,3,1,0,BC_JMP,6,2,128,BC_ISEQV,4,0,0,BC_JMP,6,9,128,BC_MOV,6,1,0,
|
||||||
|
BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,
|
||||||
|
BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0,
|
||||||
|
BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR,
|
||||||
|
11,10,4,BC_FORL,6,252,127,BC_RET1,4,2,0,
|
||||||
#else
|
#else
|
||||||
0,1,2,0,0,1,2,24,1,0,0,76,1,2,0,241,135,158,166,3,220,203,178,130,4,0,1,2,0,
|
/* math.deg */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,241,135,158,166,3,
|
||||||
0,1,2,24,1,0,0,76,1,2,0,243,244,148,165,20,198,190,199,252,3,0,1,2,0,0,0,3,
|
220,203,178,130,4,
|
||||||
16,0,5,0,21,1,0,0,76,1,2,0,0,2,9,0,0,0,15,16,0,12,0,16,1,9,0,41,2,1,0,21,3,
|
/* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20,
|
||||||
0,0,41,4,1,0,77,2,8,128,18,6,1,0,18,7,5,0,59,8,5,0,66,6,3,2,10,6,0,0,88,7,1,
|
198,190,199,252,3,
|
||||||
128,76,6,2,0,79,2,248,127,75,0,1,0,0,2,10,0,0,0,16,16,0,12,0,16,1,9,0,43,2,
|
/* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
|
||||||
0,0,18,3,0,0,41,4,0,0,88,5,7,128,18,7,1,0,18,8,5,0,18,9,6,0,66,7,3,2,10,7,0,
|
/* table.foreachi */ 0,2,9,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,
|
||||||
0,88,8,1,128,76,7,2,0,70,5,3,3,82,5,247,127,75,0,1,0,0,1,2,0,0,0,3,16,0,12,
|
BC_KSHORT,2,1,0,BC_LEN,3,0,0,BC_KSHORT,4,1,0,BC_FORI,2,8,128,BC_MOV,6,1,0,
|
||||||
0,21,1,0,0,76,1,2,0,0,2,10,0,0,2,30,16,0,12,0,21,2,0,0,11,1,0,0,88,3,7,128,
|
BC_MOV,7,5,0,BC_TGETR,8,5,0,BC_CALL,6,3,2,BC_ISEQP,6,0,0,BC_JMP,7,1,128,
|
||||||
8,2,0,0,88,3,23,128,59,3,2,0,43,4,0,0,64,4,2,0,76,3,2,0,88,3,18,128,16,1,14,
|
BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0,
|
||||||
0,41,3,1,0,3,3,1,0,88,3,14,128,3,1,2,0,88,3,12,128,59,3,1,0,22,4,1,1,18,5,2,
|
/* table.foreach */ 0,2,10,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI,
|
||||||
0,41,6,1,0,77,4,4,128,23,8,1,7,59,9,7,0,64,9,8,0,79,4,252,127,43,4,0,0,64,4,
|
2,0,0,BC_MOV,3,0,0,BC_KNUM,4,0,0,BC_JMP,5,7,128,BC_MOV,7,1,0,BC_MOV,8,5,0,
|
||||||
2,0,76,3,2,0,75,0,1,0,0,2,0,5,12,0,0,0,35,16,0,12,0,16,1,14,0,16,2,14,0,16,
|
BC_MOV,9,6,0,BC_CALL,7,3,2,BC_ISEQP,7,0,0,BC_JMP,8,1,128,BC_RET1,7,2,0,
|
||||||
3,14,0,11,4,0,0,88,5,1,128,18,4,0,0,16,4,12,0,3,1,2,0,88,5,24,128,33,5,1,3,
|
BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15,
|
||||||
0,2,3,0,88,6,4,128,2,3,1,0,88,6,2,128,4,4,0,0,88,6,9,128,18,6,1,0,18,7,2,0,
|
/* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
|
||||||
41,8,1,0,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,6,252,127,88,6,8,128,
|
/* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0,
|
||||||
18,6,2,0,18,7,1,0,41,8,255,255,77,6,4,128,32,10,5,9,59,11,9,0,64,11,10,4,79,
|
0,BC_JMP,3,7,128,BC_ISEQN,2,0,0,BC_JMP,3,23,128,BC_TGETR,3,2,0,BC_KPRI,4,0,0,
|
||||||
6,252,127,76,4,2,0,0
|
BC_TSETR,4,2,0,BC_RET1,3,2,0,BC_JMP,3,18,128,BC_ISTYPE,1,14,0,BC_KSHORT,3,1,0,
|
||||||
|
BC_ISGT,3,1,0,BC_JMP,3,14,128,BC_ISGT,1,2,0,BC_JMP,3,12,128,BC_TGETR,3,1,0,
|
||||||
|
BC_ADDVN,4,1,1,BC_MOV,5,2,0,BC_KSHORT,6,1,0,BC_FORI,4,4,128,BC_SUBVN,8,1,7,
|
||||||
|
BC_TGETR,9,7,0,BC_TSETR,9,8,0,BC_FORL,4,252,127,BC_KPRI,4,0,0,BC_TSETR,4,2,0,
|
||||||
|
BC_RET1,3,2,0,BC_RET0,0,1,0,0,2,
|
||||||
|
/* table.move */ 0,5,12,0,0,0,35,BC_ISTYPE,0,12,0,BC_ISTYPE,1,14,0,BC_ISTYPE,
|
||||||
|
2,14,0,BC_ISTYPE,3,14,0,BC_ISNEP,4,0,0,BC_JMP,5,1,128,BC_MOV,4,0,0,BC_ISTYPE,
|
||||||
|
4,12,0,BC_ISGT,1,2,0,BC_JMP,5,24,128,BC_SUBVV,5,1,3,BC_ISLT,2,3,0,BC_JMP,6,4,
|
||||||
|
128,BC_ISLE,3,1,0,BC_JMP,6,2,128,BC_ISEQV,4,0,0,BC_JMP,6,9,128,BC_MOV,6,1,0,
|
||||||
|
BC_MOV,7,2,0,BC_KSHORT,8,1,0,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,
|
||||||
|
BC_TSETR,11,10,4,BC_FORL,6,252,127,BC_JMP,6,8,128,BC_MOV,6,2,0,BC_MOV,7,1,0,
|
||||||
|
BC_KSHORT,8,255,255,BC_FORI,6,4,128,BC_ADDVV,10,5,9,BC_TGETR,11,9,0,BC_TSETR,
|
||||||
|
11,10,4,BC_FORL,6,252,127,BC_RET1,4,2,0,
|
||||||
#endif
|
#endif
|
||||||
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct { const char *name; int ofs; } libbc_map[] = {
|
static const struct { const char *name; int ofs; } libbc_map[] = {
|
||||||
@@ -48,9 +73,9 @@ static const struct { const char *name; int ofs; } libbc_map[] = {
|
|||||||
{"string_len",50},
|
{"string_len",50},
|
||||||
{"table_foreachi",69},
|
{"table_foreachi",69},
|
||||||
{"table_foreach",136},
|
{"table_foreach",136},
|
||||||
{"table_getn",207},
|
{"table_getn",213},
|
||||||
{"table_remove",226},
|
{"table_remove",232},
|
||||||
{"table_move",355},
|
{"table_move",361},
|
||||||
{NULL,502}
|
{NULL,508}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ local function transform_lua(code)
|
|||||||
end)
|
end)
|
||||||
code = string.gsub(code, "PAIRS%((.-)%)", function(var)
|
code = string.gsub(code, "PAIRS%((.-)%)", function(var)
|
||||||
fixup.PAIRS = true
|
fixup.PAIRS = true
|
||||||
return format("nil, %s, 0", var)
|
return format("nil, %s, 0x4dp80", var)
|
||||||
end)
|
end)
|
||||||
return "return "..code, fixup
|
return "return "..code, fixup
|
||||||
end
|
end
|
||||||
@@ -79,9 +79,11 @@ local name2itype = {
|
|||||||
str = 5, func = 9, tab = 12, int = 14, num = 15
|
str = 5, func = 9, tab = 12, int = 14, num = 15
|
||||||
}
|
}
|
||||||
|
|
||||||
local BC = {}
|
local BC, BCN = {}, {}
|
||||||
for i=0,#bcnames/6-1 do
|
for i=0,#bcnames/6-1 do
|
||||||
BC[string.gsub(string.sub(bcnames, i*6+1, i*6+6), " ", "")] = i
|
local name = bcnames:sub(i*6+1, i*6+6):gsub(" ", "")
|
||||||
|
BC[name] = i
|
||||||
|
BCN[i] = name
|
||||||
end
|
end
|
||||||
local xop, xra = isbe and 3 or 0, isbe and 2 or 1
|
local xop, xra = isbe and 3 or 0, isbe and 2 or 1
|
||||||
local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3
|
local xrc, xrb = isbe and 1 or 2, isbe and 0 or 3
|
||||||
@@ -96,6 +98,7 @@ local function fixup_dump(dump, fixup)
|
|||||||
p = read_uleb128(p)
|
p = read_uleb128(p)
|
||||||
p = read_uleb128(p)
|
p = read_uleb128(p)
|
||||||
p, sizebc = read_uleb128(p)
|
p, sizebc = read_uleb128(p)
|
||||||
|
local startbc = tonumber(p - start)
|
||||||
local rawtab = {}
|
local rawtab = {}
|
||||||
for i=0,sizebc-1 do
|
for i=0,sizebc-1 do
|
||||||
local op = p[xop]
|
local op = p[xop]
|
||||||
@@ -129,7 +132,10 @@ local function fixup_dump(dump, fixup)
|
|||||||
end
|
end
|
||||||
p = p + 4
|
p = p + 4
|
||||||
end
|
end
|
||||||
return ffi.string(start, n)
|
local ndump = ffi.string(start, n)
|
||||||
|
-- Fixup hi-part of 0x4dp80 to LJ_KEYINDEX.
|
||||||
|
ndump = ndump:gsub("\x80\x80\xcd\xaa\x04", "\xff\xff\xf9\xff\x0f")
|
||||||
|
return { dump = ndump, startbc = startbc, sizebc = sizebc }
|
||||||
end
|
end
|
||||||
|
|
||||||
local function find_defs(src)
|
local function find_defs(src)
|
||||||
@@ -149,24 +155,46 @@ local function gen_header(defs)
|
|||||||
local function w(x) t[#t+1] = x end
|
local function w(x) t[#t+1] = x end
|
||||||
w("/* This is a generated file. DO NOT EDIT! */\n\n")
|
w("/* This is a generated file. DO NOT EDIT! */\n\n")
|
||||||
w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n")
|
w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n")
|
||||||
local s = ""
|
local s, sb = "", ""
|
||||||
for _,name in ipairs(defs) do
|
for i,name in ipairs(defs) do
|
||||||
s = s .. defs[name]
|
local d = defs[name]
|
||||||
|
s = s .. d.dump
|
||||||
|
sb = sb .. string.char(i) .. ("\0"):rep(d.startbc - 1)
|
||||||
|
.. (isbe and "\0\0\0\255" or "\255\0\0\0"):rep(d.sizebc)
|
||||||
|
.. ("\0"):rep(#d.dump - d.startbc - d.sizebc*4)
|
||||||
end
|
end
|
||||||
w("static const uint8_t libbc_code[] = {\n")
|
w("static const uint8_t libbc_code[] = {\n")
|
||||||
local n = 0
|
local n = 0
|
||||||
for i=1,#s do
|
for i=1,#s do
|
||||||
local x = string.byte(s, i)
|
local x = string.byte(s, i)
|
||||||
w(x); w(",")
|
local xb = string.byte(sb, i)
|
||||||
n = n + (x < 10 and 2 or (x < 100 and 3 or 4))
|
if xb == 255 then
|
||||||
if n >= 75 then n = 0; w("\n") end
|
local name = BCN[x]
|
||||||
|
local m = #name + 4
|
||||||
|
if n + m > 78 then n = 0; w("\n") end
|
||||||
|
n = n + m
|
||||||
|
w("BC_"); w(name)
|
||||||
|
else
|
||||||
|
local m = x < 10 and 2 or (x < 100 and 3 or 4)
|
||||||
|
if xb == 0 then
|
||||||
|
if n + m > 78 then n = 0; w("\n") end
|
||||||
|
else
|
||||||
|
local name = defs[xb]:gsub("_", ".")
|
||||||
|
if n ~= 0 then w("\n") end
|
||||||
|
w("/* "); w(name); w(" */ ")
|
||||||
|
n = #name + 7
|
||||||
|
end
|
||||||
|
n = n + m
|
||||||
|
w(x)
|
||||||
|
end
|
||||||
|
w(",")
|
||||||
end
|
end
|
||||||
w("0\n};\n\n")
|
w("\n0\n};\n\n")
|
||||||
w("static const struct { const char *name; int ofs; } libbc_map[] = {\n")
|
w("static const struct { const char *name; int ofs; } libbc_map[] = {\n")
|
||||||
local m = 0
|
local m = 0
|
||||||
for _,name in ipairs(defs) do
|
for _,name in ipairs(defs) do
|
||||||
w('{"'); w(name); w('",'); w(m) w('},\n')
|
w('{"'); w(name); w('",'); w(m) w('},\n')
|
||||||
m = m + #defs[name]
|
m = m + #defs[name].dump
|
||||||
end
|
end
|
||||||
w("{NULL,"); w(m); w("}\n};\n\n")
|
w("{NULL,"); w(m); w("}\n};\n\n")
|
||||||
return table.concat(t)
|
return table.concat(t)
|
||||||
|
|||||||
@@ -327,6 +327,12 @@ local function rename_tokens2(src)
|
|||||||
return gsub(src, "ZY([%w_]+)", "union %1")
|
return gsub(src, "ZY([%w_]+)", "union %1")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function fix_bugs_and_warnings(src)
|
||||||
|
src = gsub(src, "(luaD_checkstack%(L,p%->maxstacksize)%)", "%1+p->numparams)")
|
||||||
|
src = gsub(src, "if%(sep==%-1%)(return'%[';)\nelse (luaX_lexerror%b();)", "if (sep!=-1)%2\n%1")
|
||||||
|
return gsub(src, "(default:{\nNode%*n=mainposition)", "/*fallthrough*/\n%1")
|
||||||
|
end
|
||||||
|
|
||||||
local function func_gather(src)
|
local function func_gather(src)
|
||||||
local nodes, list = {}, {}
|
local nodes, list = {}, {}
|
||||||
local pos, len = 1, #src
|
local pos, len = 1, #src
|
||||||
@@ -425,5 +431,6 @@ src = rename_tokens1(src)
|
|||||||
src = func_collect(src)
|
src = func_collect(src)
|
||||||
src = rename_tokens2(src)
|
src = rename_tokens2(src)
|
||||||
src = restore_strings(src)
|
src = restore_strings(src)
|
||||||
|
src = fix_bugs_and_warnings(src)
|
||||||
src = merge_header(src, license)
|
src = merge_header(src, license)
|
||||||
io.write(src)
|
io.write(src)
|
||||||
|
|||||||
@@ -1639,6 +1639,7 @@ lua_number2int(k,n);
|
|||||||
if(luai_numeq(cast_num(k),nvalue(key)))
|
if(luai_numeq(cast_num(k),nvalue(key)))
|
||||||
return luaH_getnum(t,k);
|
return luaH_getnum(t,k);
|
||||||
}
|
}
|
||||||
|
/*fallthrough*/
|
||||||
default:{
|
default:{
|
||||||
Node*n=mainposition(t,key);
|
Node*n=mainposition(t,key);
|
||||||
do{
|
do{
|
||||||
@@ -2905,8 +2906,8 @@ if(sep>=0){
|
|||||||
read_long_string(ls,seminfo,sep);
|
read_long_string(ls,seminfo,sep);
|
||||||
return TK_STRING;
|
return TK_STRING;
|
||||||
}
|
}
|
||||||
else if(sep==-1)return'[';
|
else if (sep!=-1)luaX_lexerror(ls,"invalid long string delimiter",TK_STRING);
|
||||||
else luaX_lexerror(ls,"invalid long string delimiter",TK_STRING);
|
return'[';
|
||||||
}
|
}
|
||||||
case'=':{
|
case'=':{
|
||||||
next(ls);
|
next(ls);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ Save LuaJIT bytecode: luajit -b[options] input output
|
|||||||
-t type Set output file type (default: auto-detect from output name).
|
-t type Set output file type (default: auto-detect from output name).
|
||||||
-a arch Override architecture for object files (default: native).
|
-a arch Override architecture for object files (default: native).
|
||||||
-o os Override OS for object files (default: native).
|
-o os Override OS for object files (default: native).
|
||||||
|
-F name Override filename (default: input filename).
|
||||||
-e chunk Use chunk string as input.
|
-e chunk Use chunk string as input.
|
||||||
-- Stop handling options.
|
-- Stop handling options.
|
||||||
- Use stdin as input and/or stdout as output.
|
- Use stdin as input and/or stdout as output.
|
||||||
@@ -49,10 +50,22 @@ local function check(ok, ...)
|
|||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function readfile(input)
|
local function readfile(ctx, input)
|
||||||
if type(input) == "function" then return input end
|
if type(input) == "function" then return input end
|
||||||
if input == "-" then input = nil end
|
if ctx.filename then
|
||||||
return check(loadfile(input))
|
local data
|
||||||
|
if input == "-" then
|
||||||
|
data = io.stdin:read("*a")
|
||||||
|
else
|
||||||
|
local fp = assert(io.open(input, "rb"))
|
||||||
|
data = assert(fp:read("*a"))
|
||||||
|
assert(fp:close())
|
||||||
|
end
|
||||||
|
return check(load(data, ctx.filename))
|
||||||
|
else
|
||||||
|
if input == "-" then input = nil end
|
||||||
|
return check(loadfile(input))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function savefile(name, mode)
|
local function savefile(name, mode)
|
||||||
@@ -456,18 +469,18 @@ typedef struct {
|
|||||||
uint32_t value;
|
uint32_t value;
|
||||||
} mach_nlist;
|
} mach_nlist;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t strx;
|
int32_t strx;
|
||||||
uint8_t type, sect;
|
uint8_t type, sect;
|
||||||
uint16_t desc;
|
uint16_t desc;
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
} mach_nlist_64;
|
} mach_nlist_64;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t magic, nfat_arch;
|
int32_t magic, nfat_arch;
|
||||||
} mach_fat_header;
|
} mach_fat_header;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32_t cputype, cpusubtype, offset, size, align;
|
int32_t cputype, cpusubtype, offset, size, align;
|
||||||
} mach_fat_arch;
|
} mach_fat_arch;
|
||||||
typedef struct {
|
typedef struct {
|
||||||
struct {
|
struct {
|
||||||
@@ -501,6 +514,18 @@ typedef struct {
|
|||||||
mach_nlist sym_entry;
|
mach_nlist sym_entry;
|
||||||
uint8_t space[4096];
|
uint8_t space[4096];
|
||||||
} mach_fat_obj;
|
} mach_fat_obj;
|
||||||
|
typedef struct {
|
||||||
|
mach_fat_header fat;
|
||||||
|
mach_fat_arch fat_arch[2];
|
||||||
|
struct {
|
||||||
|
mach_header_64 hdr;
|
||||||
|
mach_segment_command_64 seg;
|
||||||
|
mach_section_64 sec;
|
||||||
|
mach_symtab_command sym;
|
||||||
|
} arch[2];
|
||||||
|
mach_nlist_64 sym_entry;
|
||||||
|
uint8_t space[4096];
|
||||||
|
} mach_fat_obj_64;
|
||||||
]]
|
]]
|
||||||
local symname = '_'..LJBC_PREFIX..ctx.modname
|
local symname = '_'..LJBC_PREFIX..ctx.modname
|
||||||
local isfat, is64, align, mobj = false, false, 4, "mach_obj"
|
local isfat, is64, align, mobj = false, false, 4, "mach_obj"
|
||||||
@@ -509,7 +534,7 @@ typedef struct {
|
|||||||
elseif ctx.arch == "arm" then
|
elseif ctx.arch == "arm" then
|
||||||
isfat, mobj = true, "mach_fat_obj"
|
isfat, mobj = true, "mach_fat_obj"
|
||||||
elseif ctx.arch == "arm64" then
|
elseif ctx.arch == "arm64" then
|
||||||
is64, align, isfat, mobj = true, 8, true, "mach_fat_obj"
|
is64, align, isfat, mobj = true, 8, true, "mach_fat_obj_64"
|
||||||
else
|
else
|
||||||
check(ctx.arch == "x86", "unsupported architecture for OSX")
|
check(ctx.arch == "x86", "unsupported architecture for OSX")
|
||||||
end
|
end
|
||||||
@@ -592,13 +617,13 @@ end
|
|||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function bclist(input, output)
|
local function bclist(ctx, input, output)
|
||||||
local f = readfile(input)
|
local f = readfile(ctx, input)
|
||||||
require("jit.bc").dump(f, savefile(output, "w"), true)
|
require("jit.bc").dump(f, savefile(output, "w"), true)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function bcsave(ctx, input, output)
|
local function bcsave(ctx, input, output)
|
||||||
local f = readfile(input)
|
local f = readfile(ctx, input)
|
||||||
local s = string.dump(f, ctx.strip)
|
local s = string.dump(f, ctx.strip)
|
||||||
local t = ctx.type
|
local t = ctx.type
|
||||||
if not t then
|
if not t then
|
||||||
@@ -651,6 +676,8 @@ local function docmd(...)
|
|||||||
ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture")
|
ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture")
|
||||||
elseif opt == "o" then
|
elseif opt == "o" then
|
||||||
ctx.os = checkarg(tremove(arg, n), map_os, "OS name")
|
ctx.os = checkarg(tremove(arg, n), map_os, "OS name")
|
||||||
|
elseif opt == "F" then
|
||||||
|
ctx.filename = "@"..tremove(arg, n)
|
||||||
else
|
else
|
||||||
usage()
|
usage()
|
||||||
end
|
end
|
||||||
@@ -662,7 +689,7 @@ local function docmd(...)
|
|||||||
end
|
end
|
||||||
if list then
|
if list then
|
||||||
if #arg == 0 or #arg > 2 then usage() end
|
if #arg == 0 or #arg > 2 then usage() end
|
||||||
bclist(arg[1], arg[2] or "-")
|
bclist(ctx, arg[1], arg[2] or "-")
|
||||||
else
|
else
|
||||||
if #arg ~= 2 then usage() end
|
if #arg ~= 2 then usage() end
|
||||||
bcsave(ctx, arg[1], arg[2])
|
bcsave(ctx, arg[1], arg[2])
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ LJLIB_CF(buffer_method_skip) LJLIB_REC(.)
|
|||||||
MSize len = sbufxlen(sbx);
|
MSize len = sbufxlen(sbx);
|
||||||
if (n < len) {
|
if (n < len) {
|
||||||
sbx->r += n;
|
sbx->r += n;
|
||||||
|
} else if (sbufiscow(sbx)) {
|
||||||
|
sbx->r = sbx->w;
|
||||||
} else {
|
} else {
|
||||||
sbx->r = sbx->w = sbx->b;
|
sbx->r = sbx->w = sbx->b;
|
||||||
}
|
}
|
||||||
@@ -173,7 +175,7 @@ LJLIB_CF(buffer_method_get) LJLIB_REC(.)
|
|||||||
setstrV(L, o, lj_str_new(L, sbx->r, n));
|
setstrV(L, o, lj_str_new(L, sbx->r, n));
|
||||||
sbx->r += n;
|
sbx->r += n;
|
||||||
}
|
}
|
||||||
if (sbx->r == sbx->w) sbx->r = sbx->w = sbx->b;
|
if (sbx->r == sbx->w && !sbufiscow(sbx)) sbx->r = sbx->w = sbx->b;
|
||||||
lj_gc_check(L);
|
lj_gc_check(L);
|
||||||
return narg-1;
|
return narg-1;
|
||||||
}
|
}
|
||||||
@@ -321,6 +323,7 @@ LJLIB_CF(buffer_new)
|
|||||||
setgcref(sbx->dict_str, obj2gco(dict_str));
|
setgcref(sbx->dict_str, obj2gco(dict_str));
|
||||||
setgcref(sbx->dict_mt, obj2gco(dict_mt));
|
setgcref(sbx->dict_mt, obj2gco(dict_mt));
|
||||||
if (sz > 0) lj_buf_need2((SBuf *)sbx, sz);
|
if (sz > 0) lj_buf_need2((SBuf *)sbx, sz);
|
||||||
|
lj_gc_check(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +340,7 @@ LJLIB_CF(buffer_decode) LJLIB_REC(.)
|
|||||||
GCstr *str = lj_lib_checkstrx(L, 1);
|
GCstr *str = lj_lib_checkstrx(L, 1);
|
||||||
setnilV(L->top++);
|
setnilV(L->top++);
|
||||||
lj_serialize_decode(L, L->top-1, str);
|
lj_serialize_decode(L, L->top-1, str);
|
||||||
|
lj_gc_check(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -639,7 +639,7 @@ LJLIB_CF(ffi_alignof) LJLIB_REC(ffi_xof FF_ffi_alignof)
|
|||||||
CTState *cts = ctype_cts(L);
|
CTState *cts = ctype_cts(L);
|
||||||
CTypeID id = ffi_checkctype(L, cts, NULL);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
CTSize sz = 0;
|
CTSize sz = 0;
|
||||||
CTInfo info = lj_ctype_info(cts, id, &sz);
|
CTInfo info = lj_ctype_info_raw(cts, id, &sz);
|
||||||
setintV(L->top-1, 1 << ctype_align(info));
|
setintV(L->top-1, 1 << ctype_align(info));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -770,7 +770,7 @@ LJLIB_CF(ffi_metatype)
|
|||||||
CTypeID id = ffi_checkctype(L, cts, NULL);
|
CTypeID id = ffi_checkctype(L, cts, NULL);
|
||||||
GCtab *mt = lj_lib_checktab(L, 2);
|
GCtab *mt = lj_lib_checktab(L, 2);
|
||||||
GCtab *t = cts->miscmap;
|
GCtab *t = cts->miscmap;
|
||||||
CType *ct = ctype_get(cts, id); /* Only allow raw types. */
|
CType *ct = ctype_raw(cts, id);
|
||||||
TValue *tv;
|
TValue *tv;
|
||||||
GCcdata *cd;
|
GCcdata *cd;
|
||||||
if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) ||
|
if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) ||
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ LJLIB_CF(io_popen)
|
|||||||
LJLIB_CF(io_tmpfile)
|
LJLIB_CF(io_tmpfile)
|
||||||
{
|
{
|
||||||
IOFileUD *iof = io_file_new(L);
|
IOFileUD *iof = io_file_new(L);
|
||||||
#if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PSVITA
|
#if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PS5 || LJ_TARGET_PSVITA || LJ_TARGET_NX
|
||||||
iof->fp = NULL; errno = ENOSYS;
|
iof->fp = NULL; errno = ENOSYS;
|
||||||
#else
|
#else
|
||||||
iof->fp = tmpfile();
|
iof->fp = tmpfile();
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ LJLIB_CF(os_rename)
|
|||||||
|
|
||||||
LJLIB_CF(os_tmpname)
|
LJLIB_CF(os_tmpname)
|
||||||
{
|
{
|
||||||
#if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PSVITA
|
#if LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PS5 || LJ_TARGET_PSVITA || LJ_TARGET_NX
|
||||||
lj_err_caller(L, LJ_ERR_OSUNIQF);
|
lj_err_caller(L, LJ_ERR_OSUNIQF);
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ static lua_CFunction ll_sym(lua_State *L, void *lib, const char *sym)
|
|||||||
|
|
||||||
static const char *ll_bcsym(void *lib, const char *sym)
|
static const char *ll_bcsym(void *lib, const char *sym)
|
||||||
{
|
{
|
||||||
#if defined(RTLD_DEFAULT)
|
#if defined(RTLD_DEFAULT) && !defined(NO_RTLD_DEFAULT)
|
||||||
if (lib == NULL) lib = RTLD_DEFAULT;
|
if (lib == NULL) lib = RTLD_DEFAULT;
|
||||||
#elif LJ_TARGET_OSX || LJ_TARGET_BSD
|
#elif LJ_TARGET_OSX || LJ_TARGET_BSD
|
||||||
if (lib == NULL) lib = (void *)(intptr_t)-2;
|
if (lib == NULL) lib = (void *)(intptr_t)-2;
|
||||||
|
|||||||
@@ -330,7 +330,7 @@ static void *mmap_plain(size_t size)
|
|||||||
#define CALL_MMAP(prng, size) mmap_plain(size)
|
#define CALL_MMAP(prng, size) mmap_plain(size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4
|
#if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4 && !LJ_TARGET_PS5
|
||||||
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
|
|||||||
@@ -779,7 +779,7 @@ LUA_API void lua_concat(lua_State *L, int n)
|
|||||||
L->top -= n;
|
L->top -= n;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
n -= (int)(L->top - top);
|
n -= (int)(L->top - (top - 2*LJ_FR2));
|
||||||
L->top = top+2;
|
L->top = top+2;
|
||||||
lj_vm_call(L, top, 1+1);
|
lj_vm_call(L, top, 1+1);
|
||||||
L->top -= 1+LJ_FR2;
|
L->top -= 1+LJ_FR2;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@
|
|||||||
#define LUAJIT_OS LUAJIT_OS_OSX
|
#define LUAJIT_OS LUAJIT_OS_OSX
|
||||||
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
|
||||||
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
defined(__NetBSD__) || defined(__OpenBSD__) || \
|
||||||
defined(__DragonFly__)) && !defined(__ORBIS__)
|
defined(__DragonFly__)) && !defined(__ORBIS__) && !defined(__PROSPERO__)
|
||||||
#define LUAJIT_OS LUAJIT_OS_BSD
|
#define LUAJIT_OS LUAJIT_OS_BSD
|
||||||
#elif (defined(__sun__) && defined(__svr4__))
|
#elif (defined(__sun__) && defined(__svr4__))
|
||||||
#define LJ_TARGET_SOLARIS 1
|
#define LJ_TARGET_SOLARIS 1
|
||||||
@@ -139,6 +139,13 @@
|
|||||||
#define NULL ((void*)0)
|
#define NULL ((void*)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __PROSPERO__
|
||||||
|
#define LJ_TARGET_PS5 1
|
||||||
|
#define LJ_TARGET_CONSOLE 1
|
||||||
|
#undef NULL
|
||||||
|
#define NULL ((void*)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __psp2__
|
#ifdef __psp2__
|
||||||
#define LJ_TARGET_PSVITA 1
|
#define LJ_TARGET_PSVITA 1
|
||||||
#define LJ_TARGET_CONSOLE 1
|
#define LJ_TARGET_CONSOLE 1
|
||||||
@@ -155,6 +162,13 @@
|
|||||||
#define LJ_TARGET_GC64 1
|
#define LJ_TARGET_GC64 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __NX__
|
||||||
|
#define LJ_TARGET_NX 1
|
||||||
|
#define LJ_TARGET_CONSOLE 1
|
||||||
|
#undef NULL
|
||||||
|
#define NULL ((void*)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _UWP
|
#ifdef _UWP
|
||||||
#define LJ_TARGET_UWP 1
|
#define LJ_TARGET_UWP 1
|
||||||
#if LUAJIT_TARGET == LUAJIT_ARCH_X64
|
#if LUAJIT_TARGET == LUAJIT_ARCH_X64
|
||||||
@@ -634,7 +648,7 @@ extern void *LJ_WIN_LOADLIBA(const char *path);
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LUAJIT_NO_UNWIND) || __GNU_COMPACT_EH__ || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
|
#if defined(LUAJIT_NO_UNWIND) || __GNU_COMPACT_EH__ || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4 || LJ_TARGET_PS5
|
||||||
#define LJ_NO_UNWIND 1
|
#define LJ_NO_UNWIND 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -847,7 +847,8 @@ static void ra_destpair(ASMState *as, IRIns *ir)
|
|||||||
if (destlo == RID_RETHI) {
|
if (destlo == RID_RETHI) {
|
||||||
if (desthi == RID_RETLO) {
|
if (desthi == RID_RETLO) {
|
||||||
#if LJ_TARGET_X86ORX64
|
#if LJ_TARGET_X86ORX64
|
||||||
*--as->mcp = REX_64IR(irx, XI_XCHGa + RID_RETHI);
|
*--as->mcp = XI_XCHGa + RID_RETHI;
|
||||||
|
if (LJ_64 && irt_is64(irx->t)) *--as->mcp = 0x48;
|
||||||
#else
|
#else
|
||||||
emit_movrr(as, irx, RID_RETHI, RID_TMP);
|
emit_movrr(as, irx, RID_RETHI, RID_TMP);
|
||||||
emit_movrr(as, irx, RID_RETLO, RID_RETHI);
|
emit_movrr(as, irx, RID_RETLO, RID_RETHI);
|
||||||
@@ -1670,7 +1671,6 @@ static void asm_loop(ASMState *as)
|
|||||||
#if !LJ_SOFTFP32
|
#if !LJ_SOFTFP32
|
||||||
#if !LJ_TARGET_X86ORX64
|
#if !LJ_TARGET_X86ORX64
|
||||||
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
|
#define asm_ldexp(as, ir) asm_callid(as, ir, IRCALL_ldexp)
|
||||||
#define asm_fppowi(as, ir) asm_callid(as, ir, IRCALL_lj_vm_powi)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void asm_pow(ASMState *as, IRIns *ir)
|
static void asm_pow(ASMState *as, IRIns *ir)
|
||||||
@@ -1681,10 +1681,7 @@ static void asm_pow(ASMState *as, IRIns *ir)
|
|||||||
IRCALL_lj_carith_powu64);
|
IRCALL_lj_carith_powu64);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (irt_isnum(IR(ir->op2)->t))
|
asm_callid(as, ir, IRCALL_pow);
|
||||||
asm_callid(as, ir, IRCALL_pow);
|
|
||||||
else
|
|
||||||
asm_fppowi(as, ir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_div(ASMState *as, IRIns *ir)
|
static void asm_div(ASMState *as, IRIns *ir)
|
||||||
|
|||||||
@@ -1250,7 +1250,12 @@ dotypecheck:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
asm_guardcc(as, t == IRT_NUM ? CC_HS : CC_NE);
|
asm_guardcc(as, t == IRT_NUM ? CC_HS : CC_NE);
|
||||||
emit_n(as, ARMI_CMN|ARMI_K12|-irt_toitype_(t), type);
|
if ((ir->op2 & IRSLOAD_KEYINDEX)) {
|
||||||
|
emit_n(as, ARMI_CMN|ARMI_K12|1, type);
|
||||||
|
emit_dn(as, ARMI_EOR^emit_isk12(ARMI_EOR, ~LJ_KEYINDEX), type, type);
|
||||||
|
} else {
|
||||||
|
emit_n(as, ARMI_CMN|ARMI_K12|-irt_toitype_(t), type);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ra_hasreg(dest)) {
|
if (ra_hasreg(dest)) {
|
||||||
#if !LJ_SOFTFP
|
#if !LJ_SOFTFP
|
||||||
|
|||||||
@@ -1209,7 +1209,7 @@ dotypecheck:
|
|||||||
lj_assertA(irt_isinteger(t) || irt_isnum(t),
|
lj_assertA(irt_isinteger(t) || irt_isnum(t),
|
||||||
"bad SLOAD type %d", irt_type(t));
|
"bad SLOAD type %d", irt_type(t));
|
||||||
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
emit_nm(as, A64I_CMPx | A64F_SH(A64SH_LSR, 32),
|
||||||
ra_allock(as, LJ_TISNUM << 15, allow), tmp);
|
ra_allock(as, (ir->op2 & IRSLOAD_KEYINDEX) ? LJ_KEYINDEX : (LJ_TISNUM << 15), allow), tmp);
|
||||||
} else if (irt_isnil(t)) {
|
} else if (irt_isnil(t)) {
|
||||||
emit_n(as, (A64I_CMNx^A64I_K12) | A64F_U12(1), tmp);
|
emit_n(as, (A64I_CMNx^A64I_K12) | A64F_U12(1), tmp);
|
||||||
} else if (irt_ispri(t)) {
|
} else if (irt_ispri(t)) {
|
||||||
|
|||||||
@@ -1577,7 +1577,7 @@ dotypecheck:
|
|||||||
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
|
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
|
||||||
emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM);
|
emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM);
|
||||||
} else {
|
} else {
|
||||||
Reg ktype = ra_allock(as, irt_toitype(t), allow);
|
Reg ktype = ra_allock(as, (ir->op2 & IRSLOAD_KEYINDEX) ? LJ_KEYINDEX : irt_toitype(t), allow);
|
||||||
asm_guard(as, MIPSI_BNE, type, ktype);
|
asm_guard(as, MIPSI_BNE, type, ktype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1595,6 +1595,10 @@ dotypecheck:
|
|||||||
if (irt_ispri(t)) {
|
if (irt_ispri(t)) {
|
||||||
asm_guard(as, MIPSI_BNE, type,
|
asm_guard(as, MIPSI_BNE, type,
|
||||||
ra_allock(as, ~((int64_t)~irt_toitype(t) << 47) , allow));
|
ra_allock(as, ~((int64_t)~irt_toitype(t) << 47) , allow));
|
||||||
|
} else if ((ir->op2 & IRSLOAD_KEYINDEX)) {
|
||||||
|
asm_guard(as, MIPSI_BNE, RID_TMP,
|
||||||
|
ra_allock(as, (int32_t)LJ_KEYINDEX, allow));
|
||||||
|
emit_dta(as, MIPSI_DSRA32, RID_TMP, type, 0);
|
||||||
} else {
|
} else {
|
||||||
if (irt_isnum(t)) {
|
if (irt_isnum(t)) {
|
||||||
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
|
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
|
||||||
@@ -2568,7 +2572,22 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
|
|||||||
}
|
}
|
||||||
emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4));
|
emit_tsi(as, MIPSI_SW, type, RID_BASE, ofs+(LJ_BE?0:4));
|
||||||
#else
|
#else
|
||||||
asm_tvstore64(as, RID_BASE, ofs, ref);
|
if ((sn & SNAP_KEYINDEX)) {
|
||||||
|
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
|
||||||
|
int64_t kki = (int64_t)LJ_KEYINDEX << 32;
|
||||||
|
if (irref_isk(ref)) {
|
||||||
|
emit_tsi(as, MIPSI_SD,
|
||||||
|
ra_allock(as, kki | (int64_t)(uint32_t)ir->i, allow),
|
||||||
|
RID_BASE, ofs);
|
||||||
|
} else {
|
||||||
|
Reg src = ra_alloc1(as, ref, allow);
|
||||||
|
Reg rki = ra_allock(as, kki, rset_exclude(allow, src));
|
||||||
|
emit_tsi(as, MIPSI_SD, RID_TMP, RID_BASE, ofs);
|
||||||
|
emit_dst(as, MIPSI_DADDU, RID_TMP, src, rki);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
asm_tvstore64(as, RID_BASE, ofs, ref);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
checkmclim(as);
|
checkmclim(as);
|
||||||
|
|||||||
@@ -1169,7 +1169,12 @@ dotypecheck:
|
|||||||
} else {
|
} else {
|
||||||
if ((ir->op2 & IRSLOAD_TYPECHECK)) {
|
if ((ir->op2 & IRSLOAD_TYPECHECK)) {
|
||||||
asm_guardcc(as, CC_NE);
|
asm_guardcc(as, CC_NE);
|
||||||
emit_ai(as, PPCI_CMPWI, RID_TMP, irt_toitype(t));
|
if ((ir->op2 & IRSLOAD_KEYINDEX)) {
|
||||||
|
emit_ai(as, PPCI_CMPWI, RID_TMP, (LJ_KEYINDEX & 0xffff));
|
||||||
|
emit_asi(as, PPCI_XORIS, RID_TMP, RID_TMP, (LJ_KEYINDEX >> 16));
|
||||||
|
} else {
|
||||||
|
emit_ai(as, PPCI_CMPWI, RID_TMP, irt_toitype(t));
|
||||||
|
}
|
||||||
type = RID_TMP;
|
type = RID_TMP;
|
||||||
}
|
}
|
||||||
if (ra_hasreg(dest)) emit_tai(as, PPCI_LWZ, dest, base, ofs);
|
if (ra_hasreg(dest)) emit_tai(as, PPCI_LWZ, dest, base, ofs);
|
||||||
|
|||||||
@@ -485,7 +485,8 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow)
|
|||||||
asm_fusexref(as, ir->op1, xallow);
|
asm_fusexref(as, ir->op1, xallow);
|
||||||
return RID_MRM;
|
return RID_MRM;
|
||||||
}
|
}
|
||||||
} else if (ir->o == IR_VLOAD && !(LJ_GC64 && irt_isaddr(ir->t))) {
|
} else if (ir->o == IR_VLOAD && IR(ir->op1)->o == IR_AREF &&
|
||||||
|
!(LJ_GC64 && irt_isaddr(ir->t))) {
|
||||||
asm_fuseahuref(as, ir->op1, xallow);
|
asm_fuseahuref(as, ir->op1, xallow);
|
||||||
as->mrm.ofs += 8 * ir->op2;
|
as->mrm.ofs += 8 * ir->op2;
|
||||||
return RID_MRM;
|
return RID_MRM;
|
||||||
@@ -1768,14 +1769,11 @@ static void asm_sload(ASMState *as, IRIns *ir)
|
|||||||
if ((ir->op2 & IRSLOAD_TYPECHECK)) {
|
if ((ir->op2 & IRSLOAD_TYPECHECK)) {
|
||||||
/* Need type check, even if the load result is unused. */
|
/* Need type check, even if the load result is unused. */
|
||||||
asm_guardcc(as, irt_isnum(t) ? CC_AE : CC_NE);
|
asm_guardcc(as, irt_isnum(t) ? CC_AE : CC_NE);
|
||||||
if (LJ_64 && irt_type(t) >= IRT_NUM) {
|
if ((LJ_64 && irt_type(t) >= IRT_NUM) || (ir->op2 & IRSLOAD_KEYINDEX)) {
|
||||||
lj_assertA(irt_isinteger(t) || irt_isnum(t),
|
lj_assertA(irt_isinteger(t) || irt_isnum(t),
|
||||||
"bad SLOAD type %d", irt_type(t));
|
"bad SLOAD type %d", irt_type(t));
|
||||||
#if LJ_GC64
|
emit_u32(as, (ir->op2 & IRSLOAD_KEYINDEX) ? LJ_KEYINDEX :
|
||||||
emit_u32(as, LJ_TISNUM << 15);
|
LJ_GC64 ? (LJ_TISNUM << 15) : LJ_TISNUM);
|
||||||
#else
|
|
||||||
emit_u32(as, LJ_TISNUM);
|
|
||||||
#endif
|
|
||||||
emit_rmro(as, XO_ARITHi, XOg_CMP, base, ofs+4);
|
emit_rmro(as, XO_ARITHi, XOg_CMP, base, ofs+4);
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
} else if (irt_isnil(t)) {
|
} else if (irt_isnil(t)) {
|
||||||
@@ -2017,19 +2015,6 @@ static void asm_ldexp(ASMState *as, IRIns *ir)
|
|||||||
asm_x87load(as, ir->op2);
|
asm_x87load(as, ir->op2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void asm_fppowi(ASMState *as, IRIns *ir)
|
|
||||||
{
|
|
||||||
/* The modified regs must match with the *.dasc implementation. */
|
|
||||||
RegSet drop = RSET_RANGE(RID_XMM0, RID_XMM1+1)|RID2RSET(RID_EAX);
|
|
||||||
if (ra_hasreg(ir->r))
|
|
||||||
rset_clear(drop, ir->r); /* Dest reg handled below. */
|
|
||||||
ra_evictset(as, drop);
|
|
||||||
ra_destreg(as, ir, RID_XMM0);
|
|
||||||
emit_call(as, lj_vm_powi_sse);
|
|
||||||
ra_left(as, RID_XMM0, ir->op1);
|
|
||||||
ra_left(as, RID_EAX, ir->op2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int asm_swapops(ASMState *as, IRIns *ir)
|
static int asm_swapops(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
IRIns *irl = IR(ir->op1);
|
IRIns *irl = IR(ir->op1);
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
|
|||||||
lj_err_mem(sbufL(sbx));
|
lj_err_mem(sbufL(sbx));
|
||||||
if (len + sz > sbufsz(sbx)) { /* Must grow. */
|
if (len + sz > sbufsz(sbx)) { /* Must grow. */
|
||||||
buf_grow((SBuf *)sbx, len + sz);
|
buf_grow((SBuf *)sbx, len + sz);
|
||||||
} else if (sbufxslack(sbx) < (sbufsz(sbx) >> 3)) {
|
} else if (sbufiscow(sb) || sbufxslack(sbx) < (sbufsz(sbx) >> 3)) {
|
||||||
/* Also grow to avoid excessive compactions, if slack < size/8. */
|
/* Also grow to avoid excessive compactions, if slack < size/8. */
|
||||||
buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */
|
buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */
|
||||||
return sbx->w;
|
return sbx->w;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined(RTLD_DEFAULT)
|
#if defined(RTLD_DEFAULT) && !defined(NO_RTLD_DEFAULT)
|
||||||
#define CLIB_DEFHANDLE RTLD_DEFAULT
|
#define CLIB_DEFHANDLE RTLD_DEFAULT
|
||||||
#elif LJ_TARGET_OSX || LJ_TARGET_BSD
|
#elif LJ_TARGET_OSX || LJ_TARGET_BSD
|
||||||
#define CLIB_DEFHANDLE ((void *)(intptr_t)-2)
|
#define CLIB_DEFHANDLE ((void *)(intptr_t)-2)
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
|
|||||||
} else {
|
} else {
|
||||||
cp_expr_unary(cp, k);
|
cp_expr_unary(cp, k);
|
||||||
}
|
}
|
||||||
info = lj_ctype_info(cp->cts, k->id, &sz);
|
info = lj_ctype_info_raw(cp->cts, k->id, &sz);
|
||||||
if (wantsz) {
|
if (wantsz) {
|
||||||
if (sz != CTSIZE_INVALID)
|
if (sz != CTSIZE_INVALID)
|
||||||
k->u32 = sz;
|
k->u32 = sz;
|
||||||
|
|||||||
@@ -333,6 +333,14 @@ CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp)
|
|||||||
return qual;
|
return qual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ditto, but follow a reference. */
|
||||||
|
CTInfo lj_ctype_info_raw(CTState *cts, CTypeID id, CTSize *szp)
|
||||||
|
{
|
||||||
|
CType *ct = ctype_get(cts, id);
|
||||||
|
if (ctype_isref(ct->info)) id = ctype_cid(ct->info);
|
||||||
|
return lj_ctype_info(cts, id, szp);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get ctype metamethod. */
|
/* Get ctype metamethod. */
|
||||||
cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm)
|
cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -468,6 +468,7 @@ LJ_FUNC CType *lj_ctype_rawref(CTState *cts, CTypeID id);
|
|||||||
LJ_FUNC CTSize lj_ctype_size(CTState *cts, CTypeID id);
|
LJ_FUNC CTSize lj_ctype_size(CTState *cts, CTypeID id);
|
||||||
LJ_FUNC CTSize lj_ctype_vlsize(CTState *cts, CType *ct, CTSize nelem);
|
LJ_FUNC CTSize lj_ctype_vlsize(CTState *cts, CType *ct, CTSize nelem);
|
||||||
LJ_FUNC CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp);
|
LJ_FUNC CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp);
|
||||||
|
LJ_FUNC CTInfo lj_ctype_info_raw(CTState *cts, CTypeID id, CTSize *szp);
|
||||||
LJ_FUNC cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm);
|
LJ_FUNC cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm);
|
||||||
LJ_FUNC GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name);
|
LJ_FUNC GCstr *lj_ctype_repr(lua_State *L, CTypeID id, GCstr *name);
|
||||||
LJ_FUNC GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned);
|
LJ_FUNC GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned);
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ typedef uint16_t HotCount;
|
|||||||
typedef struct GG_State {
|
typedef struct GG_State {
|
||||||
lua_State L; /* Main thread. */
|
lua_State L; /* Main thread. */
|
||||||
global_State g; /* Global state. */
|
global_State g; /* Global state. */
|
||||||
#if LJ_TARGET_ARM
|
#if LJ_TARGET_ARM && !LJ_TARGET_NX
|
||||||
/* Make g reachable via K12 encoded DISPATCH-relative addressing. */
|
/* Make g reachable via K12 encoded DISPATCH-relative addressing. */
|
||||||
uint8_t align1[(16-sizeof(global_State))&15];
|
uint8_t align1[(16-sizeof(global_State))&15];
|
||||||
#endif
|
#endif
|
||||||
@@ -99,7 +99,7 @@ typedef struct GG_State {
|
|||||||
#if LJ_HASJIT
|
#if LJ_HASJIT
|
||||||
jit_State J; /* JIT state. */
|
jit_State J; /* JIT state. */
|
||||||
HotCount hotcount[HOTCOUNT_SIZE]; /* Hot counters. */
|
HotCount hotcount[HOTCOUNT_SIZE]; /* Hot counters. */
|
||||||
#if LJ_TARGET_ARM
|
#if LJ_TARGET_ARM && !LJ_TARGET_NX
|
||||||
/* Ditto for J. */
|
/* Ditto for J. */
|
||||||
uint8_t align2[(16-sizeof(jit_State)-sizeof(HotCount)*HOTCOUNT_SIZE)&15];
|
uint8_t align2[(16-sizeof(jit_State)-sizeof(HotCount)*HOTCOUNT_SIZE)&15];
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -638,8 +638,8 @@ static void LJ_FASTCALL recff_math_call(jit_State *J, RecordFFData *rd)
|
|||||||
|
|
||||||
static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd)
|
static void LJ_FASTCALL recff_math_pow(jit_State *J, RecordFFData *rd)
|
||||||
{
|
{
|
||||||
J->base[0] = lj_opt_narrow_pow(J, J->base[0], J->base[1],
|
J->base[0] = lj_opt_narrow_arith(J, J->base[0], J->base[1],
|
||||||
&rd->argv[0], &rd->argv[1]);
|
&rd->argv[0], &rd->argv[1], IR_POW);
|
||||||
UNUSED(rd);
|
UNUSED(rd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1222,6 +1222,12 @@ static void LJ_FASTCALL recff_buffer_method_put(jit_State *J, RecordFFData *rd)
|
|||||||
TRef tr;
|
TRef tr;
|
||||||
ptrdiff_t arg;
|
ptrdiff_t arg;
|
||||||
if (!J->base[1]) return;
|
if (!J->base[1]) return;
|
||||||
|
for (arg = 1; (tr = J->base[arg]); arg++) {
|
||||||
|
if (tref_isudata(tr)) {
|
||||||
|
TRef ud2 = recff_sbufx_check(J, rd, arg);
|
||||||
|
emitir(IRTG(IR_NE, IRT_PGC), ud, ud2);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (arg = 1; (tr = J->base[arg]); arg++) {
|
for (arg = 1; (tr = J->base[arg]); arg++) {
|
||||||
if (tref_isstr(tr)) {
|
if (tref_isstr(tr)) {
|
||||||
trbuf = emitir(IRTG(IR_BUFPUT, IRT_PGC), trbuf, tr);
|
trbuf = emitir(IRTG(IR_BUFPUT, IRT_PGC), trbuf, tr);
|
||||||
@@ -1230,11 +1236,9 @@ static void LJ_FASTCALL recff_buffer_method_put(jit_State *J, RecordFFData *rd)
|
|||||||
emitir(IRT(IR_TOSTR, IRT_STR), tr,
|
emitir(IRT(IR_TOSTR, IRT_STR), tr,
|
||||||
tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT));
|
tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT));
|
||||||
} else if (tref_isudata(tr)) {
|
} else if (tref_isudata(tr)) {
|
||||||
TRef ud2 = recff_sbufx_check(J, rd, arg);
|
TRef trr = recff_sbufx_get_ptr(J, tr, IRFL_SBUF_R);
|
||||||
TRef trr = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_R);
|
TRef trw = recff_sbufx_get_ptr(J, tr, IRFL_SBUF_W);
|
||||||
TRef trw = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_W);
|
|
||||||
TRef len = recff_sbufx_len(J, trr, trw);
|
TRef len = recff_sbufx_len(J, trr, trw);
|
||||||
emitir(IRTG(IR_NE, IRT_PGC), ud, ud2);
|
|
||||||
trbuf = lj_ir_call(J, IRCALL_lj_buf_putmem, trbuf, trr, len);
|
trbuf = lj_ir_call(J, IRCALL_lj_buf_putmem, trbuf, trr, len);
|
||||||
} else {
|
} else {
|
||||||
recff_nyiu(J, rd);
|
recff_nyiu(J, rd);
|
||||||
@@ -1258,15 +1262,19 @@ static void LJ_FASTCALL recff_buffer_method_get(jit_State *J, RecordFFData *rd)
|
|||||||
TRef tr;
|
TRef tr;
|
||||||
ptrdiff_t arg;
|
ptrdiff_t arg;
|
||||||
if (!J->base[1]) { J->base[1] = TREF_NIL; J->base[2] = 0; }
|
if (!J->base[1]) { J->base[1] = TREF_NIL; J->base[2] = 0; }
|
||||||
|
for (arg = 0; (tr = J->base[arg+1]); arg++) {
|
||||||
|
if (!tref_isnil(tr)) {
|
||||||
|
J->base[arg+1] = recff_sbufx_checkint(J, rd, arg+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (arg = 0; (tr = J->base[arg+1]); arg++) {
|
for (arg = 0; (tr = J->base[arg+1]); arg++) {
|
||||||
TRef len = recff_sbufx_len(J, trr, trw);
|
TRef len = recff_sbufx_len(J, trr, trw);
|
||||||
if (tref_isnil(tr)) {
|
if (tref_isnil(tr)) {
|
||||||
J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len);
|
J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len);
|
||||||
trr = trw;
|
trr = trw;
|
||||||
} else {
|
} else {
|
||||||
TRef trn = recff_sbufx_checkint(J, rd, arg+1);
|
|
||||||
TRef tru;
|
TRef tru;
|
||||||
len = emitir(IRTI(IR_MIN), len, trn);
|
len = emitir(IRTI(IR_MIN), len, tr);
|
||||||
tru = emitir(IRT(IR_ADD, IRT_PTR), trr, len);
|
tru = emitir(IRT(IR_ADD, IRT_PTR), trr, len);
|
||||||
J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len);
|
J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len);
|
||||||
trr = tru; /* Doing the ADD before the SNEW generates better code. */
|
trr = tru; /* Doing the ADD before the SNEW generates better code. */
|
||||||
|
|||||||
@@ -700,9 +700,12 @@ static size_t gc_onestep(lua_State *L)
|
|||||||
}
|
}
|
||||||
case GCSfinalize:
|
case GCSfinalize:
|
||||||
if (gcref(g->gc.mmudata) != NULL) {
|
if (gcref(g->gc.mmudata) != NULL) {
|
||||||
|
GCSize old = g->gc.total;
|
||||||
if (tvref(g->jit_base)) /* Don't call finalizers on trace. */
|
if (tvref(g->jit_base)) /* Don't call finalizers on trace. */
|
||||||
return LJ_MAX_MEM;
|
return LJ_MAX_MEM;
|
||||||
gc_finalize(L); /* Finalize one userdata object. */
|
gc_finalize(L); /* Finalize one userdata object. */
|
||||||
|
if (old >= g->gc.total && g->gc.estimate > old - g->gc.total)
|
||||||
|
g->gc.estimate -= old - g->gc.total;
|
||||||
if (g->gc.estimate > GCFINALIZECOST)
|
if (g->gc.estimate > GCFINALIZECOST)
|
||||||
g->gc.estimate -= GCFINALIZECOST;
|
g->gc.estimate -= GCFINALIZECOST;
|
||||||
return GCFINALIZECOST;
|
return GCFINALIZECOST;
|
||||||
|
|||||||
@@ -217,7 +217,6 @@ typedef struct CCallInfo {
|
|||||||
_(FPMATH, sqrt, 1, N, NUM, XA_FP) \
|
_(FPMATH, sqrt, 1, N, NUM, XA_FP) \
|
||||||
_(ANY, log, 1, N, NUM, XA_FP) \
|
_(ANY, log, 1, N, NUM, XA_FP) \
|
||||||
_(ANY, lj_vm_log2, 1, N, NUM, XA_FP) \
|
_(ANY, lj_vm_log2, 1, N, NUM, XA_FP) \
|
||||||
_(ANY, lj_vm_powi, 2, N, NUM, XA_FP) \
|
|
||||||
_(ANY, pow, 2, N, NUM, XA2_FP) \
|
_(ANY, pow, 2, N, NUM, XA2_FP) \
|
||||||
_(ANY, atan2, 2, N, NUM, XA2_FP) \
|
_(ANY, atan2, 2, N, NUM, XA2_FP) \
|
||||||
_(ANY, ldexp, 2, N, NUM, XA_FP) \
|
_(ANY, ldexp, 2, N, NUM, XA_FP) \
|
||||||
|
|||||||
@@ -145,7 +145,6 @@ LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
|
|||||||
TValue *vb, TValue *vc, IROp op);
|
TValue *vb, TValue *vc, IROp op);
|
||||||
LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc);
|
LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc);
|
||||||
LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc);
|
LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc);
|
||||||
LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc);
|
|
||||||
LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
|
LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
|
||||||
|
|
||||||
/* Optimization passes. */
|
/* Optimization passes. */
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#define _LJ_JIT_H
|
#define _LJ_JIT_H
|
||||||
|
|
||||||
#include "lj_obj.h"
|
#include "lj_obj.h"
|
||||||
|
#if LJ_HASJIT
|
||||||
#include "lj_ir.h"
|
#include "lj_ir.h"
|
||||||
|
|
||||||
/* -- JIT engine flags ---------------------------------------------------- */
|
/* -- JIT engine flags ---------------------------------------------------- */
|
||||||
@@ -371,6 +372,7 @@ enum {
|
|||||||
#endif
|
#endif
|
||||||
LJ_K64__MAX,
|
LJ_K64__MAX,
|
||||||
};
|
};
|
||||||
|
#define LJ_K64__USED (LJ_TARGET_X86ORX64 || LJ_TARGET_MIPS)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
#if LJ_TARGET_X86ORX64
|
#if LJ_TARGET_X86ORX64
|
||||||
@@ -389,6 +391,7 @@ enum {
|
|||||||
#endif
|
#endif
|
||||||
LJ_K32__MAX
|
LJ_K32__MAX
|
||||||
};
|
};
|
||||||
|
#define LJ_K32__USED (LJ_TARGET_X86ORX64 || LJ_TARGET_PPC || LJ_TARGET_MIPS)
|
||||||
|
|
||||||
/* Get 16 byte aligned pointer to SIMD constant. */
|
/* Get 16 byte aligned pointer to SIMD constant. */
|
||||||
#define LJ_KSIMD(J, n) \
|
#define LJ_KSIMD(J, n) \
|
||||||
@@ -443,9 +446,13 @@ typedef struct jit_State {
|
|||||||
int32_t framedepth; /* Current frame depth. */
|
int32_t framedepth; /* Current frame depth. */
|
||||||
int32_t retdepth; /* Return frame depth (count of RETF). */
|
int32_t retdepth; /* Return frame depth (count of RETF). */
|
||||||
|
|
||||||
|
#if LJ_K32__USED
|
||||||
uint32_t k32[LJ_K32__MAX]; /* Common 4 byte constants used by backends. */
|
uint32_t k32[LJ_K32__MAX]; /* Common 4 byte constants used by backends. */
|
||||||
|
#endif
|
||||||
TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */
|
TValue ksimd[LJ_KSIMD__MAX*2+1]; /* 16 byte aligned SIMD constants. */
|
||||||
|
#if LJ_K64__USED
|
||||||
TValue k64[LJ_K64__MAX]; /* Common 8 byte constants. */
|
TValue k64[LJ_K64__MAX]; /* Common 8 byte constants. */
|
||||||
|
#endif
|
||||||
|
|
||||||
IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */
|
IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */
|
||||||
IRRef irtoplim; /* Upper limit of instuction buffer (biased). */
|
IRRef irtoplim; /* Upper limit of instuction buffer (biased). */
|
||||||
@@ -516,5 +523,6 @@ typedef struct jit_State {
|
|||||||
#else
|
#else
|
||||||
#define lj_assertJ(c, ...) ((void)J)
|
#define lj_assertJ(c, ...) ((void)J)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ static void mcode_protect(jit_State *J, int prot)
|
|||||||
#define MCPROT_RUN MCPROT_RX
|
#define MCPROT_RUN MCPROT_RX
|
||||||
|
|
||||||
/* Protection twiddling failed. Probably due to kernel security. */
|
/* Protection twiddling failed. Probably due to kernel security. */
|
||||||
static LJ_NOINLINE void mcode_protfail(jit_State *J)
|
static LJ_NORET LJ_NOINLINE void mcode_protfail(jit_State *J)
|
||||||
{
|
{
|
||||||
lua_CFunction panic = J2G(J)->panic;
|
lua_CFunction panic = J2G(J)->panic;
|
||||||
if (panic) {
|
if (panic) {
|
||||||
@@ -176,6 +176,7 @@ static LJ_NOINLINE void mcode_protfail(jit_State *J)
|
|||||||
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITPROT));
|
setstrV(L, L->top++, lj_err_str(L, LJ_ERR_JITPROT));
|
||||||
panic(L);
|
panic(L);
|
||||||
}
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change protection of MCode area. */
|
/* Change protection of MCode area. */
|
||||||
|
|||||||
@@ -511,7 +511,7 @@ typedef struct GCtab {
|
|||||||
} GCtab;
|
} GCtab;
|
||||||
|
|
||||||
#define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab))
|
#define sizetabcolo(n) ((n)*sizeof(TValue) + sizeof(GCtab))
|
||||||
#define tabref(r) (&gcref((r))->tab)
|
#define tabref(r) ((GCtab *)gcref((r)))
|
||||||
#define noderef(r) (mref((r), Node))
|
#define noderef(r) (mref((r), Node))
|
||||||
#define nextnode(n) (mref((n)->next, Node))
|
#define nextnode(n) (mref((n)->next, Node))
|
||||||
#if LJ_GC64
|
#if LJ_GC64
|
||||||
@@ -845,6 +845,7 @@ static LJ_AINLINE void *lightudV(global_State *g, cTValue *o)
|
|||||||
uint64_t seg = lightudseg(u);
|
uint64_t seg = lightudseg(u);
|
||||||
uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
|
uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
|
||||||
lj_assertG(tvislightud(o), "lightuserdata expected");
|
lj_assertG(tvislightud(o), "lightuserdata expected");
|
||||||
|
if (seg == (1 << LJ_LIGHTUD_BITS_SEG)-1) return NULL;
|
||||||
lj_assertG(seg <= g->gc.lightudnum, "bad lightuserdata segment %d", seg);
|
lj_assertG(seg <= g->gc.lightudnum, "bad lightuserdata segment %d", seg);
|
||||||
return (void *)(((uint64_t)segmap[seg] << 32) | lightudlo(u));
|
return (void *)(((uint64_t)segmap[seg] << 32) | lightudlo(u));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -236,14 +236,10 @@ LJFOLDF(kfold_fpcall2)
|
|||||||
return NEXTFOLD;
|
return NEXTFOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
LJFOLD(POW KNUM KINT)
|
|
||||||
LJFOLD(POW KNUM KNUM)
|
LJFOLD(POW KNUM KNUM)
|
||||||
LJFOLDF(kfold_numpow)
|
LJFOLDF(kfold_numpow)
|
||||||
{
|
{
|
||||||
lua_Number a = knumleft;
|
return lj_ir_knum(J, lj_vm_foldarith(knumleft, knumright, IR_POW - IR_ADD));
|
||||||
lua_Number b = fright->o == IR_KINT ? (lua_Number)fright->i : knumright;
|
|
||||||
lua_Number y = lj_vm_foldarith(a, b, IR_POW - IR_ADD);
|
|
||||||
return lj_ir_knum(J, y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must not use kfold_kref for numbers (could be NaN). */
|
/* Must not use kfold_kref for numbers (could be NaN). */
|
||||||
@@ -598,14 +594,15 @@ LJFOLDF(bufput_bufstr)
|
|||||||
if (fleft->o == IR_BUFHDR && fleft->op2 == IRBUFHDR_RESET &&
|
if (fleft->o == IR_BUFHDR && fleft->op2 == IRBUFHDR_RESET &&
|
||||||
fleft->prev == hdr &&
|
fleft->prev == hdr &&
|
||||||
fleft->op1 == IR(hdr)->op1 &&
|
fleft->op1 == IR(hdr)->op1 &&
|
||||||
!(irt_isphi(fright->t) && IR(hdr)->prev)) {
|
!(irt_isphi(fright->t) && IR(hdr)->prev) &&
|
||||||
|
(!LJ_HASBUFFER || J->chain[IR_CALLA] < hdr)) {
|
||||||
IRRef ref = fins->op1;
|
IRRef ref = fins->op1;
|
||||||
IR(ref)->op2 = IRBUFHDR_APPEND; /* Modify BUFHDR. */
|
IR(ref)->op2 = IRBUFHDR_APPEND; /* Modify BUFHDR. */
|
||||||
IR(ref)->op1 = fright->op1;
|
IR(ref)->op1 = fright->op1;
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
/* Replay puts to global temporary buffer. */
|
/* Replay puts to global temporary buffer. */
|
||||||
if (IR(hdr)->op2 == IRBUFHDR_RESET) {
|
if (IR(hdr)->op2 == IRBUFHDR_RESET && !irt_isphi(fright->t)) {
|
||||||
IRIns *ir = IR(fright->op1);
|
IRIns *ir = IR(fright->op1);
|
||||||
/* For now only handle single string.reverse .lower .upper .rep. */
|
/* For now only handle single string.reverse .lower .upper .rep. */
|
||||||
if (ir->o == IR_CALLL &&
|
if (ir->o == IR_CALLL &&
|
||||||
@@ -1112,61 +1109,17 @@ LJFOLDF(simplify_nummuldiv_negneg)
|
|||||||
return RETRYFOLD;
|
return RETRYFOLD;
|
||||||
}
|
}
|
||||||
|
|
||||||
LJFOLD(POW any KINT)
|
|
||||||
LJFOLDF(simplify_numpow_xkint)
|
|
||||||
{
|
|
||||||
int32_t k = fright->i;
|
|
||||||
TRef ref = fins->op1;
|
|
||||||
if (k == 0) /* x ^ 0 ==> 1 */
|
|
||||||
return lj_ir_knum_one(J); /* Result must be a number, not an int. */
|
|
||||||
if (k == 1) /* x ^ 1 ==> x */
|
|
||||||
return LEFTFOLD;
|
|
||||||
if ((uint32_t)(k+65536) > 2*65536u) /* Limit code explosion. */
|
|
||||||
return NEXTFOLD;
|
|
||||||
if (k < 0) { /* x ^ (-k) ==> (1/x) ^ k. */
|
|
||||||
ref = emitir(IRTN(IR_DIV), lj_ir_knum_one(J), ref);
|
|
||||||
k = -k;
|
|
||||||
}
|
|
||||||
/* Unroll x^k for 1 <= k <= 65536. */
|
|
||||||
for (; (k & 1) == 0; k >>= 1) /* Handle leading zeros. */
|
|
||||||
ref = emitir(IRTN(IR_MUL), ref, ref);
|
|
||||||
if ((k >>= 1) != 0) { /* Handle trailing bits. */
|
|
||||||
TRef tmp = emitir(IRTN(IR_MUL), ref, ref);
|
|
||||||
for (; k != 1; k >>= 1) {
|
|
||||||
if (k & 1)
|
|
||||||
ref = emitir(IRTN(IR_MUL), ref, tmp);
|
|
||||||
tmp = emitir(IRTN(IR_MUL), tmp, tmp);
|
|
||||||
}
|
|
||||||
ref = emitir(IRTN(IR_MUL), ref, tmp);
|
|
||||||
}
|
|
||||||
return ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
LJFOLD(POW any KNUM)
|
LJFOLD(POW any KNUM)
|
||||||
LJFOLDF(simplify_numpow_xknum)
|
LJFOLDF(simplify_numpow_k)
|
||||||
{
|
{
|
||||||
if (knumright == 0.5) /* x ^ 0.5 ==> sqrt(x) */
|
if (knumright == 0.0) /* x ^ 0 ==> 1 */
|
||||||
return emitir(IRTN(IR_FPMATH), fins->op1, IRFPM_SQRT);
|
return lj_ir_knum_one(J); /* Result must be a number, not an int. */
|
||||||
return NEXTFOLD;
|
else if (knumright == 1.0) /* x ^ 1 ==> x */
|
||||||
}
|
return LEFTFOLD;
|
||||||
|
else if (knumright == 2.0) /* x ^ 2 ==> x * x */
|
||||||
LJFOLD(POW KNUM any)
|
return emitir(IRTN(IR_MUL), fins->op1, fins->op1);
|
||||||
LJFOLDF(simplify_numpow_kx)
|
else
|
||||||
{
|
return NEXTFOLD;
|
||||||
lua_Number n = knumleft;
|
|
||||||
if (n == 2.0 && irt_isint(fright->t)) { /* 2.0 ^ i ==> ldexp(1.0, i) */
|
|
||||||
#if LJ_TARGET_X86ORX64
|
|
||||||
/* Different IR_LDEXP calling convention on x86/x64 requires conversion. */
|
|
||||||
fins->o = IR_CONV;
|
|
||||||
fins->op1 = fins->op2;
|
|
||||||
fins->op2 = IRCONV_NUM_INT;
|
|
||||||
fins->op2 = (IRRef1)lj_opt_fold(J);
|
|
||||||
#endif
|
|
||||||
fins->op1 = (IRRef1)lj_ir_knum_one(J);
|
|
||||||
fins->o = IR_LDEXP;
|
|
||||||
return RETRYFOLD;
|
|
||||||
}
|
|
||||||
return NEXTFOLD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- Simplify conversions ------------------------------------------------ */
|
/* -- Simplify conversions ------------------------------------------------ */
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ TRef LJ_FASTCALL lj_opt_fwd_alen(jit_State *J)
|
|||||||
fins->op2 = aref->op2; /* Set ALEN hint. */
|
fins->op2 = aref->op2; /* Set ALEN hint. */
|
||||||
}
|
}
|
||||||
goto doemit; /* Conflicting store, possibly giving a hint. */
|
goto doemit; /* Conflicting store, possibly giving a hint. */
|
||||||
} else if (aa_table(J, tab, fref->op1) == ALIAS_NO) {
|
} else if (aa_table(J, tab, fref->op1) != ALIAS_NO) {
|
||||||
goto doemit; /* Conflicting store. */
|
goto doemit; /* Conflicting store. */
|
||||||
}
|
}
|
||||||
sref = store->prev;
|
sref = store->prev;
|
||||||
|
|||||||
@@ -584,36 +584,6 @@ TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc)
|
|||||||
return emitir(IRTN(IR_SUB), rb, tmp);
|
return emitir(IRTN(IR_SUB), rb, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Narrowing of power operator or math.pow. */
|
|
||||||
TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vb, TValue *vc)
|
|
||||||
{
|
|
||||||
rb = conv_str_tonum(J, rb, vb);
|
|
||||||
rb = lj_ir_tonum(J, rb); /* Left arg is always treated as an FP number. */
|
|
||||||
rc = conv_str_tonum(J, rc, vc);
|
|
||||||
/* Narrowing must be unconditional to preserve (-x)^i semantics. */
|
|
||||||
if (tvisint(vc) || numisint(numV(vc))) {
|
|
||||||
int checkrange = 0;
|
|
||||||
/* pow() is faster for bigger exponents. But do this only for (+k)^i. */
|
|
||||||
if (tref_isk(rb) && (int32_t)ir_knum(IR(tref_ref(rb)))->u32.hi >= 0) {
|
|
||||||
int32_t k = numberVint(vc);
|
|
||||||
if (!(k >= -65536 && k <= 65536)) goto force_pow_num;
|
|
||||||
checkrange = 1;
|
|
||||||
}
|
|
||||||
if (!tref_isinteger(rc)) {
|
|
||||||
/* Guarded conversion to integer! */
|
|
||||||
rc = emitir(IRTGI(IR_CONV), rc, IRCONV_INT_NUM|IRCONV_CHECK);
|
|
||||||
}
|
|
||||||
if (checkrange && !tref_isk(rc)) { /* Range guard: -65536 <= i <= 65536 */
|
|
||||||
TRef tmp = emitir(IRTI(IR_ADD), rc, lj_ir_kint(J, 65536));
|
|
||||||
emitir(IRTGI(IR_ULE), tmp, lj_ir_kint(J, 2*65536));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
force_pow_num:
|
|
||||||
rc = lj_ir_tonum(J, rc); /* Want POW(num, num), not POW(num, int). */
|
|
||||||
}
|
|
||||||
return emitir(IRTN(IR_POW), rb, rc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- Predictive narrowing of induction variables ------------------------- */
|
/* -- Predictive narrowing of induction variables ------------------------- */
|
||||||
|
|
||||||
/* Narrow a single runtime value. */
|
/* Narrow a single runtime value. */
|
||||||
|
|||||||
@@ -400,7 +400,7 @@ static void split_ir(jit_State *J)
|
|||||||
hi = split_call_ll(J, hisubst, oir, ir, IRCALL_softfp_div);
|
hi = split_call_ll(J, hisubst, oir, ir, IRCALL_softfp_div);
|
||||||
break;
|
break;
|
||||||
case IR_POW:
|
case IR_POW:
|
||||||
hi = split_call_li(J, hisubst, oir, ir, IRCALL_lj_vm_powi);
|
hi = split_call_ll(J, hisubst, oir, ir, IRCALL_pow);
|
||||||
break;
|
break;
|
||||||
case IR_FPMATH:
|
case IR_FPMATH:
|
||||||
hi = split_call_l(J, hisubst, oir, ir, IRCALL_lj_vm_floor + ir->op2);
|
hi = split_call_l(J, hisubst, oir, ir, IRCALL_lj_vm_floor + ir->op2);
|
||||||
|
|||||||
@@ -1554,7 +1554,7 @@ static void fs_fixup_ret(FuncState *fs)
|
|||||||
/* Replace with UCLO plus branch. */
|
/* Replace with UCLO plus branch. */
|
||||||
fs->bcbase[pc].ins = BCINS_AD(BC_UCLO, 0, offset);
|
fs->bcbase[pc].ins = BCINS_AD(BC_UCLO, 0, offset);
|
||||||
break;
|
break;
|
||||||
case BC_UCLO:
|
case BC_FNEW:
|
||||||
return; /* We're done. */
|
return; /* We're done. */
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -83,10 +83,14 @@ extern int XNetRandom(void *buf, unsigned int len);
|
|||||||
|
|
||||||
extern int sys_get_random_number(void *buf, uint64_t len);
|
extern int sys_get_random_number(void *buf, uint64_t len);
|
||||||
|
|
||||||
#elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA
|
#elif LJ_TARGET_PS4 || LJ_TARGET_PS5 || LJ_TARGET_PSVITA
|
||||||
|
|
||||||
extern int sceRandomGetRandomNumber(void *buf, size_t len);
|
extern int sceRandomGetRandomNumber(void *buf, size_t len);
|
||||||
|
|
||||||
|
#elif LJ_TARGET_NX
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOXONE
|
#elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOXONE
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
@@ -126,7 +130,7 @@ static PRGR libfunc_rgr;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LJ_TARGET_HAS_GETENTROPY
|
#if LJ_TARGET_HAS_GETENTROPY
|
||||||
extern int getentropy(void *buf, size_t len);
|
extern int getentropy(void *buf, size_t len)
|
||||||
#ifdef __ELF__
|
#ifdef __ELF__
|
||||||
__attribute__((weak))
|
__attribute__((weak))
|
||||||
#endif
|
#endif
|
||||||
@@ -171,11 +175,16 @@ int LJ_FASTCALL lj_prng_seed_secure(PRNGState *rs)
|
|||||||
if (sys_get_random_number(rs->u, sizeof(rs->u)) == 0)
|
if (sys_get_random_number(rs->u, sizeof(rs->u)) == 0)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
||||||
#elif LJ_TARGET_PS4 || LJ_TARGET_PSVITA
|
#elif LJ_TARGET_PS4 || LJ_TARGET_PS5 || LJ_TARGET_PSVITA
|
||||||
|
|
||||||
if (sceRandomGetRandomNumber(rs->u, sizeof(rs->u)) == 0)
|
if (sceRandomGetRandomNumber(rs->u, sizeof(rs->u)) == 0)
|
||||||
goto ok;
|
goto ok;
|
||||||
|
|
||||||
|
#elif LJ_TARGET_NX
|
||||||
|
|
||||||
|
if (getentropy(rs->u, sizeof(rs->u)) == 0)
|
||||||
|
goto ok;
|
||||||
|
|
||||||
#elif LJ_TARGET_UWP || LJ_TARGET_XBOXONE
|
#elif LJ_TARGET_UWP || LJ_TARGET_XBOXONE
|
||||||
|
|
||||||
if (BCryptGenRandom(NULL, (PUCHAR)(rs->u), (ULONG)sizeof(rs->u),
|
if (BCryptGenRandom(NULL, (PUCHAR)(rs->u), (ULONG)sizeof(rs->u),
|
||||||
|
|||||||
+22
-12
@@ -664,17 +664,24 @@ static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb)
|
|||||||
RecordIndex ix;
|
RecordIndex ix;
|
||||||
/* Since ITERN is recorded at the start, we need our own loop detection. */
|
/* Since ITERN is recorded at the start, we need our own loop detection. */
|
||||||
if (J->pc == J->startpc &&
|
if (J->pc == J->startpc &&
|
||||||
(J->cur.nins > REF_FIRST+1 ||
|
|
||||||
(J->cur.nins == REF_FIRST+1 && J->cur.ir[REF_FIRST].o != IR_PROF)) &&
|
|
||||||
J->framedepth + J->retdepth == 0 && J->parent == 0 && J->exitno == 0) {
|
J->framedepth + J->retdepth == 0 && J->parent == 0 && J->exitno == 0) {
|
||||||
lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */
|
IRRef ref = REF_FIRST + LJ_HASPROFILE;
|
||||||
return LOOPEV_ENTER;
|
#ifdef LUAJIT_ENABLE_CHECKHOOK
|
||||||
|
ref += 3;
|
||||||
|
#endif
|
||||||
|
if (J->cur.nins > ref ||
|
||||||
|
(LJ_HASPROFILE && J->cur.nins == ref && J->cur.ir[ref-1].o != IR_PROF)) {
|
||||||
|
J->instunroll = 0; /* Cannot continue unrolling across an ITERN. */
|
||||||
|
lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */
|
||||||
|
return LOOPEV_ENTER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
J->maxslot = ra;
|
J->maxslot = ra;
|
||||||
lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */
|
lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */
|
||||||
ix.tab = getslot(J, ra-2);
|
ix.tab = getslot(J, ra-2);
|
||||||
ix.key = J->base[ra-1] ? J->base[ra-1] :
|
ix.key = J->base[ra-1] ? J->base[ra-1] :
|
||||||
sloadt(J, (int32_t)(ra-1), IRT_INT, IRSLOAD_KEYINDEX);
|
sloadt(J, (int32_t)(ra-1), IRT_GUARD|IRT_INT,
|
||||||
|
IRSLOAD_TYPECHECK|IRSLOAD_KEYINDEX);
|
||||||
copyTV(J->L, &ix.tabv, &J->L->base[ra-2]);
|
copyTV(J->L, &ix.tabv, &J->L->base[ra-2]);
|
||||||
copyTV(J->L, &ix.keyv, &J->L->base[ra-1]);
|
copyTV(J->L, &ix.keyv, &J->L->base[ra-1]);
|
||||||
ix.idxchain = (rb < 3); /* Omit value type check, if unused. */
|
ix.idxchain = (rb < 3); /* Omit value type check, if unused. */
|
||||||
@@ -1446,16 +1453,16 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix, IRRef *rbref,
|
|||||||
key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT);
|
key = emitir(IRTN(IR_CONV), key, IRCONV_NUM_INT);
|
||||||
if (tref_isk(key)) {
|
if (tref_isk(key)) {
|
||||||
/* Optimize lookup of constant hash keys. */
|
/* Optimize lookup of constant hash keys. */
|
||||||
MSize hslot = (MSize)((char *)ix->oldv - (char *)&noderef(t->node)[0].val);
|
GCSize hslot = (GCSize)((char *)ix->oldv-(char *)&noderef(t->node)[0].val);
|
||||||
if (t->hmask > 0 && hslot <= t->hmask*(MSize)sizeof(Node) &&
|
if (hslot <= t->hmask*(GCSize)sizeof(Node) &&
|
||||||
hslot <= 65535*(MSize)sizeof(Node)) {
|
hslot <= 65535*(GCSize)sizeof(Node)) {
|
||||||
TRef node, kslot, hm;
|
TRef node, kslot, hm;
|
||||||
*rbref = J->cur.nins; /* Mark possible rollback point. */
|
*rbref = J->cur.nins; /* Mark possible rollback point. */
|
||||||
*rbguard = J->guardemit;
|
*rbguard = J->guardemit;
|
||||||
hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK);
|
hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_HMASK);
|
||||||
emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask));
|
emitir(IRTGI(IR_EQ), hm, lj_ir_kint(J, (int32_t)t->hmask));
|
||||||
node = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_NODE);
|
node = emitir(IRT(IR_FLOAD, IRT_PGC), ix->tab, IRFL_TAB_NODE);
|
||||||
kslot = lj_ir_kslot(J, key, hslot / sizeof(Node));
|
kslot = lj_ir_kslot(J, key, (IRRef)(hslot / sizeof(Node)));
|
||||||
return emitir(IRTG(IR_HREFK, IRT_PGC), node, kslot);
|
return emitir(IRTG(IR_HREFK, IRT_PGC), node, kslot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1954,7 +1961,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
|
|||||||
emitir(IRTGI(IR_EQ), fr,
|
emitir(IRTGI(IR_EQ), fr,
|
||||||
lj_ir_kint(J, (int32_t)frame_ftsz(J->L->base-1)));
|
lj_ir_kint(J, (int32_t)frame_ftsz(J->L->base-1)));
|
||||||
vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
|
vbase = emitir(IRT(IR_SUB, IRT_IGC), REF_BASE, fr);
|
||||||
vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8));
|
vbase = emitir(IRT(IR_ADD, IRT_PGC), vbase, lj_ir_kint(J, frofs-8*(1+LJ_FR2)));
|
||||||
for (i = 0; i < nload; i++) {
|
for (i = 0; i < nload; i++) {
|
||||||
IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]);
|
IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]);
|
||||||
J->base[dst+i] = lj_record_vload(J, vbase, i, t);
|
J->base[dst+i] = lj_record_vload(J, vbase, i, t);
|
||||||
@@ -2041,7 +2048,7 @@ static TRef rec_tnew(jit_State *J, uint32_t ah)
|
|||||||
static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
|
static TRef rec_cat(jit_State *J, BCReg baseslot, BCReg topslot)
|
||||||
{
|
{
|
||||||
TRef *top = &J->base[topslot];
|
TRef *top = &J->base[topslot];
|
||||||
TValue savetv[5];
|
TValue savetv[5+LJ_FR2];
|
||||||
BCReg s;
|
BCReg s;
|
||||||
RecordIndex ix;
|
RecordIndex ix;
|
||||||
lj_assertJ(baseslot < topslot, "bad CAT arg");
|
lj_assertJ(baseslot < topslot, "bad CAT arg");
|
||||||
@@ -2231,6 +2238,7 @@ void lj_record_ins(jit_State *J)
|
|||||||
case BCMpri: setpriV(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break;
|
case BCMpri: setpriV(rcv, ~rc); ix.key = rc = TREF_PRI(IRT_NIL+rc); break;
|
||||||
case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc);
|
case BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc);
|
||||||
copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) :
|
copyTV(J->L, rcv, tv); ix.key = rc = tvisint(tv) ? lj_ir_kint(J, intV(tv)) :
|
||||||
|
tv->u32.hi == LJ_KEYINDEX ? (lj_ir_kint(J, 0) | TREF_KEYINDEX) :
|
||||||
lj_ir_knumint(J, numV(tv)); } break;
|
lj_ir_knumint(J, numV(tv)); } break;
|
||||||
case BCMstr: { GCstr *s = gco2str(proto_kgc(J->pt, ~(ptrdiff_t)rc));
|
case BCMstr: { GCstr *s = gco2str(proto_kgc(J->pt, ~(ptrdiff_t)rc));
|
||||||
setstrV(J->L, rcv, s); ix.key = rc = lj_ir_kstr(J, s); } break;
|
setstrV(J->L, rcv, s); ix.key = rc = lj_ir_kstr(J, s); } break;
|
||||||
@@ -2393,7 +2401,7 @@ void lj_record_ins(jit_State *J)
|
|||||||
|
|
||||||
case BC_POW:
|
case BC_POW:
|
||||||
if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
|
if (tref_isnumber_str(rb) && tref_isnumber_str(rc))
|
||||||
rc = lj_opt_narrow_pow(J, rb, rc, rbv, rcv);
|
rc = lj_opt_narrow_arith(J, rb, rc, rbv, rcv, IR_POW);
|
||||||
else
|
else
|
||||||
rc = rec_mm_arith(J, &ix, MM_pow);
|
rc = rec_mm_arith(J, &ix, MM_pow);
|
||||||
break;
|
break;
|
||||||
@@ -2657,6 +2665,8 @@ static const BCIns *rec_setup_root(jit_State *J)
|
|||||||
J->bc_min = pc;
|
J->bc_min = pc;
|
||||||
break;
|
break;
|
||||||
case BC_ITERL:
|
case BC_ITERL:
|
||||||
|
if (bc_op(pc[-1]) == BC_JLOOP)
|
||||||
|
lj_trace_err(J, LJ_TRERR_LINNER);
|
||||||
lj_assertJ(bc_op(pc[-1]) == BC_ITERC, "no ITERC before ITERL");
|
lj_assertJ(bc_op(pc[-1]) == BC_ITERC, "no ITERC before ITERL");
|
||||||
J->maxslot = ra + bc_b(pc[-1]) - 1;
|
J->maxslot = ra + bc_b(pc[-1]) - 1;
|
||||||
J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns);
|
J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns);
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Mark slots used by upvalues of child prototypes as used. */
|
/* Mark slots used by upvalues of child prototypes as used. */
|
||||||
void snap_useuv(GCproto *pt, uint8_t *udf)
|
static void snap_useuv(GCproto *pt, uint8_t *udf)
|
||||||
{
|
{
|
||||||
/* This is a coarse check, because it's difficult to correlate the lifetime
|
/* This is a coarse check, because it's difficult to correlate the lifetime
|
||||||
** of slots and closures. But the number of false positives is quite low.
|
** of slots and closures. But the number of false positives is quite low.
|
||||||
|
|||||||
@@ -672,9 +672,11 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
|
|||||||
trace_pendpatch(J, 0);
|
trace_pendpatch(J, 0);
|
||||||
setvmstate(J2G(J), RECORD);
|
setvmstate(J2G(J), RECORD);
|
||||||
lj_vmevent_send_(L, RECORD,
|
lj_vmevent_send_(L, RECORD,
|
||||||
/* Save/restore tmptv state for trace recorder. */
|
/* Save/restore state for trace recorder. */
|
||||||
TValue savetv = J2G(J)->tmptv;
|
TValue savetv = J2G(J)->tmptv;
|
||||||
TValue savetv2 = J2G(J)->tmptv2;
|
TValue savetv2 = J2G(J)->tmptv2;
|
||||||
|
TraceNo parent = J->parent;
|
||||||
|
ExitNo exitno = J->exitno;
|
||||||
setintV(L->top++, J->cur.traceno);
|
setintV(L->top++, J->cur.traceno);
|
||||||
setfuncV(L, L->top++, J->fn);
|
setfuncV(L, L->top++, J->fn);
|
||||||
setintV(L->top++, J->pt ? (int32_t)proto_bcpos(J->pt, J->pc) : -1);
|
setintV(L->top++, J->pt ? (int32_t)proto_bcpos(J->pt, J->pc) : -1);
|
||||||
@@ -682,6 +684,8 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
|
|||||||
,
|
,
|
||||||
J2G(J)->tmptv = savetv;
|
J2G(J)->tmptv = savetv;
|
||||||
J2G(J)->tmptv2 = savetv2;
|
J2G(J)->tmptv2 = savetv2;
|
||||||
|
J->parent = parent;
|
||||||
|
J->exitno = exitno;
|
||||||
);
|
);
|
||||||
lj_record_ins(J);
|
lj_record_ins(J);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -83,10 +83,6 @@ LJ_ASMF int32_t LJ_FASTCALL lj_vm_modi(int32_t, int32_t);
|
|||||||
LJ_ASMF void lj_vm_floor_sse(void);
|
LJ_ASMF void lj_vm_floor_sse(void);
|
||||||
LJ_ASMF void lj_vm_ceil_sse(void);
|
LJ_ASMF void lj_vm_ceil_sse(void);
|
||||||
LJ_ASMF void lj_vm_trunc_sse(void);
|
LJ_ASMF void lj_vm_trunc_sse(void);
|
||||||
LJ_ASMF void lj_vm_powi_sse(void);
|
|
||||||
#define lj_vm_powi NULL
|
|
||||||
#else
|
|
||||||
LJ_ASMF double lj_vm_powi(double, int32_t);
|
|
||||||
#endif
|
#endif
|
||||||
#if LJ_TARGET_PPC || LJ_TARGET_ARM64
|
#if LJ_TARGET_PPC || LJ_TARGET_ARM64
|
||||||
#define lj_vm_trunc trunc
|
#define lj_vm_trunc trunc
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ LJ_FUNCA double lj_wrap_pow(double x, double y) { return pow(x, y); }
|
|||||||
LJ_FUNCA double lj_wrap_fmod(double x, double y) { return fmod(x, y); }
|
LJ_FUNCA double lj_wrap_fmod(double x, double y) { return fmod(x, y); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -- Helper functions for generated machine code ------------------------- */
|
/* -- Helper functions ---------------------------------------------------- */
|
||||||
|
|
||||||
double lj_vm_foldarith(double x, double y, int op)
|
double lj_vm_foldarith(double x, double y, int op)
|
||||||
{
|
{
|
||||||
@@ -56,6 +56,8 @@ double lj_vm_foldarith(double x, double y, int op)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -- Helper functions for generated machine code ------------------------- */
|
||||||
|
|
||||||
#if (LJ_HASJIT && !(LJ_TARGET_ARM || LJ_TARGET_ARM64 || LJ_TARGET_PPC)) || LJ_TARGET_MIPS
|
#if (LJ_HASJIT && !(LJ_TARGET_ARM || LJ_TARGET_ARM64 || LJ_TARGET_PPC)) || LJ_TARGET_MIPS
|
||||||
int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b)
|
int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b)
|
||||||
{
|
{
|
||||||
@@ -80,40 +82,6 @@ double lj_vm_log2(double a)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !LJ_TARGET_X86ORX64
|
|
||||||
/* Unsigned x^k. */
|
|
||||||
static double lj_vm_powui(double x, uint32_t k)
|
|
||||||
{
|
|
||||||
double y;
|
|
||||||
lj_assertX(k != 0, "pow with zero exponent");
|
|
||||||
for (; (k & 1) == 0; k >>= 1) x *= x;
|
|
||||||
y = x;
|
|
||||||
if ((k >>= 1) != 0) {
|
|
||||||
for (;;) {
|
|
||||||
x *= x;
|
|
||||||
if (k == 1) break;
|
|
||||||
if (k & 1) y *= x;
|
|
||||||
k >>= 1;
|
|
||||||
}
|
|
||||||
y *= x;
|
|
||||||
}
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Signed x^k. */
|
|
||||||
double lj_vm_powi(double x, int32_t k)
|
|
||||||
{
|
|
||||||
if (k > 1)
|
|
||||||
return lj_vm_powui(x, (uint32_t)k);
|
|
||||||
else if (k == 1)
|
|
||||||
return x;
|
|
||||||
else if (k == 0)
|
|
||||||
return 1.0;
|
|
||||||
else
|
|
||||||
return 1.0 / lj_vm_powui(x, (uint32_t)-k);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Computes fpm(x) for extended math functions. */
|
/* Computes fpm(x) for extended math functions. */
|
||||||
double lj_vm_foldfpm(double x, int fpm)
|
double lj_vm_foldfpm(double x, int fpm)
|
||||||
{
|
{
|
||||||
|
|||||||
+11
-12
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
static lua_State *globalL = NULL;
|
static lua_State *globalL = NULL;
|
||||||
static const char *progname = LUA_PROGNAME;
|
static const char *progname = LUA_PROGNAME;
|
||||||
|
static char *empty_argv[2] = { NULL, NULL };
|
||||||
|
|
||||||
#if !LJ_TARGET_CONSOLE
|
#if !LJ_TARGET_CONSOLE
|
||||||
static void lstop(lua_State *L, lua_Debug *ar)
|
static void lstop(lua_State *L, lua_Debug *ar)
|
||||||
@@ -78,9 +79,9 @@ static void print_usage(void)
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void l_message(const char *pname, const char *msg)
|
static void l_message(const char *msg)
|
||||||
{
|
{
|
||||||
if (pname) { fputs(pname, stderr); fputc(':', stderr); fputc(' ', stderr); }
|
if (progname) { fputs(progname, stderr); fputc(':', stderr); fputc(' ', stderr); }
|
||||||
fputs(msg, stderr); fputc('\n', stderr);
|
fputs(msg, stderr); fputc('\n', stderr);
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
@@ -90,7 +91,7 @@ static int report(lua_State *L, int status)
|
|||||||
if (status && !lua_isnil(L, -1)) {
|
if (status && !lua_isnil(L, -1)) {
|
||||||
const char *msg = lua_tostring(L, -1);
|
const char *msg = lua_tostring(L, -1);
|
||||||
if (msg == NULL) msg = "(error object is not a string)";
|
if (msg == NULL) msg = "(error object is not a string)";
|
||||||
l_message(progname, msg);
|
l_message(msg);
|
||||||
lua_pop(L, 1);
|
lua_pop(L, 1);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
@@ -256,9 +257,8 @@ static void dotty(lua_State *L)
|
|||||||
lua_getglobal(L, "print");
|
lua_getglobal(L, "print");
|
||||||
lua_insert(L, 1);
|
lua_insert(L, 1);
|
||||||
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
|
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
|
||||||
l_message(progname,
|
l_message(lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
|
||||||
lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
|
lua_tostring(L, -1)));
|
||||||
lua_tostring(L, -1)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_settop(L, 0); /* clear stack */
|
lua_settop(L, 0); /* clear stack */
|
||||||
@@ -310,8 +310,7 @@ static int loadjitmodule(lua_State *L)
|
|||||||
lua_getfield(L, -1, "start");
|
lua_getfield(L, -1, "start");
|
||||||
if (lua_isnil(L, -1)) {
|
if (lua_isnil(L, -1)) {
|
||||||
nomodule:
|
nomodule:
|
||||||
l_message(progname,
|
l_message("unknown luaJIT command or jit.* modules not installed");
|
||||||
"unknown luaJIT command or jit.* modules not installed");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
lua_remove(L, -2); /* Drop module table. */
|
lua_remove(L, -2); /* Drop module table. */
|
||||||
@@ -516,8 +515,6 @@ static int pmain(lua_State *L)
|
|||||||
int argn;
|
int argn;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
globalL = L;
|
globalL = L;
|
||||||
if (argv[0] && argv[0][0]) progname = argv[0];
|
|
||||||
|
|
||||||
LUAJIT_VERSION_SYM(); /* Linker-enforced version check. */
|
LUAJIT_VERSION_SYM(); /* Linker-enforced version check. */
|
||||||
|
|
||||||
argn = collectargs(argv, &flags);
|
argn = collectargs(argv, &flags);
|
||||||
@@ -572,9 +569,11 @@ static int pmain(lua_State *L)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
lua_State *L = lua_open();
|
lua_State *L;
|
||||||
|
if (!argv[0]) argv = empty_argv; else if (argv[0][0]) progname = argv[0];
|
||||||
|
L = lua_open();
|
||||||
if (L == NULL) {
|
if (L == NULL) {
|
||||||
l_message(argv[0], "cannot create state: not enough memory");
|
l_message("cannot create state: not enough memory");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
smain.argc = argc;
|
smain.argc = argc;
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
@rem Script to build LuaJIT with NintendoSDK + NX Addon.
|
||||||
|
@rem Donated to the public domain by Swyter.
|
||||||
|
@rem
|
||||||
|
@rem To run this script you must open a "Native Tools Command Prompt for VS".
|
||||||
|
@rem
|
||||||
|
@rem Either the x86 version for NX32, or x64 for the NX64 target.
|
||||||
|
@rem This is because the pointer size of the LuaJIT host tools (buildvm.exe)
|
||||||
|
@rem must match the cross-compiled target (32 or 64 bits).
|
||||||
|
@rem
|
||||||
|
@rem Then cd to this directory and run this script.
|
||||||
|
@rem
|
||||||
|
@rem Recommended invocation:
|
||||||
|
@rem
|
||||||
|
@rem nxbuild # release build, amalgamated
|
||||||
|
@rem nxbuild debug # debug build, amalgamated
|
||||||
|
@rem
|
||||||
|
@rem Additional command-line options (not generally recommended):
|
||||||
|
@rem
|
||||||
|
@rem noamalg # (after debug) non-amalgamated build
|
||||||
|
|
||||||
|
@if not defined INCLUDE goto :FAIL
|
||||||
|
@if not defined NINTENDO_SDK_ROOT goto :FAIL
|
||||||
|
@if not defined PLATFORM goto :FAIL
|
||||||
|
|
||||||
|
@if "%platform%" == "x86" goto :DO_NX32
|
||||||
|
@if "%platform%" == "x64" goto :DO_NX64
|
||||||
|
|
||||||
|
@echo Error: Current host platform is %platform%!
|
||||||
|
@echo.
|
||||||
|
@goto :FAIL
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
:DO_NX32
|
||||||
|
@set DASC=vm_arm.dasc
|
||||||
|
@set DASMFLAGS= -D HFABI -D FPU
|
||||||
|
@set DASMTARGET= -D LUAJIT_TARGET=LUAJIT_ARCH_ARM
|
||||||
|
@set HOST_PTR_SIZE=4
|
||||||
|
goto :BEGIN
|
||||||
|
|
||||||
|
:DO_NX64
|
||||||
|
@set DASC=vm_arm64.dasc
|
||||||
|
@set DASMFLAGS= -D ENDIAN_LE
|
||||||
|
@set DASMTARGET= -D LUAJIT_TARGET=LUAJIT_ARCH_ARM64
|
||||||
|
@set HOST_PTR_SIZE=8
|
||||||
|
|
||||||
|
:BEGIN
|
||||||
|
@rem ---- Host compiler ----
|
||||||
|
@set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /wo4146 /wo4244 /D_CRT_SECURE_NO_DEPRECATE
|
||||||
|
@set LJLINK=link /nologo
|
||||||
|
@set LJMT=mt /nologo
|
||||||
|
@set DASMDIR=..\dynasm
|
||||||
|
@set DASM=%DASMDIR%\dynasm.lua
|
||||||
|
@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
|
||||||
|
|
||||||
|
%LJCOMPILE% host\minilua.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
%LJLINK% /out:minilua.exe minilua.obj
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
if exist minilua.exe.manifest^
|
||||||
|
%LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe
|
||||||
|
|
||||||
|
@rem Check that we have the right 32/64 bit host compiler to generate the right virtual machine files.
|
||||||
|
@minilua
|
||||||
|
@if "%ERRORLEVEL%" == "%HOST_PTR_SIZE%" goto :PASSED_PTR_CHECK
|
||||||
|
|
||||||
|
@echo The pointer size of the host in bytes (%HOST_PTR_SIZE%) does not match the expected value (%errorlevel%).
|
||||||
|
@echo Check that the script is being ran under the correct x86/x64 VS prompt.
|
||||||
|
@goto :BAD
|
||||||
|
|
||||||
|
:PASSED_PTR_CHECK
|
||||||
|
@set DASMFLAGS=%DASMFLAGS% %DASMTARGET% -D LJ_TARGET_NX -D LUAJIT_OS=LUAJIT_OS_OTHER -D LUAJIT_DISABLE_JIT -D LUAJIT_DISABLE_FFI
|
||||||
|
minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h %DASC%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
%LJCOMPILE% /I "." /I %DASMDIR% %DASMTARGET% -D LJ_TARGET_NX -DLUAJIT_OS=LUAJIT_OS_OTHER -DLUAJIT_DISABLE_JIT -DLUAJIT_DISABLE_FFI host\buildvm*.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
%LJLINK% /out:buildvm.exe buildvm*.obj
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
if exist buildvm.exe.manifest^
|
||||||
|
%LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe
|
||||||
|
|
||||||
|
buildvm -m elfasm -o lj_vm.s
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m bcdef -o lj_bcdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m ffdef -o lj_ffdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m libdef -o lj_libdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m recdef -o lj_recdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m folddef -o lj_folddef.h lj_opt_fold.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
|
||||||
|
@rem ---- Cross compiler ----
|
||||||
|
@if "%platform%" neq "x64" goto :NX32_CROSSBUILD
|
||||||
|
@set LJCOMPILE="%NINTENDO_SDK_ROOT%\Compilers\NX\nx\aarch64\bin\clang" -Wall -I%NINTENDO_SDK_ROOT%\Include %DASMTARGET% -DLUAJIT_OS=LUAJIT_OS_OTHER -DLUAJIT_DISABLE_JIT -DLUAJIT_DISABLE_FFI -DLUAJIT_USE_SYSMALLOC -c
|
||||||
|
@set LJLIB="%NINTENDO_SDK_ROOT%\Compilers\NX\nx\aarch64\bin\aarch64-nintendo-nx-elf-ar" rc
|
||||||
|
@set TARGETLIB_SUFFIX=nx64
|
||||||
|
|
||||||
|
%NINTENDO_SDK_ROOT%\Compilers\NX\nx\aarch64\bin\aarch64-nintendo-nx-elf-as -o lj_vm.o lj_vm.s
|
||||||
|
goto :DEBUGCHECK
|
||||||
|
|
||||||
|
:NX32_CROSSBUILD
|
||||||
|
@set LJCOMPILE="%NINTENDO_SDK_ROOT%\Compilers\NX\nx\armv7l\bin\clang" -Wall -I%NINTENDO_SDK_ROOT%\Include %DASMTARGET% -DLUAJIT_OS=LUAJIT_OS_OTHER -DLUAJIT_DISABLE_JIT -DLUAJIT_DISABLE_FFI -DLUAJIT_USE_SYSMALLOC -c
|
||||||
|
@set LJLIB="%NINTENDO_SDK_ROOT%\Compilers\NX\nx\armv7l\bin\armv7l-nintendo-nx-eabihf-ar" rc
|
||||||
|
@set TARGETLIB_SUFFIX=nx32
|
||||||
|
|
||||||
|
%NINTENDO_SDK_ROOT%\Compilers\NX\nx\armv7l\bin\armv7l-nintendo-nx-eabihf-as -o lj_vm.o lj_vm.s
|
||||||
|
:DEBUGCHECK
|
||||||
|
|
||||||
|
@if "%1" neq "debug" goto :NODEBUG
|
||||||
|
@shift
|
||||||
|
@set LJCOMPILE=%LJCOMPILE% -DNN_SDK_BUILD_DEBUG -g -O0
|
||||||
|
@set TARGETLIB=libluajitD_%TARGETLIB_SUFFIX%.a
|
||||||
|
goto :BUILD
|
||||||
|
:NODEBUG
|
||||||
|
@set LJCOMPILE=%LJCOMPILE% -DNN_SDK_BUILD_RELEASE -O3
|
||||||
|
@set TARGETLIB=libluajit_%TARGETLIB_SUFFIX%.a
|
||||||
|
:BUILD
|
||||||
|
del %TARGETLIB%
|
||||||
|
@if "%1" neq "noamalg" goto :AMALG
|
||||||
|
for %%f in (lj_*.c lib_*.c) do (
|
||||||
|
%LJCOMPILE% %%f
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
)
|
||||||
|
|
||||||
|
%LJLIB% %TARGETLIB% lj_*.o lib_*.o
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
@goto :NOAMALG
|
||||||
|
:AMALG
|
||||||
|
%LJCOMPILE% ljamalg.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
%LJLIB% %TARGETLIB% ljamalg.o lj_vm.o
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
:NOAMALG
|
||||||
|
|
||||||
|
@del *.o *.obj *.manifest minilua.exe buildvm.exe
|
||||||
|
@echo.
|
||||||
|
@echo === Successfully built LuaJIT for Nintendo Switch (%TARGETLIB_SUFFIX%) ===
|
||||||
|
|
||||||
|
@goto :END
|
||||||
|
:BAD
|
||||||
|
@echo.
|
||||||
|
@echo *******************************************************
|
||||||
|
@echo *** Build FAILED -- Please check the error messages ***
|
||||||
|
@echo *******************************************************
|
||||||
|
@goto :END
|
||||||
|
:FAIL
|
||||||
|
@echo To run this script you must open a "Native Tools Command Prompt for VS".
|
||||||
|
@echo.
|
||||||
|
@echo Either the x86 version for NX32, or x64 for the NX64 target.
|
||||||
|
@echo This is because the pointer size of the LuaJIT host tools (buildvm.exe)
|
||||||
|
@echo must match the cross-compiled target (32 or 64 bits).
|
||||||
|
@echo.
|
||||||
|
@echo Keep in mind that NintendoSDK + NX Addon must be installed, too.
|
||||||
|
:END
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
@rem Script to build LuaJIT with the PS5 SDK.
|
||||||
|
@rem Donated to the public domain.
|
||||||
|
@rem
|
||||||
|
@rem Open a "Visual Studio .NET Command Prompt" (64 bit host compiler)
|
||||||
|
@rem or "VS20xx x64 Native Tools Command Prompt".
|
||||||
|
@rem
|
||||||
|
@rem Then cd to this directory and run this script.
|
||||||
|
@rem
|
||||||
|
@rem Recommended invocation:
|
||||||
|
@rem
|
||||||
|
@rem ps5build release build, amalgamated, 64-bit GC
|
||||||
|
@rem ps5build debug debug build, amalgamated, 64-bit GC
|
||||||
|
@rem
|
||||||
|
@rem Additional command-line options (not generally recommended):
|
||||||
|
@rem
|
||||||
|
@rem gc32 (before debug) 32-bit GC
|
||||||
|
@rem noamalg (after debug) non-amalgamated build
|
||||||
|
|
||||||
|
@if not defined INCLUDE goto :FAIL
|
||||||
|
@if not defined SCE_PROSPERO_SDK_DIR goto :FAIL
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
@rem ---- Host compiler ----
|
||||||
|
@set LJCOMPILE=cl /nologo /c /MD /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE
|
||||||
|
@set LJLINK=link /nologo
|
||||||
|
@set LJMT=mt /nologo
|
||||||
|
@set DASMDIR=..\dynasm
|
||||||
|
@set DASM=%DASMDIR%\dynasm.lua
|
||||||
|
@set ALL_LIB=lib_base.c lib_math.c lib_bit.c lib_string.c lib_table.c lib_io.c lib_os.c lib_package.c lib_debug.c lib_jit.c lib_ffi.c lib_buffer.c
|
||||||
|
@set GC64=
|
||||||
|
@set DASC=vm_x64.dasc
|
||||||
|
|
||||||
|
@if "%1" neq "gc32" goto :NOGC32
|
||||||
|
@shift
|
||||||
|
@set GC64=-DLUAJIT_DISABLE_GC64
|
||||||
|
@set DASC=vm_x86.dasc
|
||||||
|
:NOGC32
|
||||||
|
|
||||||
|
%LJCOMPILE% host\minilua.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
%LJLINK% /out:minilua.exe minilua.obj
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
if exist minilua.exe.manifest^
|
||||||
|
%LJMT% -manifest minilua.exe.manifest -outputresource:minilua.exe
|
||||||
|
|
||||||
|
@rem Check for 64 bit host compiler.
|
||||||
|
@minilua
|
||||||
|
@if not errorlevel 8 goto :FAIL
|
||||||
|
|
||||||
|
@set DASMFLAGS=-D P64 -D NO_UNWIND
|
||||||
|
minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h %DASC%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
|
||||||
|
%LJCOMPILE% /I "." /I %DASMDIR% %GC64% -DLUAJIT_TARGET=LUAJIT_ARCH_X64 -DLUAJIT_OS=LUAJIT_OS_OTHER -DLUAJIT_DISABLE_JIT -DLUAJIT_DISABLE_FFI -DLUAJIT_NO_UNWIND host\buildvm*.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
%LJLINK% /out:buildvm.exe buildvm*.obj
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
if exist buildvm.exe.manifest^
|
||||||
|
%LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe
|
||||||
|
|
||||||
|
buildvm -m elfasm -o lj_vm.s
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m bcdef -o lj_bcdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m ffdef -o lj_ffdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m libdef -o lj_libdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m recdef -o lj_recdef.h %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB%
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
buildvm -m folddef -o lj_folddef.h lj_opt_fold.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
|
||||||
|
@rem ---- Cross compiler ----
|
||||||
|
@set LJCOMPILE="%SCE_PROSPERO_SDK_DIR%\host_tools\bin\prospero-clang" -c -Wall -DLUAJIT_DISABLE_FFI %GC64%
|
||||||
|
@set LJLIB="%SCE_PROSPERO_SDK_DIR%\host_tools\bin\prospero-llvm-ar" rcus
|
||||||
|
@set INCLUDE=""
|
||||||
|
|
||||||
|
%SCE_PROSPERO_SDK_DIR%\host_tools\bin\prospero-llvm-as -o lj_vm.o lj_vm.s
|
||||||
|
|
||||||
|
@if "%1" neq "debug" goto :NODEBUG
|
||||||
|
@shift
|
||||||
|
@set LJCOMPILE=%LJCOMPILE% -g -O0
|
||||||
|
@set TARGETLIB=libluajitD_ps5.a
|
||||||
|
goto :BUILD
|
||||||
|
:NODEBUG
|
||||||
|
@set LJCOMPILE=%LJCOMPILE% -O2
|
||||||
|
@set TARGETLIB=libluajit_ps5.a
|
||||||
|
:BUILD
|
||||||
|
del %TARGETLIB%
|
||||||
|
@if "%1" neq "noamalg" goto :AMALG
|
||||||
|
for %%f in (lj_*.c lib_*.c) do (
|
||||||
|
%LJCOMPILE% %%f
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
)
|
||||||
|
|
||||||
|
%LJLIB% %TARGETLIB% lj_*.o lib_*.o
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
@goto :NOAMALG
|
||||||
|
:AMALG
|
||||||
|
%LJCOMPILE% ljamalg.c
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
%LJLIB% %TARGETLIB% ljamalg.o lj_vm.o
|
||||||
|
@if errorlevel 1 goto :BAD
|
||||||
|
:NOAMALG
|
||||||
|
|
||||||
|
@del *.o *.obj *.manifest minilua.exe buildvm.exe
|
||||||
|
@echo.
|
||||||
|
@echo === Successfully built LuaJIT for PS5 ===
|
||||||
|
|
||||||
|
@goto :END
|
||||||
|
:BAD
|
||||||
|
@echo.
|
||||||
|
@echo *******************************************************
|
||||||
|
@echo *** Build FAILED -- Please check the error messages ***
|
||||||
|
@echo *******************************************************
|
||||||
|
@goto :END
|
||||||
|
:FAIL
|
||||||
|
@echo To run this script you must open a "Visual Studio .NET Command Prompt"
|
||||||
|
@echo (64 bit host compiler). The PS5 Prospero SDK must be installed, too.
|
||||||
|
:END
|
||||||
@@ -3988,6 +3988,7 @@ static void emit_asm_debug(BuildCtx *ctx)
|
|||||||
"\t.align 3\n"
|
"\t.align 3\n"
|
||||||
".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
|
".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
|
||||||
#endif
|
#endif
|
||||||
|
#if !LJ_NO_UNWIND
|
||||||
fprintf(ctx->fp, "\t.section .eh_frame,\"a\",%%progbits\n");
|
fprintf(ctx->fp, "\t.section .eh_frame,\"a\",%%progbits\n");
|
||||||
fprintf(ctx->fp,
|
fprintf(ctx->fp,
|
||||||
".Lframe1:\n"
|
".Lframe1:\n"
|
||||||
@@ -4055,6 +4056,7 @@ static void emit_asm_debug(BuildCtx *ctx)
|
|||||||
"\t.byte 0x94\n\t.uleb128 4\n" /* offset x20 */
|
"\t.byte 0x94\n\t.uleb128 4\n" /* offset x20 */
|
||||||
"\t.align 3\n"
|
"\t.align 3\n"
|
||||||
".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
|
".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
#if !LJ_NO_UNWIND
|
#if !LJ_NO_UNWIND
|
||||||
|
|||||||
@@ -359,9 +359,6 @@
|
|||||||
|.macro sseconst_1, reg, tmp // Synthesize 1.0.
|
|.macro sseconst_1, reg, tmp // Synthesize 1.0.
|
||||||
| sseconst_hi reg, tmp, 3ff00000
|
| sseconst_hi reg, tmp, 3ff00000
|
||||||
|.endmacro
|
|.endmacro
|
||||||
|.macro sseconst_m1, reg, tmp // Synthesize -1.0.
|
|
||||||
| sseconst_hi reg, tmp, bff00000
|
|
||||||
|.endmacro
|
|
||||||
|.macro sseconst_2p52, reg, tmp // Synthesize 2^52.
|
|.macro sseconst_2p52, reg, tmp // Synthesize 2^52.
|
||||||
| sseconst_hi reg, tmp, 43300000
|
| sseconst_hi reg, tmp, 43300000
|
||||||
|.endmacro
|
|.endmacro
|
||||||
@@ -2530,15 +2527,17 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
|
| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
|
||||||
| subsd xmm1, xmm3
|
| subsd xmm1, xmm3
|
||||||
| orpd xmm1, xmm2 // Merge sign bit back in.
|
| orpd xmm1, xmm2 // Merge sign bit back in.
|
||||||
|
| sseconst_1 xmm3, RD
|
||||||
| .if mode == 1 // ceil(x)?
|
| .if mode == 1 // ceil(x)?
|
||||||
| sseconst_m1 xmm2, RD // Must subtract -1 to preserve -0.
|
|
||||||
| cmpsd xmm0, xmm1, 6 // x > result?
|
| cmpsd xmm0, xmm1, 6 // x > result?
|
||||||
|
| andpd xmm0, xmm3
|
||||||
|
| addsd xmm1, xmm0 // If yes, add 1.
|
||||||
|
| orpd xmm1, xmm2 // Merge sign bit back in (again).
|
||||||
| .else // floor(x)?
|
| .else // floor(x)?
|
||||||
| sseconst_1 xmm2, RD
|
|
||||||
| cmpsd xmm0, xmm1, 1 // x < result?
|
| cmpsd xmm0, xmm1, 1 // x < result?
|
||||||
|
| andpd xmm0, xmm3
|
||||||
|
| subsd xmm1, xmm0 // If yes, subtract 1.
|
||||||
| .endif
|
| .endif
|
||||||
| andpd xmm0, xmm2
|
|
||||||
| subsd xmm1, xmm0 // If yes, subtract +-1.
|
|
||||||
|.endif
|
|.endif
|
||||||
| movaps xmm0, xmm1
|
| movaps xmm0, xmm1
|
||||||
|1:
|
|1:
|
||||||
@@ -2579,41 +2578,6 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| subsd xmm0, xmm1
|
| subsd xmm0, xmm1
|
||||||
| ret
|
| ret
|
||||||
|
|
|
|
||||||
|// Args in xmm0/eax. Ret in xmm0. xmm0-xmm1 and eax modified.
|
|
||||||
|->vm_powi_sse:
|
|
||||||
| cmp eax, 1; jle >6 // i<=1?
|
|
||||||
| // Now 1 < (unsigned)i <= 0x80000000.
|
|
||||||
|1: // Handle leading zeros.
|
|
||||||
| test eax, 1; jnz >2
|
|
||||||
| mulsd xmm0, xmm0
|
|
||||||
| shr eax, 1
|
|
||||||
| jmp <1
|
|
||||||
|2:
|
|
||||||
| shr eax, 1; jz >5
|
|
||||||
| movaps xmm1, xmm0
|
|
||||||
|3: // Handle trailing bits.
|
|
||||||
| mulsd xmm0, xmm0
|
|
||||||
| shr eax, 1; jz >4
|
|
||||||
| jnc <3
|
|
||||||
| mulsd xmm1, xmm0
|
|
||||||
| jmp <3
|
|
||||||
|4:
|
|
||||||
| mulsd xmm0, xmm1
|
|
||||||
|5:
|
|
||||||
| ret
|
|
||||||
|6:
|
|
||||||
| je <5 // x^1 ==> x
|
|
||||||
| jb >7 // x^0 ==> 1
|
|
||||||
| neg eax
|
|
||||||
| call <1
|
|
||||||
| sseconst_1 xmm1, RD
|
|
||||||
| divsd xmm1, xmm0
|
|
||||||
| movaps xmm0, xmm1
|
|
||||||
| ret
|
|
||||||
|7:
|
|
||||||
| sseconst_1 xmm0, RD
|
|
||||||
| ret
|
|
||||||
|
|
|
||||||
|//-----------------------------------------------------------------------
|
|//-----------------------------------------------------------------------
|
||||||
|//-- Miscellaneous functions --------------------------------------------
|
|//-- Miscellaneous functions --------------------------------------------
|
||||||
|//-----------------------------------------------------------------------
|
|//-----------------------------------------------------------------------
|
||||||
|
|||||||
@@ -464,9 +464,6 @@
|
|||||||
|.macro sseconst_1, reg, tmp // Synthesize 1.0.
|
|.macro sseconst_1, reg, tmp // Synthesize 1.0.
|
||||||
| sseconst_hi reg, tmp, 3ff00000
|
| sseconst_hi reg, tmp, 3ff00000
|
||||||
|.endmacro
|
|.endmacro
|
||||||
|.macro sseconst_m1, reg, tmp // Synthesize -1.0.
|
|
||||||
| sseconst_hi reg, tmp, bff00000
|
|
||||||
|.endmacro
|
|
||||||
|.macro sseconst_2p52, reg, tmp // Synthesize 2^52.
|
|.macro sseconst_2p52, reg, tmp // Synthesize 2^52.
|
||||||
| sseconst_hi reg, tmp, 43300000
|
| sseconst_hi reg, tmp, 43300000
|
||||||
|.endmacro
|
|.endmacro
|
||||||
@@ -2989,15 +2986,17 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
|
| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
|
||||||
| subsd xmm1, xmm3
|
| subsd xmm1, xmm3
|
||||||
| orpd xmm1, xmm2 // Merge sign bit back in.
|
| orpd xmm1, xmm2 // Merge sign bit back in.
|
||||||
|
| sseconst_1 xmm3, RDa
|
||||||
| .if mode == 1 // ceil(x)?
|
| .if mode == 1 // ceil(x)?
|
||||||
| sseconst_m1 xmm2, RDa // Must subtract -1 to preserve -0.
|
|
||||||
| cmpsd xmm0, xmm1, 6 // x > result?
|
| cmpsd xmm0, xmm1, 6 // x > result?
|
||||||
|
| andpd xmm0, xmm3
|
||||||
|
| addsd xmm1, xmm0 // If yes, add 1.
|
||||||
|
| orpd xmm1, xmm2 // Merge sign bit back in (again).
|
||||||
| .else // floor(x)?
|
| .else // floor(x)?
|
||||||
| sseconst_1 xmm2, RDa
|
|
||||||
| cmpsd xmm0, xmm1, 1 // x < result?
|
| cmpsd xmm0, xmm1, 1 // x < result?
|
||||||
|
| andpd xmm0, xmm3
|
||||||
|
| subsd xmm1, xmm0 // If yes, subtract 1.
|
||||||
| .endif
|
| .endif
|
||||||
| andpd xmm0, xmm2
|
|
||||||
| subsd xmm1, xmm0 // If yes, subtract +-1.
|
|
||||||
|.endif
|
|.endif
|
||||||
| movaps xmm0, xmm1
|
| movaps xmm0, xmm1
|
||||||
|1:
|
|1:
|
||||||
@@ -3038,41 +3037,6 @@ static void build_subroutines(BuildCtx *ctx)
|
|||||||
| subsd xmm0, xmm1
|
| subsd xmm0, xmm1
|
||||||
| ret
|
| ret
|
||||||
|
|
|
|
||||||
|// Args in xmm0/eax. Ret in xmm0. xmm0-xmm1 and eax modified.
|
|
||||||
|->vm_powi_sse:
|
|
||||||
| cmp eax, 1; jle >6 // i<=1?
|
|
||||||
| // Now 1 < (unsigned)i <= 0x80000000.
|
|
||||||
|1: // Handle leading zeros.
|
|
||||||
| test eax, 1; jnz >2
|
|
||||||
| mulsd xmm0, xmm0
|
|
||||||
| shr eax, 1
|
|
||||||
| jmp <1
|
|
||||||
|2:
|
|
||||||
| shr eax, 1; jz >5
|
|
||||||
| movaps xmm1, xmm0
|
|
||||||
|3: // Handle trailing bits.
|
|
||||||
| mulsd xmm0, xmm0
|
|
||||||
| shr eax, 1; jz >4
|
|
||||||
| jnc <3
|
|
||||||
| mulsd xmm1, xmm0
|
|
||||||
| jmp <3
|
|
||||||
|4:
|
|
||||||
| mulsd xmm0, xmm1
|
|
||||||
|5:
|
|
||||||
| ret
|
|
||||||
|6:
|
|
||||||
| je <5 // x^1 ==> x
|
|
||||||
| jb >7 // x^0 ==> 1
|
|
||||||
| neg eax
|
|
||||||
| call <1
|
|
||||||
| sseconst_1 xmm1, RDa
|
|
||||||
| divsd xmm1, xmm0
|
|
||||||
| movaps xmm0, xmm1
|
|
||||||
| ret
|
|
||||||
|7:
|
|
||||||
| sseconst_1 xmm0, RDa
|
|
||||||
| ret
|
|
||||||
|
|
|
||||||
|//-----------------------------------------------------------------------
|
|//-----------------------------------------------------------------------
|
||||||
|//-- Miscellaneous functions --------------------------------------------
|
|//-- Miscellaneous functions --------------------------------------------
|
||||||
|//-----------------------------------------------------------------------
|
|//-----------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user