This commit is contained in:
Miku AuahDark
2022-08-25 18:33:56 +08:00
parent 27276a031d
commit 65e6adcbd1
69 changed files with 992 additions and 553 deletions
+5 -1
View File
@@ -33,7 +33,8 @@ DPREFIX= $(DESTDIR)$(PREFIX)
INSTALL_BIN= $(DPREFIX)/bin
INSTALL_LIB= $(DPREFIX)/$(MULTILIB)
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_JITLIB= $(INSTALL_LJLIBD)/jit
@@ -78,6 +79,9 @@ UNINSTALL= $(RM)
LDCONFIG= ldconfig -n 2>/dev/null
SED_PC= sed -e "s|^prefix=.*|prefix=$(PREFIX)|" \
-e "s|^multilib=.*|multilib=$(MULTILIB)|"
ifneq ($(INSTALL_DEFINC),$(INSTALL_INC))
SED_PC+= -e "s|^includedir=.*|includedir=$(INSTALL_INC)|"
endif
FILE_T= luajit
FILE_A= libluajit.a
+7 -7
View File
@@ -86,7 +86,7 @@ overhead. In conjunction with the FFI library, they allow zero-copy
operations.
</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.
</p>
@@ -434,8 +434,8 @@ unsupported object types, circular references or deeply nested tables.
<h3 id="buffer_decode"><tt>obj = buffer.decode(str)<br>
obj = buf:decode()</tt></h3>
<p>
The stand-alone function de-serializes (decodes) the string
<tt>str</tt>, the buffer method de-serializes one object from the
The stand-alone function deserializes (decodes) the string
<tt>str</tt>, the buffer method deserializes one object from the
buffer. Both return a Lua object <tt>obj</tt>.
</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.
</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.
</p>
@@ -462,7 +462,7 @@ the following members (all optional):
<li>
<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
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.
</li>
<li>
@@ -473,7 +473,7 @@ for the table objects you are serializing.
<p>
<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
<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
a plain array). The tables must not be modified after they have been passed
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.
</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
<tt>obj:method()</tt> does that implicitly. But to wrap a method with
<tt>pcall()</tt>, the arguments need to be passed like this:
+2 -2
View File
@@ -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
the parent of the calling function (<tt>idx = 0</tt>). It either
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
<tt>LUAJIT_MODE_ALLFUNC</tt> or only to the sub-functions with
<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
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
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
off and all C functions are directly called.
</p>
+7 -7
View File
@@ -157,7 +157,7 @@ call the binding function. Phew!
<h2 id="cdata">Motivating Example: Using C Data Structures</h2>
<p>
The FFI library allows you to create and access C&nbsp;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&nbsp;functions. But they can be used stand-alone, too.
</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.
</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:
</p>
<pre class="code">
@@ -184,7 +184,7 @@ local function image_ramp_green(n)
return img
end
local function image_to_grey(img, n)
local function image_to_gray(img, n)
for i=1,n do
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
@@ -194,14 +194,14 @@ end
local N = 400*400
local img = image_ramp_green(N)
for i=1,1000 do
image_to_grey(img, N)
image_to_gray(img, N)
end
</pre>
<p>
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
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 ...
</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.
</p>
<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
the FFI version of the code. Also, high-level data structures cannot
be easily passed to other C&nbsp;functions, especially I/O functions,
+5 -5
View File
@@ -121,7 +121,7 @@ separated by semicolons. The trailing semicolon for a single
declaration may be omitted.
</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
achieved with C&nbsp;library namespaces (see below).
</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.
</p>
<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
<tt>ffi.new()</tt>. This is probably <b>not</b> what you want,
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
afterwards. The associated metatable automatically applies to all uses
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).
</p>
<p>
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
<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>
@@ -492,7 +492,7 @@ have some extra methods:
<p>
Free the resources associated with a callback. The associated Lua
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).
</p>
+29 -29
View File
@@ -88,7 +88,7 @@ footprint. It's used by the <a href="ext_ffi_api.html">ffi.* library
functions</a> to declare C&nbsp;types or external symbols.
</p>
<p>
It's only purpose is to parse C&nbsp;declarations, as found e.g. in
Its only purpose is to parse C&nbsp;declarations, as found e.g. in
C&nbsp;header files. Although it does evaluate constant expressions,
it's <em>not</em> a C&nbsp;compiler. The body of <tt>inline</tt>
C&nbsp;function definitions is simply ignored.
@@ -165,7 +165,7 @@ function declarations.</li>
</ul>
<p>
The following C&nbsp;types are pre-defined by the C&nbsp;parser (like
The following C&nbsp;types are predefined by the C&nbsp;parser (like
a <tt>typedef</tt>, except re-declarations will be ignored):
</p>
<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>
<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
the pre-defined operations.
the predefined operations.
</p>
<p>
Reference types are dereferenced <em>before</em> performing each of
@@ -593,7 +593,7 @@ the operations below &mdash; the operation is applied to the
C&nbsp;type pointed to by the reference.
</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
for <tt>__new</tt>). An error is raised if the metamethod lookup or
index table lookup fails.
@@ -643,7 +643,7 @@ assigning to an index of a vector raises an error.</li>
</ul>
<p>
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
to the corresponding metamethods or index tables (if any).
</p>
@@ -656,7 +656,7 @@ certain optimizations.
<p>
As a consequence, the <em>elements</em> of complex numbers and
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
to <tt>foo.c</tt>.
</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
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
use <tt>ffi.new</tt> inside of it, since calling <tt>ct(...)</tt> would
cause infinite recursion.</li>
use <tt>ffi.new</tt> inside the metamethod, since calling <tt>ct(...)</tt>
would cause infinite recursion.</li>
<li><b>C&nbsp;function call</b>: a cdata function or cdata function
pointer can be called. The passed arguments are
@@ -687,7 +687,7 @@ variable argument part of vararg C&nbsp;function use
C&nbsp;function is called and the return value (if any) is
<a href="#convert_tolua">converted to a Lua object</a>.<br>
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>
</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
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
multiplied by the element size in bytes. An error is raised if the
element size is undefined.</li>
@@ -712,7 +712,7 @@ operators (<tt>+&nbsp;-&nbsp;*&nbsp;/&nbsp;%&nbsp;^</tt> and unary
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
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
result is a boxed 64&nbsp;bit cdata object.<br>
@@ -759,7 +759,7 @@ which is compatible with any other pointer type.</li>
<li><b>64&nbsp;bit integer comparison</b>: two cdata numbers, or a
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
<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
comparison is performed.<br>
@@ -784,9 +784,9 @@ keys!</b>
A cdata object is treated like any other garbage-collected object and
is hashed and compared by its address for table indexing. Since
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
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>.
</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
the same slot as <tt>t[2]</tt>.</li>
<li>Otherwise use either <tt>tostring()</tt> on 64&nbsp;bit integers
<li>Otherwise, use either <tt>tostring()</tt> on 64&nbsp;bit integers
or complex numbers or combine multiple fields of a cdata aggregate to
a Lua string (e.g. with
<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
C&nbsp;types provided by the FFI library, just like you would in
C&nbsp;code. Ultimately this may give much better performance than the
C&nbsp;code. Ultimately, this may give much better performance than the
other alternatives or what a generic by-value hash table could
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).
</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
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:
@@ -931,18 +931,18 @@ of the function pointer and the Lua function object (closure).
</p>
<p>
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
C&nbsp;function pointer.
</p>
<p>
Currently only certain C&nbsp;function types can be used as callback
Currently, only certain C&nbsp;function types can be used as callback
functions. Neither C&nbsp;vararg functions nor functions with
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 &mdash; no checks for the proper number of arguments
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>
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.
</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
C&nbsp;function pointer and keep the resulting cdata object. Then use
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>
For new designs <b>avoid push-style APIs</b>: a C&nbsp;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&nbsp;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
libraries already use pull-style APIs (read/write, get/put).
@@ -1075,7 +1075,7 @@ function.
</p>
<p>
Indexing a C&nbsp;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 &mdash; it must have been declared with
<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
@@ -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
effectively turns function cdata objects into constants. It's not
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 =
ffi.C</tt>.
</p>
@@ -1155,14 +1155,14 @@ This behavior is inevitable, since the goal is to provide full
interoperability with C&nbsp;code. Adding extra safety measures, like
bounds checks, would be futile. There's no way to detect
misdeclarations of C&nbsp;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.
</p>
<p>
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
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
first exercise for someone with little experience in Lua, C or C++.
</p>
@@ -1190,7 +1190,7 @@ currently incomplete:
<li>C&nbsp;declarations are not passed through a C&nbsp;pre-processor,
yet.</li>
<li>The C&nbsp;parser is able to evaluate most constant expressions
commonly found in C&nbsp;header files. However it doesn't handle the
commonly found in C&nbsp;header files. However, it doesn't handle the
full range of C&nbsp;expression semantics and may fail for some
obscure constructs.</li>
<li><tt>static const</tt> declarations only work for integer types
+12 -12
View File
@@ -85,7 +85,7 @@ of its functions:
local ffi = require("ffi")
</pre>
<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 &mdash; you really need to use the local variable. The
<tt>require</tt> function ensures the library is only loaded once.
</p>
@@ -194,7 +194,7 @@ don't need to declare them as such.
<span class="mark">&#9316;</span> The <tt>poll()</tt>
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>
for the <tt>nfds</tt> parameter. Please note that the
for the <tt>nfds</tt> parameter. Please note, that the
number&nbsp;<tt>0</tt> <em>does not convert to a pointer value</em>,
unlike in C++. You really have to pass pointers to pointer arguments
and numbers to number arguments.
@@ -291,12 +291,12 @@ Here's the step-by-step explanation:
<p>
<span class="mark">&#9312;</span> This defines some of the
C&nbsp;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.
</p>
<p>
<span class="mark">&#9313;</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
missing standard prefixes/suffixes, we can simply load the
<tt>"z"</tt> library. On Windows it's named <tt>zlib1.dll</tt> and
@@ -324,7 +324,7 @@ actual length that was used.
<p>
In C you'd pass in the address of a local variable
(<tt>&amp;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
actual <tt>zlib.compress2</tt> function is then straightforward.
</p>
@@ -348,7 +348,7 @@ for garbage collection and string interning.
<span class="mark">&#9317;</span> The <tt>uncompress</tt>
functions does the exact opposite of the <tt>compress</tt> function.
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>
<span class="mark">&#9318;</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
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
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
application might work on some systems, but would fail in a POSIX/x64
environment.
@@ -454,7 +454,7 @@ the origin.
</p>
<p>
<span class="mark">&#9315;</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
define <tt>__index</tt> and <tt>__newindex</tt> <em>functions</em> instead.
</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.
</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
<tt>__index</tt> table.
</p>
<p>
<span class="mark">&#9317;</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
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
@@ -483,7 +483,7 @@ called with the Lua syntax for methods: <tt>a:area()</tt>, not
<p>
The C&nbsp;type metamethod mechanism is most useful when used in
conjunction with C&nbsp;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
<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
@@ -569,7 +569,7 @@ end
</pre>
<p>
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:
</p>
<pre class="code">
+2 -2
View File
@@ -154,7 +154,7 @@ Contains the target architecture name:
<h2 id="jit_opt"><tt>jit.opt.*</tt> &mdash; JIT compiler optimization control</h2>
<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.
</p>
<p>
@@ -174,7 +174,7 @@ which was one of the ways to enable optimization.
<h2 id="jit_util"><tt>jit.util.*</tt> &mdash; JIT compiler introspection</h2>
<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
provided by this module is still in flux and therefore undocumented.
</p>
+4 -4
View File
@@ -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
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
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?".
</p>
<p>
@@ -217,7 +217,7 @@ local profile = require("jit.profile")
This module can be used to implement your own higher-level profiler.
A typical profiling run starts the profiler, captures stack dumps in
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,
too. But it's important not to spend too much time in the callback,
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:
</p>
<ul>
<li><tt>p</tt> &mdash; Preserve the full path for module names. Otherwise
<li><tt>p</tt> &mdash; Preserve the full path for module names. Otherwise,
only the file name is used.</li>
<li><tt>f</tt> &mdash; Dump the function name if it can be derived. Otherwise
<li><tt>f</tt> &mdash; Dump the function name if it can be derived. Otherwise,
use module:line.</li>
<li><tt>F</tt> &mdash; Ditto, but dump module:name.</li>
<li><tt>l</tt> &mdash; Dump module:line.</li>
+5 -5
View File
@@ -88,7 +88,7 @@ or LuaJIT.
</p>
<p>
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,
such as the optimized VM, the faster interpreter or the JIT compiler.
</p>
@@ -197,7 +197,7 @@ usage. See also the
</p>
<p>
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
for dot releases (x.y.0 &rarr; x.y.1), but may change with major or
minor releases (2.0 &rarr; 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.
</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
and let the GC do its work.
</p>
@@ -239,7 +239,7 @@ and let the GC do its work.
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
<tt>math.random()</tt> and <tt>math.randomseed()</tt>. The quality of
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>
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&nbsp;bit file offsets</h3>
<p>
The file I/O functions in the standard <tt>io.*</tt> library handle
64&nbsp;bit file offsets. In particular this means it's possible
64&nbsp;bit file offsets. In particular, this means it's possible
to open files larger than 2&nbsp;Gigabytes and to reposition or obtain
the current file position for offsets beyond 2&nbsp;GB
(<tt>fp:seek()</tt> method).
+3 -3
View File
@@ -120,7 +120,7 @@ Direct3D version 10 or higher do not show this behavior anymore.
Consider testing your application with older versions, too.<br>
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>
</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
and never falls back to the interpreter, the debug hook never runs and
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>
</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">
<dt>Q: Can Lua code be safely sandboxed?</dt>
<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>
Although Lua provides some sandboxing functionality (<tt>setfenv()</tt>, hooks),
+241 -92
View File
@@ -14,25 +14,20 @@ table.compat {
}
table.compat td {
border: 1px solid #bfcfff;
height: 2.5em;
height: 1.5em;
}
table.compat tr.compathead td {
font-weight: bold;
border-bottom: 2px solid #bfcfff;
}
tr.compathead td.compatos {
vertical-align: top;
td.compatname, td.compatver {
width: 10%;
}
table.compat td.compatcpu {
width: 18%;
border-right: 2px solid #bfcfff;
td.compatbits {
width: 5%;
}
td.compatos {
td.compatx {
width: 21%;
vertical-align: middle;
}
td.compatno {
background-color: #d0d0d0;
}
</style>
</head>
@@ -95,62 +90,204 @@ For the impatient (on POSIX systems):
<pre class="code">
make &amp;&amp; sudo make install
</pre>
<h2 id="req">Requirements</h2>
<h3 id="systems">Systems</h3>
<p>
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:
LuaJIT currently builds out-of-the box on most systems:
</p>
<table class="compat">
<tr class="compathead">
<td class="compatcpu">CPU / OS</td>
<td class="compatos"><a href="#posix">Linux</a> or<br><a href="#android">Android</a></td>
<td class="compatos"><a href="#posix">*BSD, Other</a></td>
<td class="compatos"><a href="#posix">macOS 10.4+</a> or<br><a href="#ios">iOS 3.0+</a></td>
<td class="compatos"><a href="#windows">Windows 7<br>or later</a></td>
<td class="compatname">OS</td>
<td class="compatver">Min. Version</td>
<td class="compatx">Requirements</td>
<td class="compatx">LuaJIT Versions</td>
</tr>
<tr class="odd separate">
<td class="compatcpu">x86 (32 bit)</td>
<td class="compatos">GCC 4.2+</td>
<td class="compatos">GCC 4.2+</td>
<td class="compatos">XCode 5.0+<br>Clang</td>
<td class="compatos">MSVC<br>MinGW, Cygwin</td>
<td class="compatname"><a href="#windows">Windows</a></td>
<td class="compatver">7</td>
<td class="compatx">x86 or x64, ARM64: TBA</td>
<td class="compatx">v2.0 &ndash;</td>
</tr>
<tr class="even">
<td class="compatcpu">x64 (64 bit)</td>
<td class="compatos">GCC 4.2+</td>
<td class="compatos">GCC 4.2+<br>ORBIS (<a href="#ps4">PS4</a>)</td>
<td class="compatos">XCode 5.0+<br>Clang</td>
<td class="compatos">MSVC<br>Durango (<a href="#xboxone">Xbox One</a>)</td>
<td class="compatname"><a href="#posix">Linux</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">&nbsp;</td>
<td class="compatx">v2.0 &ndash;</td>
</tr>
<tr class="odd">
<td class="compatcpu"><a href="#cross2">ARMv5+<br>ARM9E+</a></td>
<td class="compatos">GCC 4.2+</td>
<td class="compatos">GCC 4.2+<br>PSP2 (<a href="#psvita">PS VITA</a>)</td>
<td class="compatos">XCode 5.0+<br>Clang</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatname"><a href="#posix">*BSD</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">&nbsp;</td>
<td class="compatx">v2.0 &ndash;</td>
</tr>
<tr class="even">
<td class="compatcpu"><a href="#cross2">ARM64<br>ARM64be</a></td>
<td class="compatos">GCC 4.8+</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatos">XCode 6.0+<br>Clang 3.5+</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatname"><a href="#posix">macOS (OSX)</a></td>
<td class="compatver">10.4</td>
<td class="compatx">&nbsp;</td>
<td class="compatx">v2.1 &ndash;</td>
</tr>
<tr class="odd">
<td class="compatcpu"><a href="#cross2">PPC</a></td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos">GCC 4.3+<br>GCC 4.1 (<a href="#ps3">PS3</a>)</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
<td class="compatname"><a href="#posix">POSIX</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">mmap, dlopen</td>
<td class="compatx">v2.0 &ndash;</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 &ndash;</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 &ndash;</td>
</tr>
<tr class="even separate">
<td class="compatname"><a href="#consoles">PS3</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">PS3 SDK</td>
<td class="compatx">v2.0 &ndash; v2.1 EOL</td>
</tr>
<tr class="odd">
<td class="compatname"><a href="#consoles">PS4</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">PS4 SDK (ORBIS)</td>
<td class="compatx">v2.0 &ndash;</td>
</tr>
<tr class="even">
<td class="compatcpu"><a href="#cross2">MIPS32<br>MIPS64<br>MIPS64r6</a></td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos">GCC 4.3+</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatos compatno">&nbsp;</td>
<td class="compatname"><a href="#consoles">PS5</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">PS5 SDK (PROSPERO)</td>
<td class="compatx">v2.1 &ndash;</td>
</tr>
<tr class="odd">
<td class="compatname"><a href="#consoles">PS Vita</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">PS Vita SDK (PSP2)</td>
<td class="compatx">v2.0 &ndash; v2.1 EOL</td>
</tr>
<tr class="even">
<td class="compatname"><a href="#consoles">Xbox 360</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">Xbox 360 SDK (XEDK)</td>
<td class="compatx">v2.0 &ndash; v2.1 EOL</td>
</tr>
<tr class="odd">
<td class="compatname"><a href="#consoles">Xbox One</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">Xbox One SDK (DURANGO)</td>
<td class="compatx">v2.1 &ndash;</td>
</tr>
<tr class="even">
<td class="compatname"><a href="#consoles">Nintendo Switch</a></td>
<td class="compatver">&nbsp;</td>
<td class="compatx">NintendoSDK + NX Addon</td>
<td class="compatx">v2.1 &ndash;</td>
</tr>
</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">&nbsp;</td>
<td class="compatx">v2.0 &ndash;</td>
</tr>
<tr class="even">
<td class="compatname">x64</td>
<td class="compatbits">64</td>
<td class="compatx">&nbsp;</td>
<td class="compatx">&nbsp;</td>
<td class="compatx">v2.0 &ndash;</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 &ndash;</td>
</tr>
<tr class="even">
<td class="compatname">ARM64</td>
<td class="compatbits">64</td>
<td class="compatx">&nbsp;</td>
<td class="compatx">ARM64le + ARM64be</td>
<td class="compatx">v2.1 &ndash;</td>
</tr>
<tr class="odd">
<td class="compatname">PPC32</td>
<td class="compatbits">32</td>
<td class="compatx">&nbsp;</td>
<td class="compatx">hard-fp + soft-fp</td>
<td class="compatx">v2.0 &ndash; 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">&nbsp;</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 &ndash; r5</td>
<td class="compatx">hard-fp + soft-fp</td>
<td class="compatx">v2.0 &ndash;</td>
</tr>
<tr class="even">
<td class="compatname">MIPS64</td>
<td class="compatbits">64</td>
<td class="compatx">MIPS64r1 &ndash; r5</td>
<td class="compatx">hard-fp + soft-fp</td>
<td class="compatx">v2.1 &ndash;</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">&nbsp;</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>
<p>
@@ -191,7 +328,7 @@ The recommended way to fetch the latest version is to do a pull from
the git repository.
</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
to this directory. Now unpack the archive and change to the newly created
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
make CROSS=$NDKCROSS \
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
# 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
make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
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
</pre>
<p>
@@ -446,8 +583,7 @@ make DEFAULT_CC=clang CROSS="$(dirname $ICC)/" \
<h3 id="consoles">Cross-compiling for consoles</h3>
<p>
Building LuaJIT for consoles requires both a supported host compiler
(x86 or x64) and a cross-compiler (to PPC or ARM) from the official
console SDK.
(x86 or x64) and a cross-compiler from the official console SDK.
</p>
<p>
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-
</pre>
<p>
To cross-compile for <b id="ps4">PS4</b> from a Windows host,
open a "Visual Studio .NET Command Prompt" (64&nbsp;bit host compiler),
<tt>cd</tt> to the directory where you've unpacked the sources and
run the following commands:
To cross-compile for the other consoles from a Windows host, open a
"Native Tools Command Prompt for VS". You need to choose either the 32
or the 64&nbsp;bit version of the host compiler to match the target.
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>
<pre class="code">
cd src
ps4build
</pre>
<table class="compat">
<tr class="compathead">
<td class="compatname">Console</td>
<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>
To cross-compile for <b id="psvita">PS Vita</b> from a Windows host,
open a "Visual Studio .NET Command Prompt" (32&nbsp;bit host compiler),
<tt>cd</tt> to the directory where you've unpacked the sources and
run the following commands:
Please check out the comments in the corresponding <tt>*.bat</tt>
file for more options.
</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&nbsp;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&nbsp;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>
<p>
@@ -548,7 +697,7 @@ allocator from your system (no support for this on 64&nbsp;bit architectures).</
of calling <tt>luaopen_base</tt> etc. directly.</li>
<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.
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>
<li>The <tt>bit.*</tt> module for bitwise operations
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
of the Makefiles. And please do not hand-pick files for your packages &mdash;
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>
The build system uses GNU make and auto-detects most settings based on
+1 -1
View File
@@ -162,7 +162,7 @@ LuaJIT is Copyright &copy; 2005-2022 Mike Pall, released under the
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
</table>
<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 class="feature compiler">
<tr><td>GCC</td><td>Clang<br>LLVM</td><td>MSVC</td></tr>
+3 -2
View File
@@ -111,6 +111,7 @@ are accepted:
<li><tt>-t type</tt> &mdash; Set output file type (default: auto-detect from output name).</li>
<li><tt>-a arch</tt> &mdash; Override architecture for object files (default: native).</li>
<li><tt>-o os</tt> &mdash; Override OS for object files (default: native).</li>
<li><tt>-F name</tt> &mdash; Override filename (default: input filename).</li>
<li><tt>-e chunk</tt> &mdash; Use chunk string as input.</li>
<li><tt>-</tt> (a single minus sign) &mdash; Use stdin as input and/or stdout as output.</li>
</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
read the comment block at the start of their 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
systems (replace XX.YY.ZZ by the installed version).
</p>
@@ -216,7 +217,7 @@ to a specific value.
You can either use this option multiple times (like <tt>-Ocse
-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
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
overrides all earlier flags.
</p>
+1 -1
View File
@@ -83,7 +83,7 @@ Known incompatibilities and issues in LuaJIT&nbsp;2.0:
<ul>
<li>
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
demonstrable need is shown.
</li>
+8 -6
View File
@@ -158,10 +158,10 @@ void dasm_setup(Dst_DECL, const void *actionlist)
#ifdef DASM_CHECKS
#define CK(x, st) \
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) \
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
#define CK(x, 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 m = 1ULL, a, b, c;
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);
if (c) {
w = dasm_ffs(c) - xa;
@@ -406,7 +408,7 @@ int dasm_link(Dst_DECL, size_t *szp)
#ifdef DASM_CHECKS
#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
#define CK(x, st) ((void)0)
#endif
@@ -438,7 +440,7 @@ int dasm_encode(Dst_DECL, void *buffer)
n = DASM_EXTERN(Dst, (unsigned char *)cp, (ins&2047), !(ins&2048));
goto patchrel;
case DASM_ALIGN:
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xd503201f;
break;
case DASM_REL_LG:
if (n < 0) {
@@ -554,7 +556,7 @@ int dasm_checkstep(Dst_DECL, int secmatch)
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
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;
}
#endif
+4 -4
View File
@@ -248,7 +248,7 @@ local map_cond = {
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
local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
if not tname then
@@ -281,7 +281,7 @@ local function parse_reg(expr, shift)
elseif parse_reg_type ~= vrt then
werror("register size mismatch")
end
if shift then waction("VREG", shift, vreg) end
if not no_vreg then waction("VREG", shift, vreg) end
return 0
end
werror("bad register name `"..expr.."'")
@@ -638,7 +638,7 @@ local function alias_bfx(p)
end
local function alias_bfiz(p)
parse_reg(p[1], 0)
parse_reg(p[1], 0, true)
if parse_reg_type == "w" then
p[3] = "#(32-("..p[3]:sub(2).."))%32"
p[4] = "#("..p[4]:sub(2)..")-1"
@@ -649,7 +649,7 @@ local function alias_bfiz(p)
end
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)
if parse_reg_type == "w" then
p[3] = "#(32-("..sh.."))%32"
+4 -4
View File
@@ -155,10 +155,10 @@ void dasm_setup(Dst_DECL, const void *actionlist)
#ifdef DASM_CHECKS
#define CK(x, st) \
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) \
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
#define CK(x, st) ((void)0)
#define CKPL(kind, st) ((void)0)
@@ -314,7 +314,7 @@ int dasm_link(Dst_DECL, size_t *szp)
#ifdef DASM_CHECKS
#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
#define CK(x, st) ((void)0)
#endif
@@ -417,7 +417,7 @@ int dasm_checkstep(Dst_DECL, int secmatch)
}
if (D->status == DASM_S_OK && secmatch >= 0 &&
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;
}
#endif
+10
View File
@@ -18,8 +18,10 @@
#include "lj_obj.h"
#include "lj_gc.h"
#include "lj_bc.h"
#if LJ_HASJIT
#include "lj_ir.h"
#include "lj_ircall.h"
#endif
#include "lj_frame.h"
#include "lj_dispatch.h"
#if LJ_HASFFI
@@ -250,6 +252,7 @@ BCDEF(BCNAME)
NULL
};
#if LJ_HASJIT
const char *const ir_names[] = {
#define IRNAME(name, m, m1, m2) #name,
IRDEF(IRNAME)
@@ -290,7 +293,9 @@ static const char *const trace_errors[] = {
#include "lj_traceerr.h"
NULL
};
#endif
#if LJ_HASJIT
static const char *lower(char *buf, const char *s)
{
char *p = buf;
@@ -301,6 +306,7 @@ static const char *lower(char *buf, const char *s)
*p = '\0';
return buf;
}
#endif
/* Emit C source code for bytecode-related definitions. */
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. */
static void emit_vmdef(BuildCtx *ctx)
{
#if LJ_HASJIT
char buf[80];
#endif
int i;
fprintf(ctx->fp, "-- This is a generated file. DO NOT EDIT!\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]);
fprintf(ctx->fp, "\",\n\n");
#if LJ_HASJIT
fprintf(ctx->fp, "irnames = \"");
for (i = 0; ir_names[i]; i++) fprintf(ctx->fp, "%-6s", ir_names[i]);
fprintf(ctx->fp, "\",\n\n");
@@ -355,6 +364,7 @@ static void emit_vmdef(BuildCtx *ctx)
for (i = 0; trace_errors[i]; i++)
fprintf(ctx->fp, "\"%s\",\n", trace_errors[i]);
fprintf(ctx->fp, "},\n\n");
#endif
}
/* -- Argument parsing ---------------------------------------------------- */
+7
View File
@@ -5,6 +5,7 @@
#include "buildvm.h"
#include "lj_obj.h"
#if LJ_HASJIT
#include "lj_ir.h"
/* Context for the folding hash table generator. */
@@ -226,4 +227,10 @@ void emit_fold(BuildCtx *ctx)
makehash(ctx);
}
#else
void emit_fold(BuildCtx *ctx)
{
UNUSED(ctx);
}
#endif
+63 -38
View File
@@ -4,42 +4,67 @@ static const int libbc_endian = 0;
static const uint8_t libbc_code[] = {
#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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,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,
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,
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,
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,
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,
6,252,127,76,4,2,0,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,
220,203,178,130,4,
/* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20,
198,190,199,252,3,
/* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
/* table.foreachi */ 0,2,10,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,
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,
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,
BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0,
/* table.foreach */ 0,2,11,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI,
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,
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,
BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15,
/* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
/* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0,
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,
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
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,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,
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,
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,
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,
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,
6,252,127,76,4,2,0,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,
220,203,178,130,4,
/* math.rad */ 0,1,2,0,0,1,2,BC_MULVN,1,0,0,BC_RET1,1,2,0,243,244,148,165,20,
198,190,199,252,3,
/* string.len */ 0,1,2,0,0,0,3,BC_ISTYPE,0,5,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
/* table.foreachi */ 0,2,9,0,0,0,15,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,
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,
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,
BC_RET1,6,2,0,BC_FORL,2,248,127,BC_RET0,0,1,0,
/* table.foreach */ 0,2,10,0,0,1,16,BC_ISTYPE,0,12,0,BC_ISTYPE,1,9,0,BC_KPRI,
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,
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,
BC_ITERN,5,3,3,BC_ITERL,5,247,127,BC_RET0,0,1,0,1,255,255,249,255,15,
/* table.getn */ 0,1,2,0,0,0,3,BC_ISTYPE,0,12,0,BC_LEN,1,0,0,BC_RET1,1,2,0,
/* table.remove */ 0,2,10,0,0,2,30,BC_ISTYPE,0,12,0,BC_LEN,2,0,0,BC_ISNEP,1,0,
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,
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
0
};
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},
{"table_foreachi",69},
{"table_foreach",136},
{"table_getn",207},
{"table_remove",226},
{"table_move",355},
{NULL,502}
{"table_getn",213},
{"table_remove",232},
{"table_move",361},
{NULL,508}
};
+40 -12
View File
@@ -55,7 +55,7 @@ local function transform_lua(code)
end)
code = string.gsub(code, "PAIRS%((.-)%)", function(var)
fixup.PAIRS = true
return format("nil, %s, 0", var)
return format("nil, %s, 0x4dp80", var)
end)
return "return "..code, fixup
end
@@ -79,9 +79,11 @@ local name2itype = {
str = 5, func = 9, tab = 12, int = 14, num = 15
}
local BC = {}
local BC, BCN = {}, {}
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
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
@@ -96,6 +98,7 @@ local function fixup_dump(dump, fixup)
p = read_uleb128(p)
p = read_uleb128(p)
p, sizebc = read_uleb128(p)
local startbc = tonumber(p - start)
local rawtab = {}
for i=0,sizebc-1 do
local op = p[xop]
@@ -129,7 +132,10 @@ local function fixup_dump(dump, fixup)
end
p = p + 4
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
local function find_defs(src)
@@ -149,24 +155,46 @@ local function gen_header(defs)
local function w(x) t[#t+1] = x end
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")
local s = ""
for _,name in ipairs(defs) do
s = s .. defs[name]
local s, sb = "", ""
for i,name in ipairs(defs) do
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
w("static const uint8_t libbc_code[] = {\n")
local n = 0
for i=1,#s do
local x = string.byte(s, i)
w(x); w(",")
n = n + (x < 10 and 2 or (x < 100 and 3 or 4))
if n >= 75 then n = 0; w("\n") end
local xb = string.byte(sb, i)
if xb == 255 then
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
w("0\n};\n\n")
w("\n0\n};\n\n")
w("static const struct { const char *name; int ofs; } libbc_map[] = {\n")
local m = 0
for _,name in ipairs(defs) do
w('{"'); w(name); w('",'); w(m) w('},\n')
m = m + #defs[name]
m = m + #defs[name].dump
end
w("{NULL,"); w(m); w("}\n};\n\n")
return table.concat(t)
+7
View File
@@ -327,6 +327,12 @@ local function rename_tokens2(src)
return gsub(src, "ZY([%w_]+)", "union %1")
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 nodes, list = {}, {}
local pos, len = 1, #src
@@ -425,5 +431,6 @@ src = rename_tokens1(src)
src = func_collect(src)
src = rename_tokens2(src)
src = restore_strings(src)
src = fix_bugs_and_warnings(src)
src = merge_header(src, license)
io.write(src)
+3 -2
View File
@@ -1639,6 +1639,7 @@ lua_number2int(k,n);
if(luai_numeq(cast_num(k),nvalue(key)))
return luaH_getnum(t,k);
}
/*fallthrough*/
default:{
Node*n=mainposition(t,key);
do{
@@ -2905,8 +2906,8 @@ if(sep>=0){
read_long_string(ls,seminfo,sep);
return TK_STRING;
}
else if(sep==-1)return'[';
else luaX_lexerror(ls,"invalid long string delimiter",TK_STRING);
else if (sep!=-1)luaX_lexerror(ls,"invalid long string delimiter",TK_STRING);
return'[';
}
case'=':{
next(ls);
+38 -11
View File
@@ -33,6 +33,7 @@ Save LuaJIT bytecode: luajit -b[options] input output
-t type Set output file type (default: auto-detect from output name).
-a arch Override architecture 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.
-- Stop handling options.
- Use stdin as input and/or stdout as output.
@@ -49,10 +50,22 @@ local function check(ok, ...)
os.exit(1)
end
local function readfile(input)
local function readfile(ctx, input)
if type(input) == "function" then return input end
if input == "-" then input = nil end
return check(loadfile(input))
if ctx.filename then
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
local function savefile(name, mode)
@@ -456,18 +469,18 @@ typedef struct {
uint32_t value;
} mach_nlist;
typedef struct {
uint32_t strx;
int32_t strx;
uint8_t type, sect;
uint16_t desc;
uint64_t value;
} mach_nlist_64;
typedef struct
{
uint32_t magic, nfat_arch;
int32_t magic, nfat_arch;
} mach_fat_header;
typedef struct
{
uint32_t cputype, cpusubtype, offset, size, align;
int32_t cputype, cpusubtype, offset, size, align;
} mach_fat_arch;
typedef struct {
struct {
@@ -501,6 +514,18 @@ typedef struct {
mach_nlist sym_entry;
uint8_t space[4096];
} 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 isfat, is64, align, mobj = false, false, 4, "mach_obj"
@@ -509,7 +534,7 @@ typedef struct {
elseif ctx.arch == "arm" then
isfat, mobj = true, "mach_fat_obj"
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
check(ctx.arch == "x86", "unsupported architecture for OSX")
end
@@ -592,13 +617,13 @@ end
------------------------------------------------------------------------------
local function bclist(input, output)
local f = readfile(input)
local function bclist(ctx, input, output)
local f = readfile(ctx, input)
require("jit.bc").dump(f, savefile(output, "w"), true)
end
local function bcsave(ctx, input, output)
local f = readfile(input)
local f = readfile(ctx, input)
local s = string.dump(f, ctx.strip)
local t = ctx.type
if not t then
@@ -651,6 +676,8 @@ local function docmd(...)
ctx.arch = checkarg(tremove(arg, n), map_arch, "architecture")
elseif opt == "o" then
ctx.os = checkarg(tremove(arg, n), map_os, "OS name")
elseif opt == "F" then
ctx.filename = "@"..tremove(arg, n)
else
usage()
end
@@ -662,7 +689,7 @@ local function docmd(...)
end
if list then
if #arg == 0 or #arg > 2 then usage() end
bclist(arg[1], arg[2] or "-")
bclist(ctx, arg[1], arg[2] or "-")
else
if #arg ~= 2 then usage() end
bcsave(ctx, arg[1], arg[2])
+5 -1
View File
@@ -76,6 +76,8 @@ LJLIB_CF(buffer_method_skip) LJLIB_REC(.)
MSize len = sbufxlen(sbx);
if (n < len) {
sbx->r += n;
} else if (sbufiscow(sbx)) {
sbx->r = sbx->w;
} else {
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));
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);
return narg-1;
}
@@ -321,6 +323,7 @@ LJLIB_CF(buffer_new)
setgcref(sbx->dict_str, obj2gco(dict_str));
setgcref(sbx->dict_mt, obj2gco(dict_mt));
if (sz > 0) lj_buf_need2((SBuf *)sbx, sz);
lj_gc_check(L);
return 1;
}
@@ -337,6 +340,7 @@ LJLIB_CF(buffer_decode) LJLIB_REC(.)
GCstr *str = lj_lib_checkstrx(L, 1);
setnilV(L->top++);
lj_serialize_decode(L, L->top-1, str);
lj_gc_check(L);
return 1;
}
+2 -2
View File
@@ -639,7 +639,7 @@ LJLIB_CF(ffi_alignof) LJLIB_REC(ffi_xof FF_ffi_alignof)
CTState *cts = ctype_cts(L);
CTypeID id = ffi_checkctype(L, cts, NULL);
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));
return 1;
}
@@ -770,7 +770,7 @@ LJLIB_CF(ffi_metatype)
CTypeID id = ffi_checkctype(L, cts, NULL);
GCtab *mt = lj_lib_checktab(L, 2);
GCtab *t = cts->miscmap;
CType *ct = ctype_get(cts, id); /* Only allow raw types. */
CType *ct = ctype_raw(cts, id);
TValue *tv;
GCcdata *cd;
if (!(ctype_isstruct(ct->info) || ctype_iscomplex(ct->info) ||
+1 -1
View File
@@ -439,7 +439,7 @@ LJLIB_CF(io_popen)
LJLIB_CF(io_tmpfile)
{
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;
#else
iof->fp = tmpfile();
+1 -1
View File
@@ -76,7 +76,7 @@ LJLIB_CF(os_rename)
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);
return 0;
#else
+1 -1
View File
@@ -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)
{
#if defined(RTLD_DEFAULT)
#if defined(RTLD_DEFAULT) && !defined(NO_RTLD_DEFAULT)
if (lib == NULL) lib = RTLD_DEFAULT;
#elif LJ_TARGET_OSX || LJ_TARGET_BSD
if (lib == NULL) lib = (void *)(intptr_t)-2;
+1 -1
View File
@@ -330,7 +330,7 @@ static void *mmap_plain(size_t size)
#define CALL_MMAP(prng, size) mmap_plain(size)
#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>
+1 -1
View File
@@ -779,7 +779,7 @@ LUA_API void lua_concat(lua_State *L, int n)
L->top -= n;
break;
}
n -= (int)(L->top - top);
n -= (int)(L->top - (top - 2*LJ_FR2));
L->top = top+2;
lj_vm_call(L, top, 1+1);
L->top -= 1+LJ_FR2;
+16 -2
View File
@@ -83,7 +83,7 @@
#define LUAJIT_OS LUAJIT_OS_OSX
#elif (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__NetBSD__) || defined(__OpenBSD__) || \
defined(__DragonFly__)) && !defined(__ORBIS__)
defined(__DragonFly__)) && !defined(__ORBIS__) && !defined(__PROSPERO__)
#define LUAJIT_OS LUAJIT_OS_BSD
#elif (defined(__sun__) && defined(__svr4__))
#define LJ_TARGET_SOLARIS 1
@@ -139,6 +139,13 @@
#define NULL ((void*)0)
#endif
#ifdef __PROSPERO__
#define LJ_TARGET_PS5 1
#define LJ_TARGET_CONSOLE 1
#undef NULL
#define NULL ((void*)0)
#endif
#ifdef __psp2__
#define LJ_TARGET_PSVITA 1
#define LJ_TARGET_CONSOLE 1
@@ -155,6 +162,13 @@
#define LJ_TARGET_GC64 1
#endif
#ifdef __NX__
#define LJ_TARGET_NX 1
#define LJ_TARGET_CONSOLE 1
#undef NULL
#define NULL ((void*)0)
#endif
#ifdef _UWP
#define LJ_TARGET_UWP 1
#if LUAJIT_TARGET == LUAJIT_ARCH_X64
@@ -634,7 +648,7 @@ extern void *LJ_WIN_LOADLIBA(const char *path);
#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
#endif
+3 -6
View File
@@ -847,7 +847,8 @@ static void ra_destpair(ASMState *as, IRIns *ir)
if (destlo == RID_RETHI) {
if (desthi == RID_RETLO) {
#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
emit_movrr(as, irx, RID_RETHI, RID_TMP);
emit_movrr(as, irx, RID_RETLO, RID_RETHI);
@@ -1670,7 +1671,6 @@ static void asm_loop(ASMState *as)
#if !LJ_SOFTFP32
#if !LJ_TARGET_X86ORX64
#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
static void asm_pow(ASMState *as, IRIns *ir)
@@ -1681,10 +1681,7 @@ static void asm_pow(ASMState *as, IRIns *ir)
IRCALL_lj_carith_powu64);
else
#endif
if (irt_isnum(IR(ir->op2)->t))
asm_callid(as, ir, IRCALL_pow);
else
asm_fppowi(as, ir);
asm_callid(as, ir, IRCALL_pow);
}
static void asm_div(ASMState *as, IRIns *ir)
+6 -1
View File
@@ -1250,7 +1250,12 @@ dotypecheck:
}
}
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 !LJ_SOFTFP
+1 -1
View File
@@ -1209,7 +1209,7 @@ dotypecheck:
lj_assertA(irt_isinteger(t) || irt_isnum(t),
"bad SLOAD type %d", irt_type(t));
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)) {
emit_n(as, (A64I_CMNx^A64I_K12) | A64F_U12(1), tmp);
} else if (irt_ispri(t)) {
+21 -2
View File
@@ -1577,7 +1577,7 @@ dotypecheck:
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
emit_tsi(as, MIPSI_SLTIU, RID_TMP, type, (int32_t)LJ_TISNUM);
} 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);
}
}
@@ -1595,6 +1595,10 @@ dotypecheck:
if (irt_ispri(t)) {
asm_guard(as, MIPSI_BNE, type,
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 {
if (irt_isnum(t)) {
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));
#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
}
checkmclim(as);
+6 -1
View File
@@ -1169,7 +1169,12 @@ dotypecheck:
} else {
if ((ir->op2 & IRSLOAD_TYPECHECK)) {
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;
}
if (ra_hasreg(dest)) emit_tai(as, PPCI_LWZ, dest, base, ofs);
+5 -20
View File
@@ -485,7 +485,8 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow)
asm_fusexref(as, ir->op1, xallow);
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);
as->mrm.ofs += 8 * ir->op2;
return RID_MRM;
@@ -1768,14 +1769,11 @@ static void asm_sload(ASMState *as, IRIns *ir)
if ((ir->op2 & IRSLOAD_TYPECHECK)) {
/* Need type check, even if the load result is unused. */
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),
"bad SLOAD type %d", irt_type(t));
#if LJ_GC64
emit_u32(as, LJ_TISNUM << 15);
#else
emit_u32(as, LJ_TISNUM);
#endif
emit_u32(as, (ir->op2 & IRSLOAD_KEYINDEX) ? LJ_KEYINDEX :
LJ_GC64 ? (LJ_TISNUM << 15) : LJ_TISNUM);
emit_rmro(as, XO_ARITHi, XOg_CMP, base, ofs+4);
#if LJ_GC64
} else if (irt_isnil(t)) {
@@ -2017,19 +2015,6 @@ static void asm_ldexp(ASMState *as, IRIns *ir)
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)
{
IRIns *irl = IR(ir->op1);
+1 -1
View File
@@ -66,7 +66,7 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
lj_err_mem(sbufL(sbx));
if (len + sz > sbufsz(sbx)) { /* Must grow. */
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. */
buf_grow((SBuf *)sbx, sbuflen(sbx) + sz); /* Not sbufxlen! */
return sbx->w;
+1 -1
View File
@@ -25,7 +25,7 @@
#include <dlfcn.h>
#include <stdio.h>
#if defined(RTLD_DEFAULT)
#if defined(RTLD_DEFAULT) && !defined(NO_RTLD_DEFAULT)
#define CLIB_DEFHANDLE RTLD_DEFAULT
#elif LJ_TARGET_OSX || LJ_TARGET_BSD
#define CLIB_DEFHANDLE ((void *)(intptr_t)-2)
+1 -1
View File
@@ -468,7 +468,7 @@ static void cp_expr_sizeof(CPState *cp, CPValue *k, int wantsz)
} else {
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 (sz != CTSIZE_INVALID)
k->u32 = sz;
+8
View File
@@ -333,6 +333,14 @@ CTInfo lj_ctype_info(CTState *cts, CTypeID id, CTSize *szp)
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. */
cTValue *lj_ctype_meta(CTState *cts, CTypeID id, MMS mm)
{
+1
View File
@@ -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_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_raw(CTState *cts, CTypeID id, CTSize *szp);
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_int64(lua_State *L, uint64_t n, int isunsigned);
+2 -2
View File
@@ -89,7 +89,7 @@ typedef uint16_t HotCount;
typedef struct GG_State {
lua_State L; /* Main thread. */
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. */
uint8_t align1[(16-sizeof(global_State))&15];
#endif
@@ -99,7 +99,7 @@ typedef struct GG_State {
#if LJ_HASJIT
jit_State J; /* JIT state. */
HotCount hotcount[HOTCOUNT_SIZE]; /* Hot counters. */
#if LJ_TARGET_ARM
#if LJ_TARGET_ARM && !LJ_TARGET_NX
/* Ditto for J. */
uint8_t align2[(16-sizeof(jit_State)-sizeof(HotCount)*HOTCOUNT_SIZE)&15];
#endif
+16 -8
View File
@@ -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)
{
J->base[0] = lj_opt_narrow_pow(J, J->base[0], J->base[1],
&rd->argv[0], &rd->argv[1]);
J->base[0] = lj_opt_narrow_arith(J, J->base[0], J->base[1],
&rd->argv[0], &rd->argv[1], IR_POW);
UNUSED(rd);
}
@@ -1222,6 +1222,12 @@ static void LJ_FASTCALL recff_buffer_method_put(jit_State *J, RecordFFData *rd)
TRef tr;
ptrdiff_t arg;
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++) {
if (tref_isstr(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,
tref_isnum(tr) ? IRTOSTR_NUM : IRTOSTR_INT));
} else if (tref_isudata(tr)) {
TRef ud2 = recff_sbufx_check(J, rd, arg);
TRef trr = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_R);
TRef trw = recff_sbufx_get_ptr(J, ud2, IRFL_SBUF_W);
TRef trr = recff_sbufx_get_ptr(J, tr, IRFL_SBUF_R);
TRef trw = recff_sbufx_get_ptr(J, tr, IRFL_SBUF_W);
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);
} else {
recff_nyiu(J, rd);
@@ -1258,15 +1262,19 @@ static void LJ_FASTCALL recff_buffer_method_get(jit_State *J, RecordFFData *rd)
TRef tr;
ptrdiff_t arg;
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++) {
TRef len = recff_sbufx_len(J, trr, trw);
if (tref_isnil(tr)) {
J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len);
trr = trw;
} else {
TRef trn = recff_sbufx_checkint(J, rd, arg+1);
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);
J->base[arg] = emitir(IRT(IR_XSNEW, IRT_STR), trr, len);
trr = tru; /* Doing the ADD before the SNEW generates better code. */
+3
View File
@@ -700,9 +700,12 @@ static size_t gc_onestep(lua_State *L)
}
case GCSfinalize:
if (gcref(g->gc.mmudata) != NULL) {
GCSize old = g->gc.total;
if (tvref(g->jit_base)) /* Don't call finalizers on trace. */
return LJ_MAX_MEM;
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)
g->gc.estimate -= GCFINALIZECOST;
return GCFINALIZECOST;
-1
View File
@@ -217,7 +217,6 @@ typedef struct CCallInfo {
_(FPMATH, sqrt, 1, N, NUM, XA_FP) \
_(ANY, log, 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, atan2, 2, N, NUM, XA2_FP) \
_(ANY, ldexp, 2, N, NUM, XA_FP) \
-1
View File
@@ -145,7 +145,6 @@ LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
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_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);
/* Optimization passes. */
+8
View File
@@ -7,6 +7,7 @@
#define _LJ_JIT_H
#include "lj_obj.h"
#if LJ_HASJIT
#include "lj_ir.h"
/* -- JIT engine flags ---------------------------------------------------- */
@@ -371,6 +372,7 @@ enum {
#endif
LJ_K64__MAX,
};
#define LJ_K64__USED (LJ_TARGET_X86ORX64 || LJ_TARGET_MIPS)
enum {
#if LJ_TARGET_X86ORX64
@@ -389,6 +391,7 @@ enum {
#endif
LJ_K32__MAX
};
#define LJ_K32__USED (LJ_TARGET_X86ORX64 || LJ_TARGET_PPC || LJ_TARGET_MIPS)
/* Get 16 byte aligned pointer to SIMD constant. */
#define LJ_KSIMD(J, n) \
@@ -443,9 +446,13 @@ typedef struct jit_State {
int32_t framedepth; /* Current frame depth. */
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. */
#endif
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. */
#endif
IRIns *irbuf; /* Temp. IR instruction buffer. Biased with REF_BIAS. */
IRRef irtoplim; /* Upper limit of instuction buffer (biased). */
@@ -516,5 +523,6 @@ typedef struct jit_State {
#else
#define lj_assertJ(c, ...) ((void)J)
#endif
#endif
#endif
+2 -1
View File
@@ -168,7 +168,7 @@ static void mcode_protect(jit_State *J, int prot)
#define MCPROT_RUN MCPROT_RX
/* 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;
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));
panic(L);
}
exit(EXIT_FAILURE);
}
/* Change protection of MCode area. */
+2 -1
View File
@@ -511,7 +511,7 @@ typedef struct GCtab {
} 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 nextnode(n) (mref((n)->next, Node))
#if LJ_GC64
@@ -845,6 +845,7 @@ static LJ_AINLINE void *lightudV(global_State *g, cTValue *o)
uint64_t seg = lightudseg(u);
uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
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);
return (void *)(((uint64_t)segmap[seg] << 32) | lightudlo(u));
}
+13 -60
View File
@@ -236,14 +236,10 @@ LJFOLDF(kfold_fpcall2)
return NEXTFOLD;
}
LJFOLD(POW KNUM KINT)
LJFOLD(POW KNUM KNUM)
LJFOLDF(kfold_numpow)
{
lua_Number a = knumleft;
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);
return lj_ir_knum(J, lj_vm_foldarith(knumleft, knumright, IR_POW - IR_ADD));
}
/* 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 &&
fleft->prev == hdr &&
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;
IR(ref)->op2 = IRBUFHDR_APPEND; /* Modify BUFHDR. */
IR(ref)->op1 = fright->op1;
return ref;
}
/* 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);
/* For now only handle single string.reverse .lower .upper .rep. */
if (ir->o == IR_CALLL &&
@@ -1112,61 +1109,17 @@ LJFOLDF(simplify_nummuldiv_negneg)
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)
LJFOLDF(simplify_numpow_xknum)
LJFOLDF(simplify_numpow_k)
{
if (knumright == 0.5) /* x ^ 0.5 ==> sqrt(x) */
return emitir(IRTN(IR_FPMATH), fins->op1, IRFPM_SQRT);
return NEXTFOLD;
}
LJFOLD(POW KNUM any)
LJFOLDF(simplify_numpow_kx)
{
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;
if (knumright == 0.0) /* x ^ 0 ==> 1 */
return lj_ir_knum_one(J); /* Result must be a number, not an int. */
else if (knumright == 1.0) /* x ^ 1 ==> x */
return LEFTFOLD;
else if (knumright == 2.0) /* x ^ 2 ==> x * x */
return emitir(IRTN(IR_MUL), fins->op1, fins->op1);
else
return NEXTFOLD;
}
/* -- Simplify conversions ------------------------------------------------ */
+1 -1
View File
@@ -432,7 +432,7 @@ TRef LJ_FASTCALL lj_opt_fwd_alen(jit_State *J)
fins->op2 = aref->op2; /* Set ALEN 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. */
}
sref = store->prev;
-30
View File
@@ -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);
}
/* 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 ------------------------- */
/* Narrow a single runtime value. */
+1 -1
View File
@@ -400,7 +400,7 @@ static void split_ir(jit_State *J)
hi = split_call_ll(J, hisubst, oir, ir, IRCALL_softfp_div);
break;
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;
case IR_FPMATH:
hi = split_call_l(J, hisubst, oir, ir, IRCALL_lj_vm_floor + ir->op2);
+1 -1
View File
@@ -1554,7 +1554,7 @@ static void fs_fixup_ret(FuncState *fs)
/* Replace with UCLO plus branch. */
fs->bcbase[pc].ins = BCINS_AD(BC_UCLO, 0, offset);
break;
case BC_UCLO:
case BC_FNEW:
return; /* We're done. */
default:
break;
+12 -3
View File
@@ -83,10 +83,14 @@ extern int XNetRandom(void *buf, unsigned int 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);
#elif LJ_TARGET_NX
#include <unistd.h>
#elif LJ_TARGET_WINDOWS || LJ_TARGET_XBOXONE
#define WIN32_LEAN_AND_MEAN
@@ -126,7 +130,7 @@ static PRGR libfunc_rgr;
#endif
#if LJ_TARGET_HAS_GETENTROPY
extern int getentropy(void *buf, size_t len);
extern int getentropy(void *buf, size_t len)
#ifdef __ELF__
__attribute__((weak))
#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)
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)
goto ok;
#elif LJ_TARGET_NX
if (getentropy(rs->u, sizeof(rs->u)) == 0)
goto ok;
#elif LJ_TARGET_UWP || LJ_TARGET_XBOXONE
if (BCryptGenRandom(NULL, (PUCHAR)(rs->u), (ULONG)sizeof(rs->u),
+22 -12
View File
@@ -664,17 +664,24 @@ static LoopEvent rec_itern(jit_State *J, BCReg ra, BCReg rb)
RecordIndex ix;
/* Since ITERN is recorded at the start, we need our own loop detection. */
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) {
lj_record_stop(J, LJ_TRLINK_LOOP, J->cur.traceno); /* Looping trace. */
return LOOPEV_ENTER;
IRRef ref = REF_FIRST + LJ_HASPROFILE;
#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;
lj_snap_add(J); /* Required to make JLOOP the first ins in a side-trace. */
ix.tab = getslot(J, ra-2);
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.keyv, &J->L->base[ra-1]);
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);
if (tref_isk(key)) {
/* Optimize lookup of constant hash keys. */
MSize hslot = (MSize)((char *)ix->oldv - (char *)&noderef(t->node)[0].val);
if (t->hmask > 0 && hslot <= t->hmask*(MSize)sizeof(Node) &&
hslot <= 65535*(MSize)sizeof(Node)) {
GCSize hslot = (GCSize)((char *)ix->oldv-(char *)&noderef(t->node)[0].val);
if (hslot <= t->hmask*(GCSize)sizeof(Node) &&
hslot <= 65535*(GCSize)sizeof(Node)) {
TRef node, kslot, hm;
*rbref = J->cur.nins; /* Mark possible rollback point. */
*rbguard = J->guardemit;
hm = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_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);
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);
}
}
@@ -1954,7 +1961,7 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
emitir(IRTGI(IR_EQ), fr,
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_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++) {
IRType t = itype2irt(&J->L->base[i-1-LJ_FR2-nvararg]);
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)
{
TRef *top = &J->base[topslot];
TValue savetv[5];
TValue savetv[5+LJ_FR2];
BCReg s;
RecordIndex ix;
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 BCMnum: { cTValue *tv = proto_knumtv(J->pt, rc);
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;
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;
@@ -2393,7 +2401,7 @@ void lj_record_ins(jit_State *J)
case BC_POW:
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
rc = rec_mm_arith(J, &ix, MM_pow);
break;
@@ -2657,6 +2665,8 @@ static const BCIns *rec_setup_root(jit_State *J)
J->bc_min = pc;
break;
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");
J->maxslot = ra + bc_b(pc[-1]) - 1;
J->bc_extent = (MSize)(-bc_j(ins))*sizeof(BCIns);
+1 -1
View File
@@ -313,7 +313,7 @@ static BCReg snap_usedef(jit_State *J, uint8_t *udf,
}
/* 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
** of slots and closures. But the number of false positives is quite low.
+5 -1
View File
@@ -672,9 +672,11 @@ static TValue *trace_state(lua_State *L, lua_CFunction dummy, void *ud)
trace_pendpatch(J, 0);
setvmstate(J2G(J), 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 savetv2 = J2G(J)->tmptv2;
TraceNo parent = J->parent;
ExitNo exitno = J->exitno;
setintV(L->top++, J->cur.traceno);
setfuncV(L, L->top++, J->fn);
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)->tmptv2 = savetv2;
J->parent = parent;
J->exitno = exitno;
);
lj_record_ins(J);
break;
-4
View File
@@ -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_ceil_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
#if LJ_TARGET_PPC || LJ_TARGET_ARM64
#define lj_vm_trunc trunc
+3 -35
View File
@@ -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); }
#endif
/* -- Helper functions for generated machine code ------------------------- */
/* -- Helper functions ---------------------------------------------------- */
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
int32_t LJ_FASTCALL lj_vm_modi(int32_t a, int32_t b)
{
@@ -80,40 +82,6 @@ double lj_vm_log2(double a)
}
#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. */
double lj_vm_foldfpm(double x, int fpm)
{
+11 -12
View File
@@ -39,6 +39,7 @@
static lua_State *globalL = NULL;
static const char *progname = LUA_PROGNAME;
static char *empty_argv[2] = { NULL, NULL };
#if !LJ_TARGET_CONSOLE
static void lstop(lua_State *L, lua_Debug *ar)
@@ -78,9 +79,9 @@ static void print_usage(void)
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);
fflush(stderr);
}
@@ -90,7 +91,7 @@ static int report(lua_State *L, int status)
if (status && !lua_isnil(L, -1)) {
const char *msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error object is not a string)";
l_message(progname, msg);
l_message(msg);
lua_pop(L, 1);
}
return status;
@@ -256,9 +257,8 @@ static void dotty(lua_State *L)
lua_getglobal(L, "print");
lua_insert(L, 1);
if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
l_message(progname,
lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
lua_tostring(L, -1)));
l_message(lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
lua_tostring(L, -1)));
}
}
lua_settop(L, 0); /* clear stack */
@@ -310,8 +310,7 @@ static int loadjitmodule(lua_State *L)
lua_getfield(L, -1, "start");
if (lua_isnil(L, -1)) {
nomodule:
l_message(progname,
"unknown luaJIT command or jit.* modules not installed");
l_message("unknown luaJIT command or jit.* modules not installed");
return 1;
}
lua_remove(L, -2); /* Drop module table. */
@@ -516,8 +515,6 @@ static int pmain(lua_State *L)
int argn;
int flags = 0;
globalL = L;
if (argv[0] && argv[0][0]) progname = argv[0];
LUAJIT_VERSION_SYM(); /* Linker-enforced version check. */
argn = collectargs(argv, &flags);
@@ -572,9 +569,11 @@ static int pmain(lua_State *L)
int main(int argc, char **argv)
{
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) {
l_message(argv[0], "cannot create state: not enough memory");
l_message("cannot create state: not enough memory");
return EXIT_FAILURE;
}
smain.argc = argc;
+159
View File
@@ -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
+123
View File
@@ -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
+2
View File
@@ -3988,6 +3988,7 @@ static void emit_asm_debug(BuildCtx *ctx)
"\t.align 3\n"
".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
#endif
#if !LJ_NO_UNWIND
fprintf(ctx->fp, "\t.section .eh_frame,\"a\",%%progbits\n");
fprintf(ctx->fp,
".Lframe1:\n"
@@ -4055,6 +4056,7 @@ static void emit_asm_debug(BuildCtx *ctx)
"\t.byte 0x94\n\t.uleb128 4\n" /* offset x20 */
"\t.align 3\n"
".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
#endif
#endif
break;
#if !LJ_NO_UNWIND
+6 -42
View File
@@ -359,9 +359,6 @@
|.macro sseconst_1, reg, tmp // Synthesize 1.0.
| sseconst_hi reg, tmp, 3ff00000
|.endmacro
|.macro sseconst_m1, reg, tmp // Synthesize -1.0.
| sseconst_hi reg, tmp, bff00000
|.endmacro
|.macro sseconst_2p52, reg, tmp // Synthesize 2^52.
| sseconst_hi reg, tmp, 43300000
|.endmacro
@@ -2530,15 +2527,17 @@ static void build_subroutines(BuildCtx *ctx)
| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
| subsd xmm1, xmm3
| orpd xmm1, xmm2 // Merge sign bit back in.
| sseconst_1 xmm3, RD
| .if mode == 1 // ceil(x)?
| sseconst_m1 xmm2, RD // Must subtract -1 to preserve -0.
| 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)?
| sseconst_1 xmm2, RD
| cmpsd xmm0, xmm1, 1 // x < result?
| andpd xmm0, xmm3
| subsd xmm1, xmm0 // If yes, subtract 1.
| .endif
| andpd xmm0, xmm2
| subsd xmm1, xmm0 // If yes, subtract +-1.
|.endif
| movaps xmm0, xmm1
|1:
@@ -2579,41 +2578,6 @@ static void build_subroutines(BuildCtx *ctx)
| subsd xmm0, xmm1
| 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 --------------------------------------------
|//-----------------------------------------------------------------------
+6 -42
View File
@@ -464,9 +464,6 @@
|.macro sseconst_1, reg, tmp // Synthesize 1.0.
| sseconst_hi reg, tmp, 3ff00000
|.endmacro
|.macro sseconst_m1, reg, tmp // Synthesize -1.0.
| sseconst_hi reg, tmp, bff00000
|.endmacro
|.macro sseconst_2p52, reg, tmp // Synthesize 2^52.
| sseconst_hi reg, tmp, 43300000
|.endmacro
@@ -2989,15 +2986,17 @@ static void build_subroutines(BuildCtx *ctx)
| addsd xmm1, xmm3 // (|x| + 2^52) - 2^52
| subsd xmm1, xmm3
| orpd xmm1, xmm2 // Merge sign bit back in.
| sseconst_1 xmm3, RDa
| .if mode == 1 // ceil(x)?
| sseconst_m1 xmm2, RDa // Must subtract -1 to preserve -0.
| 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)?
| sseconst_1 xmm2, RDa
| cmpsd xmm0, xmm1, 1 // x < result?
| andpd xmm0, xmm3
| subsd xmm1, xmm0 // If yes, subtract 1.
| .endif
| andpd xmm0, xmm2
| subsd xmm1, xmm0 // If yes, subtract +-1.
|.endif
| movaps xmm0, xmm1
|1:
@@ -3038,41 +3037,6 @@ static void build_subroutines(BuildCtx *ctx)
| subsd xmm0, xmm1
| 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 --------------------------------------------
|//-----------------------------------------------------------------------