Update LuaJIT to the latest 2.1.0 source (f3c8569)

This commit is contained in:
Alex Szpakowski
2021-12-03 20:50:23 -04:00
parent 4f24e5473f
commit c3986a9541
216 changed files with 6026 additions and 1838 deletions
+1 -1
View File
@@ -167,7 +167,7 @@ endif()
set(MEGA_ZLIB_VER "1.2.11") set(MEGA_ZLIB_VER "1.2.11")
set(MEGA_LUA51_VER "5.1.5") set(MEGA_LUA51_VER "5.1.5")
set(MEGA_LUAJIT_VER "2.1.0-1d8b747") set(MEGA_LUAJIT_VER "2.1.0-f3c8569")
set(MEGA_LIBOGG_VER "1.3.2") set(MEGA_LIBOGG_VER "1.3.2")
set(MEGA_LIBVORBIS_VER "1.3.5") set(MEGA_LIBVORBIS_VER "1.3.5")
set(MEGA_LIBTHEORA_VER "1.1.1") set(MEGA_LIBTHEORA_VER "1.1.1")
+1 -1
View File
@@ -1,7 +1,7 @@
=============================================================================== ===============================================================================
LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/ LuaJIT -- a Just-In-Time Compiler for Lua. https://luajit.org/
Copyright (C) 2005-2020 Mike Pall. All rights reserved. Copyright (C) 2005-2021 Mike Pall. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+1 -1
View File
@@ -10,7 +10,7 @@
# For MSVC, please follow the instructions given in src/msvcbuild.bat. # For MSVC, please follow the instructions given in src/msvcbuild.bat.
# For MinGW and Cygwin, cd to src and run make with the Makefile there. # For MinGW and Cygwin, cd to src and run make with the Makefile there.
# #
# Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h # Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
############################################################################## ##############################################################################
MAJVER= 2 MAJVER= 2
+1 -1
View File
@@ -5,7 +5,7 @@ LuaJIT is a Just-In-Time (JIT) compiler for the Lua programming language.
Project Homepage: https://luajit.org/ Project Homepage: https://luajit.org/
LuaJIT is Copyright (C) 2005-2020 Mike Pall. LuaJIT is Copyright (C) 2005-2021 Mike Pall.
LuaJIT is free software, released under the MIT license. LuaJIT is free software, released under the MIT license.
See full Copyright Notice in the COPYRIGHT file or in luajit.h. See full Copyright Notice in the COPYRIGHT file or in luajit.h.
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2004-2020 Mike Pall. /* Copyright (C) 2004-2021 Mike Pall.
* *
* You are welcome to use the general ideas of this design for your own sites. * You are welcome to use the general ideas of this design for your own sites.
* But please do not steal the stylesheet, the layout or the color scheme. * But please do not steal the stylesheet, the layout or the color scheme.
+1 -1
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2004-2020 Mike Pall. /* Copyright (C) 2004-2021 Mike Pall.
* *
* You are welcome to use the general ideas of this design for your own sites. * You are welcome to use the general ideas of this design for your own sites.
* But please do not steal the stylesheet, the layout or the color scheme. * But please do not steal the stylesheet, the layout or the color scheme.
+7 -5
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Contact</title> <title>Contact</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -37,6 +37,8 @@
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -87,7 +89,7 @@ xD("fyZKB8xv\"FJytmz8.KAB0u52D")
<h2>Copyright</h2> <h2>Copyright</h2>
<p> <p>
All documentation is All documentation is
Copyright &copy; 2005-2020 Mike Pall. Copyright &copy; 2005-2021 Mike Pall.
</p> </p>
@@ -95,7 +97,7 @@ Copyright &copy; 2005-2020 Mike Pall.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+693
View File
@@ -0,0 +1,693 @@
<!DOCTYPE html>
<html>
<head>
<title>String Buffer Library</title>
<meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
<style type="text/css">
.lib {
vertical-align: middle;
margin-left: 5px;
padding: 0 5px;
font-size: 60%;
border-radius: 5px;
background: #c5d5ff;
color: #000;
}
</style>
</head>
<body>
<div id="site">
<a href="https://luajit.org"><span>Lua<span id="logo">JIT</span></span></a>
</div>
<div id="head">
<h1>String Buffer Library</h1>
</div>
<div id="nav">
<ul><li>
<a href="luajit.html">LuaJIT</a>
<ul><li>
<a href="https://luajit.org/download.html">Download <span class="ext">&raquo;</span></a>
</li><li>
<a href="install.html">Installation</a>
</li><li>
<a href="running.html">Running</a>
</li></ul>
</li><li>
<a href="extensions.html">Extensions</a>
<ul><li>
<a href="ext_ffi.html">FFI Library</a>
<ul><li>
<a href="ext_ffi_tutorial.html">FFI Tutorial</a>
</li><li>
<a href="ext_ffi_api.html">ffi.* API</a>
</li><li>
<a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul>
</li><li>
<a class="current" href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a>
</li><li>
<a href="ext_c_api.html">Lua/C API</a>
</li><li>
<a href="ext_profiler.html">Profiler</a>
</li></ul>
</li><li>
<a href="status.html">Status</a>
</li><li>
<a href="faq.html">FAQ</a>
</li><li>
<a href="http://wiki.luajit.org/">Wiki <span class="ext">&raquo;</span></a>
</li><li>
<a href="https://luajit.org/list.html">Mailing List <span class="ext">&raquo;</span></a>
</li></ul>
</div>
<div id="main">
<p>
The string buffer library allows <b>high-performance manipulation of
string-like data</b>.
</p>
<p>
Unlike Lua strings, which are constants, string buffers are
<b>mutable</b> sequences of 8-bit (binary-transparent) characters. Data
can be stored, formatted and encoded into a string buffer and later
converted, extracted or decoded.
</p>
<p>
The convenient string buffer API simplifies common string manipulation
tasks, that would otherwise require creating many intermediate strings.
String buffers improve performance by eliminating redundant memory
copies, object creation, string interning and garbage collection
overhead. In conjunction with the FFI library, they allow zero-copy
operations.
</p>
<p>
The string buffer libary also includes a high-performance
<a href="serialize">serializer</a> for Lua objects.
</p>
<h2 id="wip" style="color:#ff0000">Work in Progress</h2>
<p>
<b style="color:#ff0000">This library is a work in progress. More
functionality will be added soon.</b>
</p>
<h2 id="use">Using the String Buffer Library</h2>
<p>
The string buffer library is built into LuaJIT by default, but it's not
loaded by default. Add this to the start of every Lua file that needs
one of its functions:
</p>
<pre class="code">
local buffer = require("string.buffer")
</pre>
<p>
The convention for the syntax shown on this page is that <tt>buffer</tt>
refers to the buffer library and <tt>buf</tt> refers to an individual
buffer object.
</p>
<p>
Please note the difference between a Lua function call, e.g.
<tt>buffer.new()</tt> (with a dot) and a Lua method call, e.g.
<tt>buf:reset()</tt> (with a colon).
</p>
<h3 id="buffer_object">Buffer Objects</h3>
<p>
A buffer object is a garbage-collected Lua object. After creation with
<tt>buffer.new()</tt>, it can (and should) be reused for many operations.
When the last reference to a buffer object is gone, it will eventually
be freed by the garbage collector, along with the allocated buffer
space.
</p>
<p>
Buffers operate like a FIFO (first-in first-out) data structure. Data
can be appended (written) to the end of the buffer and consumed (read)
from the front of the buffer. These operations may be freely mixed.
</p>
<p>
The buffer space that holds the characters is managed automatically
&mdash; it grows as needed and already consumed space is recycled. Use
<tt>buffer.new(size)</tt> and <tt>buf:free()</tt>, if you need more
control.
</p>
<p>
The maximum size of a single buffer is the same as the maximum size of a
Lua string, which is slightly below two gigabytes. For huge data sizes,
neither strings nor buffers are the right data structure &mdash; use the
FFI library to directly map memory or files up to the virtual memory
limit of your OS.
</p>
<h3 id="buffer_overview">Buffer Method Overview</h3>
<ul>
<li>
The <tt>buf:put*()</tt>-like methods append (write) characters to the
end of the buffer.
</li>
<li>
The <tt>buf:get*()</tt>-like methods consume (read) characters from the
front of the buffer.
</li>
<li>
Other methods, like <tt>buf:tostring()</tt> only read the buffer
contents, but don't change the buffer.
</li>
<li>
The <tt>buf:set()</tt> method allows zero-copy consumption of a string
or an FFI cdata object as a buffer.
</li>
<li>
The FFI-specific methods allow zero-copy read/write-style operations or
modifying the buffer contents in-place. Please check the
<a href="#ffi_caveats">FFI caveats</a> below, too.
</li>
<li>
Methods that don't need to return anything specific, return the buffer
object itself as a convenience. This allows method chaining, e.g.:
<tt>buf:reset():encode(obj)</tt> or <tt>buf:skip(len):get()</tt>
</li>
</ul>
<h2 id="create">Buffer Creation and Management</h2>
<h3 id="buffer_new"><tt>local buf = buffer.new([size [,options]])<br>
local buf = buffer.new([options])</tt></h3>
<p>
Creates a new buffer object.
</p>
<p>
The optional <tt>size</tt> argument ensures a minimum initial buffer
size. This is strictly an optimization when the required buffer size is
known beforehand. The buffer space will grow as needed, in any case.
</p>
<p>
The optional table <tt>options</tt> sets various
<a href="#serialize_options">serialization options</a>.
</p>
<h3 id="buffer_reset"><tt>buf = buf:reset()</tt></h3>
<p>
Reset (empty) the buffer. The allocated buffer space is not freed and
may be reused.
</p>
<h3 id="buffer_free"><tt>buf = buf:free()</tt></h3>
<p>
The buffer space of the buffer object is freed. The object itself
remains intact, empty and may be reused.
</p>
<p>
Note: you normally don't need to use this method. The garbage collector
automatically frees the buffer space, when the buffer object is
collected. Use this method, if you need to free the associated memory
immediately.
</p>
<h2 id="write">Buffer Writers</h2>
<h3 id="buffer_put"><tt>buf = buf:put([str|num|obj] [,…])</tt></h3>
<p>
Appends a string <tt>str</tt>, a number <tt>num</tt> or any object
<tt>obj</tt> with a <tt>__tostring</tt> metamethod to the buffer.
Multiple arguments are appended in the given order.
</p>
<p>
Appending a buffer to a buffer is possible and short-circuited
internally. But it still involves a copy. Better combine the buffer
writes to use a single buffer.
</p>
<h3 id="buffer_putf"><tt>buf = buf:putf(format, …)</tt></h3>
<p>
Appends the formatted arguments to the buffer. The <tt>format</tt>
string supports the same options as <tt>string.format()</tt>.
</p>
<h3 id="buffer_putcdata"><tt>buf = buf:putcdata(cdata, len)</tt><span class="lib">FFI</span></h3>
<p>
Appends the given <tt>len</tt> number of bytes from the memory pointed
to by the FFI <tt>cdata</tt> object to the buffer. The object needs to
be convertible to a (constant) pointer.
</p>
<h3 id="buffer_set"><tt>buf = buf:set(str)<br>
buf = buf:set(cdata, len)</tt><span class="lib">FFI</span></h3>
<p>
This method allows zero-copy consumption of a string or an FFI cdata
object as a buffer. It stores a reference to the passed string
<tt>str</tt> or the FFI <tt>cdata</tt> object in the buffer. Any buffer
space originally allocated is freed. This is <i>not</i> an append
operation, unlike the <tt>buf:put*()</tt> methods.
</p>
<p>
After calling this method, the buffer behaves as if
<tt>buf:free():put(str)</tt> or <tt>buf:free():put(cdata,&nbsp;len)</tt>
had been called. However, the data is only referenced and not copied, as
long as the buffer is only consumed.
</p>
<p>
In case the buffer is written to later on, the referenced data is copied
and the object reference is removed (copy-on-write semantics).
</p>
<p>
The stored reference is an anchor for the garbage collector and keeps the
originally passed string or FFI cdata object alive.
</p>
<h3 id="buffer_reserve"><tt>ptr, len = buf:reserve(size)</tt><span class="lib">FFI</span><br>
<tt>buf = buf:commit(used)</tt><span class="lib">FFI</span></h3>
<p>
The <tt>reserve</tt> method reserves at least <tt>size</tt> bytes of
write space in the buffer. It returns an <tt>uint8_t&nbsp;*</tt> FFI
cdata pointer <tt>ptr</tt> that points to this space.
</p>
<p>
The available length in bytes is returned in <tt>len</tt>. This is at
least <tt>size</tt> bytes, but may be more to facilitate efficient
buffer growth. You can either make use of the additional space or ignore
<tt>len</tt> and only use <tt>size</tt> bytes.
</p>
<p>
The <tt>commit</tt> method appends the <tt>used</tt> bytes of the
previously returned write space to the buffer data.
</p>
<p>
This pair of methods allows zero-copy use of C read-style APIs:
</p>
<pre class="code">
local MIN_SIZE = 65536
repeat
local ptr, len = buf:reserve(MIN_SIZE)
local n = C.read(fd, ptr, len)
if n == 0 then break end -- EOF.
if n &lt; 0 then error("read error") end
buf:commit(n)
until false
</pre>
<p>
The reserved write space is <i>not</i> initialized. At least the
<tt>used</tt> bytes <b>must</b> be written to before calling the
<tt>commit</tt> method. There's no need to call the <tt>commit</tt>
method, if nothing is added to the buffer (e.g. on error).
</p>
<h2 id="read">Buffer Readers</h2>
<h3 id="buffer_length"><tt>len = #buf</tt></h3>
<p>
Returns the current length of the buffer data in bytes.
</p>
<h3 id="buffer_concat"><tt>res = str|num|buf .. str|num|buf […]</tt></h3>
<p>
The Lua concatenation operator <tt>..</tt> also accepts buffers, just
like strings or numbers. It always returns a string and not a buffer.
</p>
<p>
Note that although this is supported for convenience, this thwarts one
of the main reasons to use buffers, which is to avoid string
allocations. Rewrite it with <tt>buf:put()</tt> and <tt>buf:get()</tt>.
</p>
<p>
Mixing this with unrelated objects that have a <tt>__concat</tt>
metamethod may not work, since these probably only expect strings.
</p>
<h3 id="buffer_skip"><tt>buf = buf:skip(len)</tt></h3>
<p>
Skips (consumes) <tt>len</tt> bytes from the buffer up to the current
length of the buffer data.
</p>
<h3 id="buffer_get"><tt>str, … = buf:get([len|nil] [,…])</tt></h3>
<p>
Consumes the buffer data and returns one or more strings. If called
without arguments, the whole buffer data is consumed. If called with a
number, up to <tt>len</tt> bytes are consumed. A <tt>nil</tt> argument
consumes the remaining buffer space (this only makes sense as the last
argument). Multiple arguments consume the buffer data in the given
order.
</p>
<p>
Note: a zero length or no remaining buffer data returns an empty string
and not <tt>nil</tt>.
</p>
<h3 id="buffer_tostring"><tt>str = buf:tostring()<br>
str = tostring(buf)</tt></h3>
<p>
Creates a string from the buffer data, but doesn't consume it. The
buffer remains unchanged.
</p>
<p>
Buffer objects also define a <tt>__tostring</tt> metamethod. This means
buffers can be passed to the global <tt>tostring()</tt> function and
many other functions that accept this in place of strings. The important
internal uses in functions like <tt>io.write()</tt> are short-circuited
to avoid the creation of an intermediate string object.
</p>
<h3 id="buffer_ref"><tt>ptr, len = buf:ref()</tt><span class="lib">FFI</span></h3>
<p>
Returns an <tt>uint8_t&nbsp;*</tt> FFI cdata pointer <tt>ptr</tt> that
points to the buffer data. The length of the buffer data in bytes is
returned in <tt>len</tt>.
</p>
<p>
The returned pointer can be directly passed to C functions that expect a
buffer and a length. You can also do bytewise reads
(<tt>local&nbsp;x&nbsp;=&nbsp;ptr[i]</tt>) or writes
(<tt>ptr[i]&nbsp;=&nbsp;0x40</tt>) of the buffer data.
</p>
<p>
In conjunction with the <tt>skip</tt> method, this allows zero-copy use
of C write-style APIs:
</p>
<pre class="code">
repeat
local ptr, len = buf:ref()
if len == 0 then break end
local n = C.write(fd, ptr, len)
if n &lt; 0 then error("write error") end
buf:skip(n)
until n >= len
</pre>
<p>
Unlike Lua strings, buffer data is <i>not</i> implicitly
zero-terminated. It's not safe to pass <tt>ptr</tt> to C functions that
expect zero-terminated strings. If you're not using <tt>len</tt>, then
you're doing something wrong.
</p>
<h2 id="serialize">Serialization of Lua Objects</h2>
<p>
The following functions and methods allow <b>high-speed serialization</b>
(encoding) of a Lua object into a string and decoding it back to a Lua
object. This allows convenient storage and transport of <b>structured
data</b>.
</p>
<p>
The encoded data is in an <a href="#serialize_format">internal binary
format</a>. The data can be stored in files, binary-transparent
databases or transmitted to other LuaJIT instances across threads,
processes or networks.
</p>
<p>
Encoding speed can reach up to 1 Gigabyte/second on a modern desktop- or
server-class system, even when serializing many small objects. Decoding
speed is mostly constrained by object creation cost.
</p>
<p>
The serializer handles most Lua types, common FFI number types and
nested structures. Functions, thread objects, other FFI cdata and full
userdata cannot be serialized (yet).
</p>
<p>
The encoder serializes nested structures as trees. Multiple references
to a single object will be stored separately and create distinct objects
after decoding. Circular references cause an error.
</p>
<h3 id="serialize_methods">Serialization Functions and Methods</h3>
<h3 id="buffer_encode"><tt>str = buffer.encode(obj)<br>
buf = buf:encode(obj)</tt></h3>
<p>
Serializes (encodes) the Lua object <tt>obj</tt>. The stand-alone
function returns a string <tt>str</tt>. The buffer method appends the
encoding to the buffer.
</p>
<p>
<tt>obj</tt> can be any of the supported Lua types &mdash; it doesn't
need to be a Lua table.
</p>
<p>
This function may throw an error when attempting to serialize
unsupported object types, circular references or deeply nested tables.
</p>
<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
buffer. Both return a Lua object <tt>obj</tt>.
</p>
<p>
The returned object may be any of the supported Lua types &mdash;
even <tt>nil</tt>.
</p>
<p>
This function may throw an error when fed with malformed or incomplete
encoded data. The stand-alone function throws when there's left-over
data after decoding a single top-level object. The buffer method leaves
any left-over data in the buffer.
</p>
<h3 id="serialize_options">Serialization Options</h3>
<p>
The <tt>options</tt> table passed to <tt>buffer.new()</tt> may contain
the following members (all optional):
</p>
<ul>
<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
dictionary saves space and improves serialization performance.
</li>
<li>
<tt>metatable</tt> is a Lua table holding a <b>dictionary of metatables</b>
for the table objects you are serializing.
</li>
</ul>
<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
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>.
</p>
<p>
The <tt>dict</tt> and <tt>metatable</tt> tables used by the encoder and
decoder must be the same. Put the most common entries at the front. Extend
at the end to ensure backwards-compatibility &mdash; older encodings can
then still be read. You may also set some indexes to <tt>false</tt> to
explicitly drop backwards-compatibility. Old encodings that use these
indexes will throw an error when decoded.
</p>
<p>
Metatables that are not found in the <tt>metatable</tt> dictionary are
ignored when encoding. Decoding returns a table with a <tt>nil</tt>
metatable.
</p>
<p>
Note: parsing and preparation of the options table is somewhat
expensive. Create a buffer object only once and recycle it for multiple
uses. Avoid mixing encoder and decoder buffers, since the
<tt>buf:set()</tt> method frees the already allocated buffer space:
</p>
<pre class="code">
local options = {
dict = { "commonly", "used", "string", "keys" },
}
local buf_enc = buffer.new(options)
local buf_dec = buffer.new(options)
local function encode(obj)
return buf_enc:reset():encode(obj):get()
end
local function decode(str)
return buf_dec:set(str):decode()
end
</pre>
<h3 id="serialize_stream">Streaming Serialization</h3>
<p>
In some contexts, it's desirable to do piecewise serialization of large
datasets, also known as <i>streaming</i>.
</p>
<p>
This serialization format can be safely concatenated and supports streaming.
Multiple encodings can simply be appended to a buffer and later decoded
individually:
</p>
<pre class="code">
local buf = buffer.new()
buf:encode(obj1)
buf:encode(obj2)
local copy1 = buf:decode()
local copy2 = buf:decode()
</pre>
<p>
Here's how to iterate over a stream:
</p>
<pre class="code">
while #buf ~= 0 do
local obj = buf:decode()
-- Do something with obj.
end
</pre>
<p>
Since the serialization format doesn't prepend a length to its encoding,
network applications may need to transmit the length, too.
</p>
<h3 id="serialize_format">Serialization Format Specification</h3>
<p>
This serialization format is designed for <b>internal use</b> by LuaJIT
applications. Serialized data is upwards-compatible and portable across
all supported LuaJIT platforms.
</p>
<p>
It's an <b>8-bit binary format</b> and not human-readable. It uses e.g.
embedded zeroes and stores embedded Lua string objects unmodified, which
are 8-bit-clean, too. Encoded data can be safely concatenated for
streaming and later decoded one top-level object at a time.
</p>
<p>
The encoding is reasonably compact, but tuned for maximum performance,
not for minimum space usage. It compresses well with any of the common
byte-oriented data compression algorithms.
</p>
<p>
Although documented here for reference, this format is explicitly
<b>not</b> intended to be a 'public standard' for structured data
interchange across computer languages (like JSON or MessagePack). Please
do not use it as such.
</p>
<p>
The specification is given below as a context-free grammar with a
top-level <tt>object</tt> as the starting point. Alternatives are
separated by the <tt>|</tt> symbol and <tt>*</tt> indicates repeats.
Grouping is implicit or indicated by <tt>{…}</tt>. Terminals are
either plain hex numbers, encoded as bytes, or have a <tt>.format</tt>
suffix.
</p>
<pre>
object → nil | false | true
| null | lightud32 | lightud64
| int | num | tab | tab_mt
| int64 | uint64 | complex
| string
nil → 0x00
false → 0x01
true → 0x02
null → 0x03 // NULL lightuserdata
lightud32 → 0x04 data.I // 32 bit lightuserdata
lightud64 → 0x05 data.L // 64 bit lightuserdata
int → 0x06 int.I // int32_t
num → 0x07 double.L
tab → 0x08 // Empty table
| 0x09 h.U h*{object object} // Key/value hash
| 0x0a a.U a*object // 0-based array
| 0x0b a.U a*object h.U h*{object object} // Mixed
| 0x0c a.U (a-1)*object // 1-based array
| 0x0d a.U (a-1)*object h.U h*{object object} // Mixed
tab_mt → 0x0e (index-1).U tab // Metatable dict entry
int64 → 0x10 int.L // FFI int64_t
uint64 → 0x11 uint.L // FFI uint64_t
complex → 0x12 re.L im.L // FFI complex
string → (0x20+len).U len*char.B
| 0x0f (index-1).U // String dict entry
.B = 8 bit
.I = 32 bit little-endian
.L = 64 bit little-endian
.U = prefix-encoded 32 bit unsigned number n:
0x00..0xdf → n.B
0xe0..0x1fdf → (0xe0|(((n-0xe0)>>8)&0x1f)).B ((n-0xe0)&0xff).B
0x1fe0.. → 0xff n.I
</pre>
<h2 id="error">Error handling</h2>
<p>
Many of the buffer methods can throw an error. Out-of-memory or usage
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
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:
</p>
<pre class="code">
local ok, err = pcall(buf.encode, buf, obj)
if not ok then
-- Handle error in err.
end
</pre>
<h2 id="ffi_caveats">FFI caveats</h2>
<p>
The string buffer library has been designed to work well together with
the FFI library. But due to the low-level nature of the FFI library,
some care needs to be taken:
</p>
<p>
First, please remember that FFI pointers are zero-indexed. The space
returned by <tt>buf:reserve()</tt> and <tt>buf:ref()</tt> starts at the
returned pointer and ends before <tt>len</tt> bytes after that.
</p>
<p>
I.e. the first valid index is <tt>ptr[0]</tt> and the last valid index
is <tt>ptr[len-1]</tt>. If the returned length is zero, there's no valid
index at all. The returned pointer may even be <tt>NULL</tt>.
</p>
<p>
The space pointed to by the returned pointer is only valid as long as
the buffer is not modified in any way (neither append, nor consume, nor
reset, etc.). The pointer is also not a GC anchor for the buffer object
itself.
</p>
<p>
Buffer data is only guaranteed to be byte-aligned. Casting the returned
pointer to a data type with higher alignment may cause unaligned
accesses. It depends on the CPU architecture whether this is allowed or
not (it's always OK on x86/x64 and mostly OK on other modern
architectures).
</p>
<p>
FFI pointers or references do not count as GC anchors for an underlying
object. E.g. an <tt>array</tt> allocated with <tt>ffi.new()</tt> is
anchored by <tt>buf:set(array,&nbsp;len)</tt>, but not by
<tt>buf:set(array+offset,&nbsp;len)</tt>. The addition of the offset
creates a new pointer, even when the offset is zero. In this case, you
need to make sure there's still a reference to the original array as
long as its contents are in use by the buffer.
</p>
<p>
Even though each LuaJIT VM instance is single-threaded (but you can
create multiple VMs), FFI data structures can be accessed concurrently.
Be careful when reading/writing FFI cdata from/to buffers to avoid
concurrent accesses or modifications. In particular, the memory
referenced by <tt>buf:set(cdata,&nbsp;len)</tt> must not be modified
while buffer readers are working on it. Shared, but read-only memory
mappings of files are OK, but only if the file does not change.
</p>
<br class="flush">
</div>
<div id="foot">
<hr class="hide">
Copyright &copy; 2005-2021
<span class="noprint">
&middot;
<a href="contact.html">Contact</a>
</span>
</div>
</body>
</html>
+6 -4
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Lua/C API Extensions</title> <title>Lua/C API Extensions</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -37,6 +37,8 @@
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a class="current" href="ext_c_api.html">Lua/C API</a> <a class="current" href="ext_c_api.html">Lua/C API</a>
@@ -173,7 +175,7 @@ Also note that this mechanism is not without overhead.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+6 -4
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>FFI Library</title> <title>FFI Library</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -37,6 +37,8 @@
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -316,7 +318,7 @@ without undue conversion penalties.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+6 -4
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>ffi.* API Functions</title> <title>ffi.* API Functions</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -42,6 +42,8 @@ td.abiparam { font-weight: bold; width: 6em; }
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -556,7 +558,7 @@ named <tt>i</tt>.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+6 -4
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>FFI Semantics</title> <title>FFI Semantics</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -42,6 +42,8 @@ td.convop { font-style: italic; width: 40%; }
<a class="current" href="ext_ffi_semantics.html">FFI Semantics</a> <a class="current" href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -1246,7 +1248,7 @@ compiled.</li>
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+6 -4
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>FFI Tutorial</title> <title>FFI Tutorial</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -44,6 +44,8 @@ td.idiomlua b { font-weight: normal; color: #2142bf; }
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -587,7 +589,7 @@ it to a local variable in the function scope is unnecessary.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+7 -5
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>jit.* Library</title> <title>jit.* Library</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -37,6 +37,8 @@
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a class="current" href="ext_jit.html">jit.* Library</a> <a class="current" href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -147,7 +149,7 @@ Contains the target OS name:
<h3 id="jit_arch"><tt>jit.arch</tt></h3> <h3 id="jit_arch"><tt>jit.arch</tt></h3>
<p> <p>
Contains the target architecture name: Contains the target architecture name:
"x86", "x64", "arm", "arm64", "ppc", "mips" or "mips64". "x86", "x64", "arm", "arm64", "arm64be", "ppc", "mips", "mipsel", "mips64", "mips64el", "mips64r6", "mips64r6el".
</p> </p>
<h2 id="jit_opt"><tt>jit.opt.*</tt> &mdash; JIT compiler optimization control</h2> <h2 id="jit_opt"><tt>jit.opt.*</tt> &mdash; JIT compiler optimization control</h2>
@@ -185,7 +187,7 @@ if you want to know more.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+6 -4
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Profiler</title> <title>Profiler</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -37,6 +37,8 @@
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -349,7 +351,7 @@ use.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+15 -21
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Extensions</title> <title>Extensions</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -54,6 +54,8 @@ td.excinterop {
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -392,29 +394,19 @@ the toolchain used to compile LuaJIT:
<td class="excinterop">Interoperability</td> <td class="excinterop">Interoperability</td>
</tr> </tr>
<tr class="odd separate"> <tr class="odd separate">
<td class="excplatform">POSIX/x64, DWARF2 unwinding</td> <td class="excplatform">External frame unwinding</td>
<td class="exccompiler">GCC 4.3+, Clang</td> <td class="exccompiler">GCC, Clang, MSVC</td>
<td class="excinterop"><b style="color: #00a000;">Full</b></td> <td class="excinterop"><b style="color: #00a000;">Full</b></td>
</tr> </tr>
<tr class="even"> <tr class="even">
<td class="excplatform">ARM <tt>-DLUAJIT_UNWIND_EXTERNAL</tt></td> <td class="excplatform">Internal frame unwinding + DWARF2</td>
<td class="exccompiler">GCC, Clang</td>
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
</tr>
<tr class="odd">
<td class="excplatform">Other platforms, DWARF2 unwinding</td>
<td class="exccompiler">GCC, Clang</td> <td class="exccompiler">GCC, Clang</td>
<td class="excinterop"><b style="color: #c06000;">Limited</b></td> <td class="excinterop"><b style="color: #c06000;">Limited</b></td>
</tr> </tr>
<tr class="even">
<td class="excplatform">Windows/x64</td>
<td class="exccompiler">MSVC</td>
<td class="excinterop"><b style="color: #00a000;">Full</b></td>
</tr>
<tr class="odd"> <tr class="odd">
<td class="excplatform">Windows/x86</td> <td class="excplatform">Windows 64 bit</td>
<td class="exccompiler">Any</td> <td class="exccompiler">non-MSVC</td>
<td class="excinterop"><b style="color: #00a000;">Full</b></td> <td class="excinterop"><b style="color: #c06000;">Limited</b></td>
</tr> </tr>
<tr class="even"> <tr class="even">
<td class="excplatform">Other platforms</td> <td class="excplatform">Other platforms</td>
@@ -435,7 +427,9 @@ the toolchain used to compile LuaJIT:
on the C&nbsp;stack. The contents of the C++&nbsp;exception object on the C&nbsp;stack. The contents of the C++&nbsp;exception object
pass through unmodified.</li> pass through unmodified.</li>
<li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>. <li>Lua errors can be caught on the C++ side with <tt>catch(...)</tt>.
The corresponding Lua error message can be retrieved from the Lua stack.</li> The corresponding Lua error message can be retrieved from the Lua stack.<br>
For MSVC for Windows 64 bit this requires compilation of your C++ code
with <tt>/EHa</tt>.</li>
<li>Throwing Lua errors across C++ frames is safe. C++ destructors <li>Throwing Lua errors across C++ frames is safe. C++ destructors
will be called.</li> will be called.</li>
</ul> </ul>
@@ -470,7 +464,7 @@ C++ destructors.</li>
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+42 -47
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Frequently Asked Questions (FAQ)</title> <title>Frequently Asked Questions (FAQ)</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -40,6 +40,8 @@ dd { margin-left: 1.5em; }
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -74,22 +76,20 @@ about LuaJIT.</li>
and links to books and papers about Lua.</li> and links to books and papers about Lua.</li>
<li>The community-managed <a href="http://lua-users.org/wiki/"><span class="ext">&raquo;</span>&nbsp;Lua Wiki</a> <li>The community-managed <a href="http://lua-users.org/wiki/"><span class="ext">&raquo;</span>&nbsp;Lua Wiki</a>
has information about diverse topics.</li> has information about diverse topics.</li>
</ul> </ul></dd>
</dl> </dl>
<dl id="tech"> <dl id="tech">
<dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt> <dt>Q: Where can I learn more about the compiler technology used by LuaJIT?</dt>
<dd> <dd>
I'm planning to write more documentation about the internals of LuaJIT. Please use the following Google Scholar searches to find relevant papers:<br>
In the meantime, please use the following Google Scholar searches
to find relevant papers:<br>
Search for: <a href="https://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">&raquo;</span>&nbsp;Trace Compiler</a><br> Search for: <a href="https://scholar.google.com/scholar?q=Trace+Compiler"><span class="ext">&raquo;</span>&nbsp;Trace Compiler</a><br>
Search for: <a href="https://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">&raquo;</span>&nbsp;JIT Compiler</a><br> Search for: <a href="https://scholar.google.com/scholar?q=JIT+Compiler"><span class="ext">&raquo;</span>&nbsp;JIT Compiler</a><br>
Search for: <a href="https://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">&raquo;</span>&nbsp;Dynamic Language Optimizations</a><br> Search for: <a href="https://scholar.google.com/scholar?q=Dynamic+Language+Optimizations"><span class="ext">&raquo;</span>&nbsp;Dynamic Language Optimizations</a><br>
Search for: <a href="https://scholar.google.com/scholar?q=SSA+Form"><span class="ext">&raquo;</span>&nbsp;SSA Form</a><br> Search for: <a href="https://scholar.google.com/scholar?q=SSA+Form"><span class="ext">&raquo;</span>&nbsp;SSA Form</a><br>
Search for: <a href="https://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">&raquo;</span>&nbsp;Linear Scan Register Allocation</a><br> Search for: <a href="https://scholar.google.com/scholar?q=Linear+Scan+Register+Allocation"><span class="ext">&raquo;</span>&nbsp;Linear Scan Register Allocation</a><br>
Here is a list of the <a href="http://lua-users.org/lists/lua-l/2009-11/msg00089.html"><span class="ext">&raquo;</span>&nbsp;innovative features in LuaJIT</a>.<br> Here is a list of the <a href="http://lua-users.org/lists/lua-l/2009-11/msg00089.html"><span class="ext">&raquo;</span>&nbsp;innovative features in LuaJIT</a>.<br>
And, you know, reading the source is of course the only way to enlightenment. :-) And, you know, reading the source is of course the only way to enlightenment.
</dd> </dd>
</dl> </dl>
@@ -121,19 +121,30 @@ Consider testing your application with older versions, too.<br>
Similarly, the Borland/Delphi runtime modifies the FPU control word and Similarly, the Borland/Delphi runtime modifies the FPU control word and
enables FP exceptions. Of course this violates the Windows ABI, too. enables FP exceptions. Of course this violates the Windows ABI, too.
Please check the Delphi docs for the Set8087CW method. Please check the Delphi docs for the Set8087CW method.</dd>
</dl> </dl>
<dl id="ctrlc"> <dl id="ctrlc">
<dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt> <dt>Q: Sometimes Ctrl-C fails to stop my Lua program. Why?</dt>
<dd>The interrupt signal handler sets a Lua debug hook. But this is <dd>The interrupt signal handler sets a Lua debug hook. But this is
currently ignored by compiled code (this will eventually be fixed). If ignored by compiled code. If your program is running in a tight loop
your program is running in a tight loop and never falls back to the and never falls back to the interpreter, the debug hook never runs and
interpreter, the debug hook never runs and can't throw the can't throw the "interrupted!" error.<br>
"interrupted!" error.<br> In the meantime you have to press Ctrl-C You have to press Ctrl-C twice to get stop your program. That's similar
twice to get stop your program. That's similar to when it's stuck to when it's stuck running inside a C function under the Lua interpreter.</dd>
running inside a C function under the Lua interpreter.</dd> </dl>
<dl id="order">
<dt>Q: Table iteration with <tt>pairs()</tt> does not result in the same order?</dt>
<dd>The order of table iteration is explicitly <b>undefined</b> by
the Lua language standard.<br>
Different Lua implementations or versions may use different orders for
otherwise identical tables. Different ways of constructing a table may
result in different orders, too.<br>
Due to improved VM security, LuaJIT 2.1 may even use a different order
on separate VM invocations or when string keys are newly interned.<br><br>
If your program relies on a deterministic order, it has a bug. Rewrite it,
so it doesn't rely on the key order. Or sort the table keys, if you must.</dd>
</dl> </dl>
<dl id="sandbox"> <dl id="sandbox">
@@ -147,30 +158,20 @@ it's very hard to get this right even for the Lua core libraries. Of course,
you'll need to inspect any extension library, too. And there are libraries you'll need to inspect any extension library, too. And there are libraries
that are inherently unsafe, e.g. the <a href="ext_ffi.html">FFI library</a>.<br> that are inherently unsafe, e.g. the <a href="ext_ffi.html">FFI library</a>.<br>
Relatedly, <b>loading untrusted bytecode is not safe!</b> It's trivial More reading material at the <a href="http://lua-users.org/wiki/SandBoxes"><span class="ext">&raquo;</span>&nbsp;Lua Wiki</a> and <a href="https://en.wikipedia.org/wiki/Sandbox_(computer_security)"><span class="ext">&raquo;</span>&nbsp;Wikipedia</a>.<br><br>
to crash the Lua or LuaJIT VM with maliciously crafted bytecode. This is
well known and there's no bytecode verification on purpose, so please Relatedly, <b>loading untrusted bytecode is not safe!</b><br>
It's trivial to crash the Lua or LuaJIT VM with maliciously crafted bytecode.
This is well known and there's no bytecode verification on purpose, so please
don't report a bug about it. Check the <tt>mode</tt> parameter for the don't report a bug about it. Check the <tt>mode</tt> parameter for the
<tt>load*()</tt> functions to disable loading of bytecode.<br> <tt>load*()</tt> functions to disable loading of bytecode.<br><br>
In general, the only promising approach is to sandbox Lua code at the <b>In general, the only promising approach is to sandbox Lua code at the
process level and not the VM level.<br> process level and not the VM level.</b>
More reading material at the <a href="http://lua-users.org/wiki/SandBoxes"><span class="ext">&raquo;</span>&nbsp;Lua Wiki</a> and <a href="https://en.wikipedia.org/wiki/Sandbox_(computer_security)"><span class="ext">&raquo;</span>&nbsp;Wikipedia</a>.
</dd> </dd>
</dl> </dl>
<dl id="patches">
<dt>Q: Why doesn't my favorite power-patch for Lua apply against LuaJIT?</dt>
<dd>Because it's a completely redesigned VM and has very little code
in common with Lua anymore. Also, if the patch introduces changes to
the Lua semantics, these would need to be reflected everywhere in the
VM, from the interpreter up to all stages of the compiler.<br> Please
use only standard Lua language constructs. For many common needs you
can use source transformations or use wrapper or proxy functions.
The compiler will happily optimize away such indirections.</dd>
</dl>
<dl id="arch"> <dl id="arch">
<dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt> <dt>Q: Lua runs everywhere. Why doesn't LuaJIT support my CPU?</dt>
<dd>Because it's a compiler &mdash; it needs to generate native <dd>Because it's a compiler &mdash; it needs to generate native
@@ -178,23 +179,17 @@ machine code. This means the code generator must be ported to each
architecture. And the fast interpreter is written in assembler and architecture. And the fast interpreter is written in assembler and
must be ported, too. This is quite an undertaking.<br> must be ported, too. This is quite an undertaking.<br>
The <a href="install.html">install documentation</a> shows the supported The <a href="install.html">install documentation</a> shows the supported
architectures. Other architectures will follow based on sufficient user architectures.<br>
demand and/or sponsoring.</dd> Other architectures may follow based on sufficient user demand and
</dl> market-relevance of the architecture. Sponsoring is required to develop
the port itself, to integrate it and to continuously maintain it in the
<dl id="when"> actively developed branches.</dd>
<dt>Q: When will feature X be added? When will the next version be released?</dt>
<dd>When it's ready.<br>
C'mon, it's open source &mdash; I'm doing it on my own time and you're
getting it for free. You can either contribute a patch or sponsor
the development of certain features, if they are important to you.
</dd>
</dl> </dl>
<br class="flush"> <br class="flush">
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+38 -33
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Installation</title> <title>Installation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -65,6 +65,8 @@ td.compatno {
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -103,8 +105,8 @@ operating systems, CPUs and compilers:
<td class="compatcpu">CPU / OS</td> <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">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">*BSD, Other</a></td>
<td class="compatos"><a href="#posix">OSX 10.4+</a> or<br><a href="#ios">iOS 3.0+</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<br>XP/Vista/7</a></td> <td class="compatos"><a href="#windows">Windows 7<br>or later</a></td>
</tr> </tr>
<tr class="odd separate"> <tr class="odd separate">
<td class="compatcpu">x86 (32 bit)</td> <td class="compatcpu">x86 (32 bit)</td>
@@ -128,7 +130,7 @@ operating systems, CPUs and compilers:
<td class="compatos compatno">&nbsp;</td> <td class="compatos compatno">&nbsp;</td>
</tr> </tr>
<tr class="even"> <tr class="even">
<td class="compatcpu"><a href="#cross2">ARM64</a></td> <td class="compatcpu"><a href="#cross2">ARM64<br>ARM64be</a></td>
<td class="compatos">GCC 4.8+</td> <td class="compatos">GCC 4.8+</td>
<td class="compatos compatno">&nbsp;</td> <td class="compatos compatno">&nbsp;</td>
<td class="compatos">XCode 6.0+<br>Clang 3.5+</td> <td class="compatos">XCode 6.0+<br>Clang 3.5+</td>
@@ -142,7 +144,7 @@ operating systems, CPUs and compilers:
<td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td> <td class="compatos">XEDK (<a href="#xbox360">Xbox 360</a>)</td>
</tr> </tr>
<tr class="even"> <tr class="even">
<td class="compatcpu"><a href="#cross2">MIPS32<br>MIPS64</a></td> <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">GCC 4.3+</td> <td class="compatos">GCC 4.3+</td>
<td class="compatos compatno">&nbsp;</td> <td class="compatos compatno">&nbsp;</td>
@@ -177,7 +179,7 @@ Please check the note about the
<a href="extensions.html#string_dump">bytecode format</a> differences, too. <a href="extensions.html#string_dump">bytecode format</a> differences, too.
</p> </p>
<h2 id="posix">POSIX Systems (Linux, OSX, *BSD etc.)</h2> <h2 id="posix">POSIX Systems (Linux, macOS, *BSD etc.)</h2>
<h3>Prerequisites</h3> <h3>Prerequisites</h3>
<p> <p>
Depending on your distribution, you may need to install a package for Depending on your distribution, you may need to install a package for
@@ -185,14 +187,19 @@ GCC, the development headers and/or a complete SDK. E.g. on a current
Debian/Ubuntu, install <tt>libc6-dev</tt> with the package manager. Debian/Ubuntu, install <tt>libc6-dev</tt> with the package manager.
</p> </p>
<p> <p>
Download the current source package of LuaJIT (pick the .tar.gz), The recommended way to fetch the latest version is to do a pull from
if you haven't already done so. Move it to a directory of your choice, the git repository.
open a terminal window and change to this directory. Now unpack the archive </p>
and change to the newly created directory: <p>
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):
</p> </p>
<pre class="code"> <pre class="code">
tar zxf LuaJIT-2.0.5.tar.gz tar zxf LuaJIT-XX.YY.ZZ.tar.gz
cd LuaJIT-2.0.5</pre> cd LuaJIT-XX.YY.ZZ
</pre>
<h3>Building LuaJIT</h3> <h3>Building LuaJIT</h3>
<p> <p>
The supplied Makefiles try to auto-detect the settings needed for your The supplied Makefiles try to auto-detect the settings needed for your
@@ -216,9 +223,12 @@ You can add an extra prefix to the search paths by appending the
make PREFIX=/home/myself/lj2 make PREFIX=/home/myself/lj2
</pre> </pre>
<p> <p>
Note for OSX: you must set the <tt>MACOSX_DEPLOYMENT_TARGET</tt> Note for macOS: you <b>must</b> set the <tt>MACOSX_DEPLOYMENT_TARGET</tt>
environment variable to a value supported by your toolchain. environment variable to a value supported by your toolchain:
</p> </p>
<pre class="code">
MACOSX_DEPLOYMENT_TARGET=XX.YY make
</pre>
<h3>Installing LuaJIT</h3> <h3>Installing LuaJIT</h3>
<p> <p>
The top-level Makefile installs LuaJIT by default under The top-level Makefile installs LuaJIT by default under
@@ -250,8 +260,9 @@ GCC plus the required development headers.
Or install Microsoft's Visual Studio (MSVC). Or install Microsoft's Visual Studio (MSVC).
</p> </p>
<p> <p>
Next, download the source package and unpack it using an archive manager Next, pull from the git repository or download the source package and
(e.g. the Windows Explorer) to a directory of your choice. unpack it using an archive manager (e.g. the Windows Explorer) to
a directory of your choice.
</p> </p>
<h3>Building with MSVC</h3> <h3>Building with MSVC</h3>
<p> <p>
@@ -269,8 +280,8 @@ Then follow the installation instructions below.
<h3>Building with MinGW or Cygwin</h3> <h3>Building with MinGW or Cygwin</h3>
<p> <p>
Open a command prompt window and make sure the MinGW or Cygwin programs Open a command prompt window and make sure the MinGW or Cygwin programs
are in your path. Then <tt>cd</tt> to the directory where are in your path. Then <tt>cd</tt> to the directory of the git repository
you've unpacked the sources and run this command for MinGW: or where you've unpacked the sources. Then run this command for MinGW:
</p> </p>
<pre class="code"> <pre class="code">
mingw32-make mingw32-make
@@ -325,7 +336,7 @@ You need to specify <tt>TARGET_SYS</tt> whenever the host OS and the
target OS differ, or you'll get assembler or linker errors: target OS differ, or you'll get assembler or linker errors:
</p> </p>
<ul> <ul>
<li>E.g. if you're compiling on a Windows or OSX host for embedded Linux or Android, you need to add <tt>TARGET_SYS=Linux</tt> to the examples below.</li> <li>E.g. if you're compiling on a Windows or macOS host for embedded Linux or Android, you need to add <tt>TARGET_SYS=Linux</tt> to the examples below.</li>
<li>For a minimal target OS, you may need to disable the built-in allocator in <tt>src/Makefile</tt> and use <tt>TARGET_SYS=Other</tt>.</li> <li>For a minimal target OS, you may need to disable the built-in allocator in <tt>src/Makefile</tt> and use <tt>TARGET_SYS=Other</tt>.</li>
<li>Don't forget to specify the same <tt>TARGET_SYS</tt> for the install step, too.</li> <li>Don't forget to specify the same <tt>TARGET_SYS</tt> for the install step, too.</li>
</ul> </ul>
@@ -400,7 +411,8 @@ NDKCROSS=$NDKBIN/aarch64-linux-android-
NDKCC=$NDKBIN/aarch64-linux-android21-clang NDKCC=$NDKBIN/aarch64-linux-android21-clang
make CROSS=$NDKCROSS \ make CROSS=$NDKCROSS \
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \ STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
TARGET_LD=$NDKCC TARGET_LD=$NDKCC TARGET_AR=$NDKBIN/llvm-ar
TARGET_STRIP=$NDKBIN/llvm-strip
# Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB) # Android/ARM, armeabi-v7a (ARMv7 VFP), Android 4.1+ (JB)
NDKDIR=/opt/android/ndk NDKDIR=/opt/android/ndk
@@ -409,7 +421,8 @@ NDKCROSS=$NDKBIN/arm-linux-androideabi-
NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang NDKCC=$NDKBIN/armv7a-linux-androideabi16-clang
make HOST_CC="gcc -m32" CROSS=$NDKCROSS \ make HOST_CC="gcc -m32" CROSS=$NDKCROSS \
STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \ STATIC_CC=$NDKCC DYNAMIC_CC="$NDKCC -fPIC" \
TARGET_LD=$NDKCC TARGET_LD=$NDKCC TARGET_AR=$NDKBIN/llvm-ar
TARGET_STRIP=$NDKBIN/llvm-strip
</pre> </pre>
<p> <p>
You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="https://developer.apple.com/ios/"><span class="ext">&raquo;</span>&nbsp;iOS SDK</a>: You can cross-compile for <b id="ios">iOS 3.0+</b> (iPhone/iPad) using the <a href="https://developer.apple.com/ios/"><span class="ext">&raquo;</span>&nbsp;iOS SDK</a>:
@@ -522,14 +535,6 @@ the DLL). You may link LuaJIT statically on Windows only if you don't
intend to load Lua/C modules at runtime. intend to load Lua/C modules at runtime.
</li></ul> </li></ul>
</li> </li>
<li>
If you're building a 64 bit application on OSX which links directly or
indirectly against LuaJIT which is not built for <tt>LJ_GC64</tt> mode,
you need to link your main executable with these flags:
<pre class="code">
-pagezero_size 10000 -image_base 100000000
</pre>
</li>
</ul> </ul>
<p>Additional hints for initializing LuaJIT using the C API functions:</p> <p>Additional hints for initializing LuaJIT using the C API functions:</p>
<ul> <ul>
@@ -538,7 +543,7 @@ you need to link your main executable with these flags:
for embedding Lua or LuaJIT into your application.</li> for embedding Lua or LuaJIT into your application.</li>
<li>Make sure you use <tt>luaL_newstate</tt>. Avoid using <li>Make sure you use <tt>luaL_newstate</tt>. Avoid using
<tt>lua_newstate</tt>, since this uses the (slower) default memory <tt>lua_newstate</tt>, since this uses the (slower) default memory
allocator from your system (no support for this on x64).</li> allocator from your system (no support for this on 64&nbsp;bit architectures).</li>
<li>Make sure you use <tt>luaL_openlibs</tt> and not the old Lua 5.0 style <li>Make sure you use <tt>luaL_openlibs</tt> and not the old Lua 5.0 style
of calling <tt>luaopen_base</tt> etc. directly.</li> of calling <tt>luaopen_base</tt> etc. directly.</li>
<li>To change or extend the list of standard libraries to load, copy <li>To change or extend the list of standard libraries to load, copy
@@ -614,7 +619,7 @@ to me (the upstream) and not you (the package maintainer), anyway.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+8 -6
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>LuaJIT</title> <title>LuaJIT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -122,6 +122,8 @@ table.feature small {
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -146,7 +148,7 @@ Lua is a powerful, dynamic and light-weight programming language.
It may be embedded or used as a general-purpose, stand-alone language. It may be embedded or used as a general-purpose, stand-alone language.
</p> </p>
<p> <p>
LuaJIT is Copyright &copy; 2005-2020 Mike Pall, released under the LuaJIT is Copyright &copy; 2005-2021 Mike Pall, released under the
<a href="https://www.opensource.org/licenses/mit-license.php"><span class="ext">&raquo;</span>&nbsp;MIT open source license</a>. <a href="https://www.opensource.org/licenses/mit-license.php"><span class="ext">&raquo;</span>&nbsp;MIT open source license</a>.
</p> </p>
<p> <p>
@@ -154,7 +156,7 @@ LuaJIT is Copyright &copy; 2005-2020 Mike Pall, released under the
<h2>Compatibility</h2> <h2>Compatibility</h2>
<table class="feature os os1"> <table class="feature os os1">
<tr><td>Windows</td><td>Linux</td><td>BSD</td><td>OSX</td><td>POSIX</td></tr> <tr><td>Windows</td><td>Linux</td><td>BSD</td><td>macOS</td><td>POSIX</td></tr>
</table> </table>
<table class="feature os os2"> <table class="feature os os2">
<tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr> <tr><td><span style="font-size:90%;">Embedded</span></td><td>Android</td><td>iOS</td></tr>
@@ -220,7 +222,7 @@ Please select a sub-topic in the navigation bar to learn more about LuaJIT.
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+8 -6
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Running LuaJIT</title> <title>Running LuaJIT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -59,6 +59,8 @@ td.param_default {
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -183,8 +185,8 @@ itself. For a description of their options and output format, please
read the comment block at the start of their source. read the comment block at the start of their source.
They can be found in the <tt>lib</tt> directory of the source They can be found in the <tt>lib</tt> directory of the source
distribution or installed under the <tt>jit</tt> directory. By default distribution or installed under the <tt>jit</tt> directory. By default
this is <tt>/usr/local/share/luajit-2.0.5/jit</tt> on POSIX this is <tt>/usr/local/share/luajit-XX.YY.ZZ>/jit</tt> on POSIX
systems. systems (replace XX.YY.ZZ by the installed version).
</p> </p>
<h3 id="opt_O"><tt>-O[level]</tt><br> <h3 id="opt_O"><tt>-O[level]</tt><br>
@@ -293,7 +295,7 @@ Here are the parameters and their default settings:
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+15 -14
View File
@@ -1,9 +1,9 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Status</title> <title>Status</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta charset="utf-8">
<meta name="Copyright" content="Copyright (C) 2005-2020"> <meta name="Copyright" content="Copyright (C) 2005-2021">
<meta name="Language" content="en"> <meta name="Language" content="en">
<link rel="stylesheet" type="text/css" href="bluequad.css" media="screen"> <link rel="stylesheet" type="text/css" href="bluequad.css" media="screen">
<link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print"> <link rel="stylesheet" type="text/css" href="bluequad-print.css" media="print">
@@ -40,6 +40,8 @@ ul li { padding-bottom: 0.3em; }
<a href="ext_ffi_semantics.html">FFI Semantics</a> <a href="ext_ffi_semantics.html">FFI Semantics</a>
</li></ul> </li></ul>
</li><li> </li><li>
<a href="ext_buffer.html">String Buffers</a>
</li><li>
<a href="ext_jit.html">jit.* Library</a> <a href="ext_jit.html">jit.* Library</a>
</li><li> </li><li>
<a href="ext_c_api.html">Lua/C API</a> <a href="ext_c_api.html">Lua/C API</a>
@@ -58,9 +60,15 @@ ul li { padding-bottom: 0.3em; }
</div> </div>
<div id="main"> <div id="main">
<p> <p>
<span style="color: #0000c0;">LuaJIT&nbsp;2.0</span> is the current This documentation is for LuaJIT 2.1.0-beta3. Please check the <tt>doc</tt>
<span style="color: #0000c0;">stable branch</span>. This branch is in directory in each git branch for the version-specific documentation.
feature-freeze &mdash; new features will only be added to LuaJIT&nbsp;2.1. </p>
<p>
The currently developed branches are LuaJIT&nbsp;2.1 and LuaJIT&nbsp;2.0.
</p>
<p>
LuaJIT&nbsp;2.0 is in feature-freeze &mdash; new features will only
be added to LuaJIT&nbsp;2.1.
</p> </p>
<h2>Current Status</h2> <h2>Current Status</h2>
@@ -84,19 +92,12 @@ The Lua <b>debug API</b> is missing a couple of features (return
hooks for non-Lua functions) and shows slightly different behavior hooks for non-Lua functions) and shows slightly different behavior
in LuaJIT (no per-coroutine hooks, no tail call counting). in LuaJIT (no per-coroutine hooks, no tail call counting).
</li> </li>
<li>
Currently some <b>out-of-memory</b> errors from <b>on-trace code</b> are not
handled correctly. The error may fall through an on-trace
<tt>pcall</tt> or it may be passed on to the function set with
<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
garbage collector.
</li>
</ul> </ul>
<br class="flush"> <br class="flush">
</div> </div>
<div id="foot"> <div id="foot">
<hr class="hide"> <hr class="hide">
Copyright &copy; 2005-2020 Copyright &copy; 2005-2021
<span class="noprint"> <span class="noprint">
&middot; &middot;
<a href="contact.html">Contact</a> <a href="contact.html">Contact</a>
+6 -3
View File
@@ -1,6 +1,6 @@
/* /*
** DynASM ARM encoding engine. ** DynASM ARM encoding engine.
** Copyright (C) 2005-2020 Mike Pall. All rights reserved. ** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice. ** Released under the MIT license. See dynasm.lua for full copyright notice.
*/ */
@@ -294,7 +294,7 @@ int dasm_link(Dst_DECL, size_t *szp)
{ /* Handle globals not defined in this translation unit. */ { /* Handle globals not defined in this translation unit. */
int idx; int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx]; int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
@@ -371,7 +371,10 @@ int dasm_encode(Dst_DECL, void *buffer)
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break; break;
case DASM_REL_LG: case DASM_REL_LG:
CK(n >= 0, UNDEF_LG); if (n < 0) {
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp - 4);
goto patchrel;
}
/* fallthrough */ /* fallthrough */
case DASM_REL_PC: case DASM_REL_PC:
CK(n >= 0, UNDEF_PC); CK(n >= 0, UNDEF_PC);
+4 -4
View File
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DynASM ARM module. -- DynASM ARM module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice. -- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -9,9 +9,9 @@
local _info = { local _info = {
arch = "arm", arch = "arm",
description = "DynASM ARM module", description = "DynASM ARM module",
version = "1.4.0", version = "1.5.0",
vernum = 10400, vernum = 10500,
release = "2015-10-18", release = "2021-05-02",
author = "Mike Pall", author = "Mike Pall",
license = "MIT", license = "MIT",
} }
+51 -9
View File
@@ -1,6 +1,6 @@
/* /*
** DynASM ARM64 encoding engine. ** DynASM ARM64 encoding engine.
** Copyright (C) 2005-2020 Mike Pall. All rights reserved. ** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice. ** Released under the MIT license. See dynasm.lua for full copyright notice.
*/ */
@@ -21,8 +21,9 @@ enum {
/* The following actions need a buffer position. */ /* The following actions need a buffer position. */
DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG, DASM_ALIGN, DASM_REL_LG, DASM_LABEL_LG,
/* The following actions also have an argument. */ /* The following actions also have an argument. */
DASM_REL_PC, DASM_LABEL_PC, DASM_REL_PC, DASM_LABEL_PC, DASM_REL_A,
DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML, DASM_IMM, DASM_IMM6, DASM_IMM12, DASM_IMM13W, DASM_IMM13X, DASM_IMML,
DASM_IMMV, DASM_VREG,
DASM__MAX DASM__MAX
}; };
@@ -39,6 +40,7 @@ enum {
#define DASM_S_RANGE_LG 0x13000000 #define DASM_S_RANGE_LG 0x13000000
#define DASM_S_RANGE_PC 0x14000000 #define DASM_S_RANGE_PC 0x14000000
#define DASM_S_RANGE_REL 0x15000000 #define DASM_S_RANGE_REL 0x15000000
#define DASM_S_RANGE_VREG 0x16000000
#define DASM_S_UNDEF_LG 0x21000000 #define DASM_S_UNDEF_LG 0x21000000
#define DASM_S_UNDEF_PC 0x22000000 #define DASM_S_UNDEF_PC 0x22000000
@@ -247,7 +249,7 @@ void dasm_put(Dst_DECL, int start, ...)
n = (ins & 255); CK(n < D->maxsection, RANGE_SEC); n = (ins & 255); CK(n < D->maxsection, RANGE_SEC);
D->section = &D->sections[n]; goto stop; D->section = &D->sections[n]; goto stop;
case DASM_ESC: p++; ofs += 4; break; case DASM_ESC: p++; ofs += 4; break;
case DASM_REL_EXT: break; case DASM_REL_EXT: if ((ins & 0x8000)) ofs += 8; break;
case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break; case DASM_ALIGN: ofs += (ins & 255); b[pos++] = ofs; break;
case DASM_REL_LG: case DASM_REL_LG:
n = (ins & 2047) - 10; pl = D->lglabels + n; n = (ins & 2047) - 10; pl = D->lglabels + n;
@@ -268,6 +270,11 @@ void dasm_put(Dst_DECL, int start, ...)
*pl = pos; *pl = pos;
} }
pos++; pos++;
if ((ins & 0x8000)) ofs += 8;
break;
case DASM_REL_A:
b[pos++] = n;
b[pos++] = va_arg(ap, int);
break; break;
case DASM_LABEL_LG: case DASM_LABEL_LG:
pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel; pl = D->lglabels + (ins & 2047) - 10; CKPL(lg, LG); goto putlabel;
@@ -312,13 +319,21 @@ void dasm_put(Dst_DECL, int start, ...)
} }
case DASM_IMML: { case DASM_IMML: {
#ifdef DASM_CHECKS #ifdef DASM_CHECKS
int scale = (p[-2] >> 30); int scale = (ins & 3);
CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) || CK((!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ||
(unsigned int)(n+256) < 512, RANGE_I); (unsigned int)(n+256) < 512, RANGE_I);
#endif #endif
b[pos++] = n; b[pos++] = n;
break; break;
} }
case DASM_IMMV:
ofs += 4;
b[pos++] = n;
break;
case DASM_VREG:
CK(n < 32, RANGE_VREG);
b[pos++] = n;
break;
} }
} }
} }
@@ -348,7 +363,7 @@ int dasm_link(Dst_DECL, size_t *szp)
{ /* Handle globals not defined in this translation unit. */ { /* Handle globals not defined in this translation unit. */
int idx; int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx]; int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
@@ -375,8 +390,8 @@ int dasm_link(Dst_DECL, size_t *szp)
case DASM_REL_LG: case DASM_REL_PC: pos++; break; case DASM_REL_LG: case DASM_REL_PC: pos++; break;
case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break; case DASM_LABEL_LG: case DASM_LABEL_PC: b[pos++] += ofs; break;
case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W: case DASM_IMM: case DASM_IMM6: case DASM_IMM12: case DASM_IMM13W:
case DASM_IMML: pos++; break; case DASM_IMML: case DASM_IMMV: case DASM_VREG: pos++; break;
case DASM_IMM13X: pos += 2; break; case DASM_IMM13X: case DASM_REL_A: pos += 2; break;
} }
} }
stop: (void)0; stop: (void)0;
@@ -426,7 +441,12 @@ int dasm_encode(Dst_DECL, void *buffer)
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000; ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0xe1a00000;
break; break;
case DASM_REL_LG: case DASM_REL_LG:
CK(n >= 0, UNDEF_LG); if (n < 0) {
ptrdiff_t na = (ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp + 4;
n = (int)na;
CK((ptrdiff_t)n == na, RANGE_REL);
goto patchrel;
}
/* fallthrough */ /* fallthrough */
case DASM_REL_PC: case DASM_REL_PC:
CK(n >= 0, UNDEF_PC); CK(n >= 0, UNDEF_PC);
@@ -446,8 +466,24 @@ int dasm_encode(Dst_DECL, void *buffer)
} else if ((ins & 0x1000)) { /* TBZ, TBNZ */ } else if ((ins & 0x1000)) { /* TBZ, TBNZ */
CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL); CK((n & 3) == 0 && ((n+0x00008000) >> 16) == 0, RANGE_REL);
cp[-1] |= ((n << 3) & 0x0007ffe0); cp[-1] |= ((n << 3) & 0x0007ffe0);
} else if ((ins & 0x8000)) { /* absolute */
cp[0] = (unsigned int)((ptrdiff_t)cp - 4 + n);
cp[1] = (unsigned int)(((ptrdiff_t)cp - 4 + n) >> 32);
cp += 2;
} }
break; break;
case DASM_REL_A: {
ptrdiff_t na = (((ptrdiff_t)(*b++) << 32) | (unsigned int)n);
if ((ins & 0x3000) == 0x3000) { /* ADRP */
ins &= ~0x1000;
na = (na >> 12) - (((ptrdiff_t)cp - 4) >> 12);
} else {
na = na - (ptrdiff_t)cp + 4;
}
n = (int)na;
CK((ptrdiff_t)n == na, RANGE_REL);
goto patchrel;
}
case DASM_LABEL_LG: case DASM_LABEL_LG:
ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n); ins &= 2047; if (ins >= 20) D->globals[ins-10] = (void *)(base + n);
break; break;
@@ -468,11 +504,17 @@ int dasm_encode(Dst_DECL, void *buffer)
cp[-1] |= (dasm_imm13(n, *b++) << 10); cp[-1] |= (dasm_imm13(n, *b++) << 10);
break; break;
case DASM_IMML: { case DASM_IMML: {
int scale = (p[-2] >> 30); int scale = (ins & 3);
cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ? cp[-1] |= (!(n & ((1<<scale)-1)) && (unsigned int)(n>>scale) < 4096) ?
((n << (10-scale)) | 0x01000000) : ((n & 511) << 12); ((n << (10-scale)) | 0x01000000) : ((n & 511) << 12);
break; break;
} }
case DASM_IMMV:
*cp++ = n;
break;
case DASM_VREG:
cp[-1] |= (n & 0x1f) << (ins & 0x1f);
break;
default: *cp++ = ins; break; default: *cp++ = ins; break;
} }
} }
+95 -42
View File
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DynASM ARM64 module. -- DynASM ARM64 module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice. -- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -9,9 +9,9 @@
local _info = { local _info = {
arch = "arm", arch = "arm",
description = "DynASM ARM64 module", description = "DynASM ARM64 module",
version = "1.4.0", version = "1.5.0",
vernum = 10400, vernum = 10500,
release = "2015-10-18", release = "2021-05-02",
author = "Mike Pall", author = "Mike Pall",
license = "MIT", license = "MIT",
} }
@@ -23,12 +23,12 @@ local _M = { _info = _info }
local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs local type, tonumber, pairs, ipairs = type, tonumber, pairs, ipairs
local assert, setmetatable, rawget = assert, setmetatable, rawget local assert, setmetatable, rawget = assert, setmetatable, rawget
local _s = string local _s = string
local sub, format, byte, char = _s.sub, _s.format, _s.byte, _s.char local format, byte, char = _s.format, _s.byte, _s.char
local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub local match, gmatch, gsub = _s.match, _s.gmatch, _s.gsub
local concat, sort, insert = table.concat, table.sort, table.insert local concat, sort, insert = table.concat, table.sort, table.insert
local bit = bit or require("bit") local bit = bit or require("bit")
local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift local band, shl, shr, sar = bit.band, bit.lshift, bit.rshift, bit.arshift
local ror, tohex = bit.ror, bit.tohex local ror, tohex, tobit = bit.ror, bit.tohex, bit.tobit
-- Inherited tables and callbacks. -- Inherited tables and callbacks.
local g_opt, g_arch local g_opt, g_arch
@@ -39,7 +39,9 @@ local wline, werror, wfatal, wwarn
local action_names = { local action_names = {
"STOP", "SECTION", "ESC", "REL_EXT", "STOP", "SECTION", "ESC", "REL_EXT",
"ALIGN", "REL_LG", "LABEL_LG", "ALIGN", "REL_LG", "LABEL_LG",
"REL_PC", "LABEL_PC", "IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "REL_PC", "LABEL_PC", "REL_A",
"IMM", "IMM6", "IMM12", "IMM13W", "IMM13X", "IMML", "IMMV",
"VREG",
} }
-- Maximum number of section buffer positions for dasm_put(). -- Maximum number of section buffer positions for dasm_put().
@@ -246,9 +248,12 @@ local map_cond = {
local parse_reg_type local parse_reg_type
local function parse_reg(expr) local function parse_reg(expr, shift)
if not expr then werror("expected register name") end if not expr then werror("expected register name") end
local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$") local tname, ovreg = match(expr, "^([%w_]+):(@?%l%d+)$")
if not tname then
tname, ovreg = match(expr, "^([%w_]+):(R[xwqdshb]%b())$")
end
local tp = map_type[tname or expr] local tp = map_type[tname or expr]
if tp then if tp then
local reg = ovreg or tp.reg local reg = ovreg or tp.reg
@@ -266,18 +271,28 @@ local function parse_reg(expr)
elseif parse_reg_type ~= rt then elseif parse_reg_type ~= rt then
werror("register size mismatch") werror("register size mismatch")
end end
return r, tp return shl(r, shift), tp
end end
end end
local vrt, vreg = match(expr, "^R([xwqdshb])(%b())$")
if vreg then
if not parse_reg_type then
parse_reg_type = vrt
elseif parse_reg_type ~= vrt then
werror("register size mismatch")
end
if shift then waction("VREG", shift, vreg) end
return 0
end
werror("bad register name `"..expr.."'") werror("bad register name `"..expr.."'")
end end
local function parse_reg_base(expr) local function parse_reg_base(expr)
if expr == "sp" then return 0x3e0 end if expr == "sp" then return 0x3e0 end
local base, tp = parse_reg(expr) local base, tp = parse_reg(expr, 5)
if parse_reg_type ~= "x" then werror("bad register type") end if parse_reg_type ~= "x" then werror("bad register type") end
parse_reg_type = false parse_reg_type = false
return shl(base, 5), tp return base, tp
end end
local parse_ctx = {} local parse_ctx = {}
@@ -297,7 +312,7 @@ local function parse_number(n)
local code = loadenv("return "..n) local code = loadenv("return "..n)
if code then if code then
local ok, y = pcall(code) local ok, y = pcall(code)
if ok then return y end if ok and type(y) == "number" then return y end
end end
return nil return nil
end end
@@ -403,7 +418,7 @@ local function parse_imm_load(imm, scale)
end end
werror("out of range immediate `"..imm.."'") werror("out of range immediate `"..imm.."'")
else else
waction("IMML", 0, imm) waction("IMML", scale, imm)
return 0 return 0
end end
end end
@@ -462,6 +477,7 @@ end
local function parse_load(params, nparams, n, op) local function parse_load(params, nparams, n, op)
if params[n+2] then werror("too many operands") end if params[n+2] then werror("too many operands") end
local scale = shr(op, 30)
local pn, p2 = params[n], params[n+1] local pn, p2 = params[n], params[n+1]
local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$") local p1, wb = match(pn, "^%[%s*(.-)%s*%](!?)$")
if not p1 then if not p1 then
@@ -470,14 +486,13 @@ local function parse_load(params, nparams, n, op)
if reg and tailr ~= "" then if reg and tailr ~= "" then
local base, tp = parse_reg_base(reg) local base, tp = parse_reg_base(reg)
if tp then if tp then
waction("IMML", 0, format(tp.ctypefmt, tailr)) waction("IMML", scale, format(tp.ctypefmt, tailr))
return op + base return op + base
end end
end end
end end
werror("expected address operand") werror("expected address operand")
end end
local scale = shr(op, 30)
if p2 then if p2 then
if wb == "!" then werror("bad use of '!'") end if wb == "!" then werror("bad use of '!'") end
op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400 op = op + parse_reg_base(p1) + parse_imm(p2, 9, 12, 0, true) + 0x400
@@ -494,7 +509,7 @@ local function parse_load(params, nparams, n, op)
op = op + parse_imm_load(imm, scale) op = op + parse_imm_load(imm, scale)
else else
local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$") local p2b, p3b, p3s = match(p2a, "^,%s*([^,%s]*)%s*,?%s*(%S*)%s*(.*)$")
op = op + shl(parse_reg(p2b), 16) + 0x00200800 op = op + parse_reg(p2b, 16) + 0x00200800
if parse_reg_type ~= "x" and parse_reg_type ~= "w" then if parse_reg_type ~= "x" and parse_reg_type ~= "w" then
werror("bad index register type") werror("bad index register type")
end end
@@ -561,14 +576,14 @@ local function parse_load_pair(params, nparams, n, op)
end end
local function parse_label(label, def) local function parse_label(label, def)
local prefix = sub(label, 1, 2) local prefix = label:sub(1, 2)
-- =>label (pc label reference) -- =>label (pc label reference)
if prefix == "=>" then if prefix == "=>" then
return "PC", 0, sub(label, 3) return "PC", 0, label:sub(3)
end end
-- ->name (global label reference) -- ->name (global label reference)
if prefix == "->" then if prefix == "->" then
return "LG", map_global[sub(label, 3)] return "LG", map_global[label:sub(3)]
end end
if def then if def then
-- [1-9] (local label definition) -- [1-9] (local label definition)
@@ -586,8 +601,11 @@ local function parse_label(label, def)
if extname then if extname then
return "EXT", map_extern[extname] return "EXT", map_extern[extname]
end end
-- &expr (pointer)
if label:sub(1, 1) == "&" then
return "A", 0, format("(ptrdiff_t)(%s)", label:sub(2))
end
end end
werror("bad label `"..label.."'")
end end
local function branch_type(op) local function branch_type(op)
@@ -620,24 +638,24 @@ local function alias_bfx(p)
end end
local function alias_bfiz(p) local function alias_bfiz(p)
parse_reg(p[1]) parse_reg(p[1], 0)
if parse_reg_type == "w" then if parse_reg_type == "w" then
p[3] = "#-("..p[3]:sub(2)..")%32" p[3] = "#(32-("..p[3]:sub(2).."))%32"
p[4] = "#("..p[4]:sub(2)..")-1" p[4] = "#("..p[4]:sub(2)..")-1"
else else
p[3] = "#-("..p[3]:sub(2)..")%64" p[3] = "#(64-("..p[3]:sub(2).."))%64"
p[4] = "#("..p[4]:sub(2)..")-1" p[4] = "#("..p[4]:sub(2)..")-1"
end end
end end
local alias_lslimm = op_alias("ubfm_4", function(p) local alias_lslimm = op_alias("ubfm_4", function(p)
parse_reg(p[1]) parse_reg(p[1], 0)
local sh = p[3]:sub(2) local sh = p[3]:sub(2)
if parse_reg_type == "w" then if parse_reg_type == "w" then
p[3] = "#-("..sh..")%32" p[3] = "#(32-("..sh.."))%32"
p[4] = "#31-("..sh..")" p[4] = "#31-("..sh..")"
else else
p[3] = "#-("..sh..")%64" p[3] = "#(64-("..sh.."))%64"
p[4] = "#63-("..sh..")" p[4] = "#63-("..sh..")"
end end
end) end)
@@ -881,25 +899,25 @@ end
-- Handle opcodes defined with template strings. -- Handle opcodes defined with template strings.
local function parse_template(params, template, nparams, pos) local function parse_template(params, template, nparams, pos)
local op = tonumber(sub(template, 1, 8), 16) local op = tonumber(template:sub(1, 8), 16)
local n = 1 local n = 1
local rtt = {} local rtt = {}
parse_reg_type = false parse_reg_type = false
-- Process each character. -- Process each character.
for p in gmatch(sub(template, 9), ".") do for p in gmatch(template:sub(9), ".") do
local q = params[n] local q = params[n]
if p == "D" then if p == "D" then
op = op + parse_reg(q); n = n + 1 op = op + parse_reg(q, 0); n = n + 1
elseif p == "N" then elseif p == "N" then
op = op + shl(parse_reg(q), 5); n = n + 1 op = op + parse_reg(q, 5); n = n + 1
elseif p == "M" then elseif p == "M" then
op = op + shl(parse_reg(q), 16); n = n + 1 op = op + parse_reg(q, 16); n = n + 1
elseif p == "A" then elseif p == "A" then
op = op + shl(parse_reg(q), 10); n = n + 1 op = op + parse_reg(q, 10); n = n + 1
elseif p == "m" then elseif p == "m" then
op = op + shl(parse_reg(params[n-1]), 16) op = op + parse_reg(params[n-1], 16)
elseif p == "p" then elseif p == "p" then
if q == "sp" then params[n] = "@x31" end if q == "sp" then params[n] = "@x31" end
@@ -930,8 +948,14 @@ local function parse_template(params, template, nparams, pos)
elseif p == "B" then elseif p == "B" then
local mode, v, s = parse_label(q, false); n = n + 1 local mode, v, s = parse_label(q, false); n = n + 1
if not mode then werror("bad label `"..q.."'") end
local m = branch_type(op) local m = branch_type(op)
waction("REL_"..mode, v+m, s, 1) if mode == "A" then
waction("REL_"..mode, v+m, format("(unsigned int)(%s)", s))
actargs[#actargs+1] = format("(unsigned int)((%s)>>32)", s)
else
waction("REL_"..mode, v+m, s, 1)
end
elseif p == "I" then elseif p == "I" then
op = op + parse_imm12(q); n = n + 1 op = op + parse_imm12(q); n = n + 1
@@ -977,8 +1001,8 @@ function op_template(params, template, nparams)
if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end if not params then return template:gsub("%x%x%x%x%x%x%x%x", "") end
-- Limit number of section buffer positions used by a single dasm_put(). -- Limit number of section buffer positions used by a single dasm_put().
-- A single opcode needs a maximum of 3 positions. -- A single opcode needs a maximum of 4 positions.
if secpos+3 > maxsecpos then wflush() end if secpos+4 > maxsecpos then wflush() end
local pos = wpos() local pos = wpos()
local lpos, apos, spos = #actlist, #actargs, secpos local lpos, apos, spos = #actlist, #actargs, secpos
@@ -990,9 +1014,11 @@ function op_template(params, template, nparams)
actlist[lpos+1] = nil actlist[lpos+1] = nil
actlist[lpos+2] = nil actlist[lpos+2] = nil
actlist[lpos+3] = nil actlist[lpos+3] = nil
actlist[lpos+4] = nil
actargs[apos+1] = nil actargs[apos+1] = nil
actargs[apos+2] = nil actargs[apos+2] = nil
actargs[apos+3] = nil actargs[apos+3] = nil
actargs[apos+4] = nil
end end
error(err, 0) error(err, 0)
end end
@@ -1036,23 +1062,50 @@ map_op[".label_1"] = function(params)
if not params then return "[1-9] | ->global | =>pcexpr" end if not params then return "[1-9] | ->global | =>pcexpr" end
if secpos+1 > maxsecpos then wflush() end if secpos+1 > maxsecpos then wflush() end
local mode, n, s = parse_label(params[1], true) local mode, n, s = parse_label(params[1], true)
if mode == "EXT" then werror("bad label definition") end if not mode or mode == "EXT" then werror("bad label definition") end
waction("LABEL_"..mode, n, s, 1) waction("LABEL_"..mode, n, s, 1)
end end
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- Pseudo-opcodes for data storage. -- Pseudo-opcodes for data storage.
map_op[".long_*"] = function(params) local function op_data(params)
if not params then return "imm..." end if not params then return "imm..." end
local sz = params.op == ".long" and 4 or 8
for _,p in ipairs(params) do for _,p in ipairs(params) do
local n = tonumber(p) local imm = parse_number(p)
if not n then werror("bad immediate `"..p.."'") end if imm then
if n < 0 then n = n + 2^32 end local n = tobit(imm)
wputw(n) if n == imm or (n < 0 and n + 2^32 == imm) then
wputw(n < 0 and n + 2^32 or n)
if sz == 8 then
wputw(imm < 0 and 0xffffffff or 0)
end
elseif sz == 4 then
werror("bad immediate `"..p.."'")
else
imm = nil
end
end
if not imm then
local mode, v, s = parse_label(p, false)
if sz == 4 then
if mode then werror("label does not fit into .long") end
waction("IMMV", 0, p)
elseif mode and mode ~= "A" then
waction("REL_"..mode, v+0x8000, s, 1)
else
if mode == "A" then p = s end
waction("IMMV", 0, format("(unsigned int)(%s)", p))
waction("IMMV", 0, format("(unsigned int)((unsigned long long)(%s)>>32)", p))
end
end
if secpos+2 > maxsecpos then wflush() end if secpos+2 > maxsecpos then wflush() end
end end
end end
map_op[".long_*"] = op_data
map_op[".quad_*"] = op_data
map_op[".addr_*"] = op_data
-- Alignment pseudo-opcode. -- Alignment pseudo-opcode.
map_op[".align_1"] = function(params) map_op[".align_1"] = function(params)
+6 -3
View File
@@ -1,6 +1,6 @@
/* /*
** DynASM MIPS encoding engine. ** DynASM MIPS encoding engine.
** Copyright (C) 2005-2020 Mike Pall. All rights reserved. ** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice. ** Released under the MIT license. See dynasm.lua for full copyright notice.
*/ */
@@ -273,7 +273,7 @@ int dasm_link(Dst_DECL, size_t *szp)
{ /* Handle globals not defined in this translation unit. */ { /* Handle globals not defined in this translation unit. */
int idx; int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx]; int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
@@ -349,7 +349,10 @@ int dasm_encode(Dst_DECL, void *buffer)
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break; break;
case DASM_REL_LG: case DASM_REL_LG:
CK(n >= 0, UNDEF_LG); if (n < 0) {
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp);
goto patchrel;
}
/* fallthrough */ /* fallthrough */
case DASM_REL_PC: case DASM_REL_PC:
CK(n >= 0, UNDEF_PC); CK(n >= 0, UNDEF_PC);
+4 -4
View File
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DynASM MIPS32/MIPS64 module. -- DynASM MIPS32/MIPS64 module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice. -- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -12,9 +12,9 @@ local mipsr6 = _map_def.MIPSR6
local _info = { local _info = {
arch = mips64 and "mips64" or "mips", arch = mips64 and "mips64" or "mips",
description = "DynASM MIPS32/MIPS64 module", description = "DynASM MIPS32/MIPS64 module",
version = "1.4.0", version = "1.5.0",
vernum = 10400, vernum = 10500,
release = "2020-01-20", release = "2021-05-02",
author = "Mike Pall", author = "Mike Pall",
license = "MIT", license = "MIT",
} }
+1 -1
View File
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DynASM MIPS64 module. -- DynASM MIPS64 module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice. -- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- This module just sets 64 bit mode for the combined MIPS/MIPS64 module. -- This module just sets 64 bit mode for the combined MIPS/MIPS64 module.
+6 -3
View File
@@ -1,6 +1,6 @@
/* /*
** DynASM PPC/PPC64 encoding engine. ** DynASM PPC/PPC64 encoding engine.
** Copyright (C) 2005-2020 Mike Pall. All rights reserved. ** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice. ** Released under the MIT license. See dynasm.lua for full copyright notice.
*/ */
@@ -277,7 +277,7 @@ int dasm_link(Dst_DECL, size_t *szp)
{ /* Handle globals not defined in this translation unit. */ { /* Handle globals not defined in this translation unit. */
int idx; int idx;
for (idx = 20; idx*sizeof(int) < D->lgsize; idx++) { for (idx = 10; idx*sizeof(int) < D->lgsize; idx++) {
int n = D->lglabels[idx]; int n = D->lglabels[idx];
/* Undefined label: Collapse rel chain and replace with marker (< 0). */ /* Undefined label: Collapse rel chain and replace with marker (< 0). */
while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; } while (n > 0) { int *pb = DASM_POS2PTR(D, n); n = *pb; *pb = -idx; }
@@ -353,7 +353,10 @@ int dasm_encode(Dst_DECL, void *buffer)
ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000; ins &= 255; while ((((char *)cp - base) & ins)) *cp++ = 0x60000000;
break; break;
case DASM_REL_LG: case DASM_REL_LG:
CK(n >= 0, UNDEF_LG); if (n < 0) {
n = (int)((ptrdiff_t)D->globals[-n] - (ptrdiff_t)cp);
goto patchrel;
}
/* fallthrough */ /* fallthrough */
case DASM_REL_PC: case DASM_REL_PC:
CK(n >= 0, UNDEF_PC); CK(n >= 0, UNDEF_PC);
+4 -4
View File
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DynASM PPC/PPC64 module. -- DynASM PPC/PPC64 module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice. -- See dynasm.lua for full copyright notice.
-- --
-- Support for various extensions contributed by Caio Souza Oliveira. -- Support for various extensions contributed by Caio Souza Oliveira.
@@ -11,9 +11,9 @@
local _info = { local _info = {
arch = "ppc", arch = "ppc",
description = "DynASM PPC module", description = "DynASM PPC module",
version = "1.4.0", version = "1.5.0",
vernum = 10400, vernum = 10500,
release = "2015-10-18", release = "2021-05-02",
author = "Mike Pall", author = "Mike Pall",
license = "MIT", license = "MIT",
} }
+3 -3
View File
@@ -1,6 +1,6 @@
/* /*
** DynASM encoding engine prototypes. ** DynASM encoding engine prototypes.
** Copyright (C) 2005-2020 Mike Pall. All rights reserved. ** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice. ** Released under the MIT license. See dynasm.lua for full copyright notice.
*/ */
@@ -10,8 +10,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdarg.h> #include <stdarg.h>
#define DASM_IDENT "DynASM 1.4.0" #define DASM_IDENT "DynASM 1.5.0"
#define DASM_VERSION 10400 /* 1.4.0 */ #define DASM_VERSION 10500 /* 1.5.0 */
#ifndef Dst_DECL #ifndef Dst_DECL
#define Dst_DECL dasm_State **Dst #define Dst_DECL dasm_State **Dst
+1 -1
View File
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DynASM x64 module. -- DynASM x64 module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice. -- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- This module just sets 64 bit mode for the combined x86/x64 module. -- This module just sets 64 bit mode for the combined x86/x64 module.
+21 -5
View File
@@ -1,6 +1,6 @@
/* /*
** DynASM x86 encoding engine. ** DynASM x86 encoding engine.
** Copyright (C) 2005-2020 Mike Pall. All rights reserved. ** Copyright (C) 2005-2021 Mike Pall. All rights reserved.
** Released under the MIT license. See dynasm.lua for full copyright notice. ** Released under the MIT license. See dynasm.lua for full copyright notice.
*/ */
@@ -239,8 +239,11 @@ void dasm_put(Dst_DECL, int start, ...)
} }
pos++; pos++;
ofs += 4; /* Maximum offset needed. */ ofs += 4; /* Maximum offset needed. */
if (action == DASM_REL_LG || action == DASM_REL_PC) if (action == DASM_REL_LG || action == DASM_REL_PC) {
b[pos++] = ofs; /* Store pass1 offset estimate. */ b[pos++] = ofs; /* Store pass1 offset estimate. */
} else if (sizeof(ptrdiff_t) == 8) {
ofs += 4;
}
break; break;
case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel; case DASM_LABEL_LG: pl = D->lglabels + *p++; CKPL(lg, LG); goto putlabel;
case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC); case DASM_LABEL_PC: pl = D->pclabels + va_arg(ap, int); CKPL(pc, PC);
@@ -365,10 +368,22 @@ int dasm_link(Dst_DECL, size_t *szp)
do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0) do { *((unsigned short *)cp) = (unsigned short)(x); cp+=2; } while (0)
#define dasmd(x) \ #define dasmd(x) \
do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0) do { *((unsigned int *)cp) = (unsigned int)(x); cp+=4; } while (0)
#define dasmq(x) \
do { *((unsigned long long *)cp) = (unsigned long long)(x); cp+=8; } while (0)
#else #else
#define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0) #define dasmw(x) do { dasmb(x); dasmb((x)>>8); } while (0)
#define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0) #define dasmd(x) do { dasmw(x); dasmw((x)>>16); } while (0)
#define dasmq(x) do { dasmd(x); dasmd((x)>>32); } while (0)
#endif #endif
static unsigned char *dasma_(unsigned char *cp, ptrdiff_t x)
{
if (sizeof(ptrdiff_t) == 8)
dasmq((unsigned long long)x);
else
dasmd((unsigned int)x);
return cp;
}
#define dasma(x) (cp = dasma_(cp, (x)))
/* Pass 3: Encode sections. */ /* Pass 3: Encode sections. */
int dasm_encode(Dst_DECL, void *buffer) int dasm_encode(Dst_DECL, void *buffer)
@@ -443,12 +458,13 @@ int dasm_encode(Dst_DECL, void *buffer)
goto wb; goto wb;
} }
case DASM_IMM_LG: case DASM_IMM_LG:
p++; if (n < 0) { n = (int)(ptrdiff_t)D->globals[-n]; goto wd; } p++;
if (n < 0) { dasma((ptrdiff_t)D->globals[-n]); break; }
/* fallthrough */ /* fallthrough */
case DASM_IMM_PC: { case DASM_IMM_PC: {
int *pb = DASM_POS2PTR(D, n); int *pb = DASM_POS2PTR(D, n);
n = *pb < 0 ? pb[1] : (*pb + (int)(ptrdiff_t)base); dasma(*pb < 0 ? (ptrdiff_t)pb[1] : (*pb + (ptrdiff_t)base));
goto wd; break;
} }
case DASM_LABEL_LG: { case DASM_LABEL_LG: {
int idx = *p++; int idx = *p++;
+40 -12
View File
@@ -1,7 +1,7 @@
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
-- DynASM x86/x64 module. -- DynASM x86/x64 module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See dynasm.lua for full copyright notice. -- See dynasm.lua for full copyright notice.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -11,9 +11,9 @@ local x64 = x64
local _info = { local _info = {
arch = x64 and "x64" or "x86", arch = x64 and "x64" or "x86",
description = "DynASM x86/x64 module", description = "DynASM x86/x64 module",
version = "1.4.0", version = "1.5.0",
vernum = 10400, vernum = 10500,
release = "2015-10-18", release = "2021-05-02",
author = "Mike Pall", author = "Mike Pall",
license = "MIT", license = "MIT",
} }
@@ -484,6 +484,22 @@ local function wputdarg(n)
end end
end end
-- Put signed or unsigned qword or arg.
local function wputqarg(n)
local tn = type(n)
if tn == "number" then -- This is only used for numbers from -2^31..2^32-1.
wputb(band(n, 255))
wputb(band(shr(n, 8), 255))
wputb(band(shr(n, 16), 255))
wputb(shr(n, 24))
local sign = n < 0 and 255 or 0
wputb(sign); wputb(sign); wputb(sign); wputb(sign)
else
waction("IMM_D", format("(unsigned int)(%s)", n))
waction("IMM_D", format("(unsigned int)((unsigned long long)(%s)>>32)", n))
end
end
-- Put operand-size dependent number or arg (defaults to dword). -- Put operand-size dependent number or arg (defaults to dword).
local function wputszarg(sz, n) local function wputszarg(sz, n)
if not sz or sz == "d" or sz == "q" then wputdarg(n) if not sz or sz == "d" or sz == "q" then wputdarg(n)
@@ -663,10 +679,16 @@ local function opmodestr(op, args)
end end
-- Convert number to valid integer or nil. -- Convert number to valid integer or nil.
local function toint(expr) local function toint(expr, isqword)
local n = tonumber(expr) local n = tonumber(expr)
if n then if n then
if n % 1 ~= 0 or n < -2147483648 or n > 4294967295 then if n % 1 ~= 0 then
werror("not an integer number `"..expr.."'")
elseif isqword then
if n < -2147483648 or n > 2147483647 then
n = nil -- Handle it as an expression to avoid precision loss.
end
elseif n < -2147483648 or n > 4294967295 then
werror("bad integer number `"..expr.."'") werror("bad integer number `"..expr.."'")
end end
return n return n
@@ -749,7 +771,7 @@ local function rtexpr(expr)
end end
-- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }. -- Parse operand and return { mode, opsize, reg, xreg, xsc, disp, imm }.
local function parseoperand(param) local function parseoperand(param, isqword)
local t = {} local t = {}
local expr = param local expr = param
@@ -810,7 +832,7 @@ local function parseoperand(param)
if t.disp then break end if t.disp then break end
-- [reg+xreg...] -- [reg+xreg...]
local xreg, tailx = match(tailr, "^+%s*([@%w_:]+)%s*(.*)$") local xreg, tailx = match(tailr, "^%+%s*([@%w_:]+)%s*(.*)$")
xreg, t.xreg, tp = rtexpr(xreg) xreg, t.xreg, tp = rtexpr(xreg)
if not t.xreg then if not t.xreg then
-- [reg+-expr] -- [reg+-expr]
@@ -837,7 +859,7 @@ local function parseoperand(param)
t.disp = dispexpr(tailx) t.disp = dispexpr(tailx)
else else
-- imm or opsize*imm -- imm or opsize*imm
local imm = toint(expr) local imm = toint(expr, isqword)
if not imm and sub(expr, 1, 1) == "*" and t.opsize then if not imm and sub(expr, 1, 1) == "*" and t.opsize then
imm = toint(sub(expr, 2)) imm = toint(sub(expr, 2))
if imm then if imm then
@@ -1952,7 +1974,7 @@ local function dopattern(pat, args, sz, op, needrex)
local a = args[narg] local a = args[narg]
narg = narg + 1 narg = narg + 1
local mode, imm = a.mode, a.imm local mode, imm = a.mode, a.imm
if mode == "iJ" and not match("iIJ", c) then if mode == "iJ" and not match(x64 and "J" or "iIJ", c) then
werror("bad operand size for label") werror("bad operand size for label")
end end
if c == "S" then if c == "S" then
@@ -2144,14 +2166,16 @@ end
local function op_data(params) local function op_data(params)
if not params then return "imm..." end if not params then return "imm..." end
local sz = sub(params.op, 2, 2) local sz = sub(params.op, 2, 2)
if sz == "a" then sz = addrsize end if sz == "l" then sz = "d" elseif sz == "a" then sz = addrsize end
for _,p in ipairs(params) do for _,p in ipairs(params) do
local a = parseoperand(p) local a = parseoperand(p, sz == "q")
if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then if sub(a.mode, 1, 1) ~= "i" or (a.opsize and a.opsize ~= sz) then
werror("bad mode or size in `"..p.."'") werror("bad mode or size in `"..p.."'")
end end
if a.mode == "iJ" then if a.mode == "iJ" then
wputlabel("IMM_", a.imm, 1) wputlabel("IMM_", a.imm, 1)
elseif sz == "q" then
wputqarg(a.imm)
else else
wputszarg(sz, a.imm) wputszarg(sz, a.imm)
end end
@@ -2163,7 +2187,11 @@ map_op[".byte_*"] = op_data
map_op[".sbyte_*"] = op_data map_op[".sbyte_*"] = op_data
map_op[".word_*"] = op_data map_op[".word_*"] = op_data
map_op[".dword_*"] = op_data map_op[".dword_*"] = op_data
map_op[".qword_*"] = op_data
map_op[".aword_*"] = op_data map_op[".aword_*"] = op_data
map_op[".long_*"] = op_data
map_op[".quad_*"] = op_data
map_op[".addr_*"] = op_data
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
+5 -5
View File
@@ -2,7 +2,7 @@
-- DynASM. A dynamic assembler for code generation engines. -- DynASM. A dynamic assembler for code generation engines.
-- Originally designed and implemented for LuaJIT. -- Originally designed and implemented for LuaJIT.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- See below for full copyright notice. -- See below for full copyright notice.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@@ -10,14 +10,14 @@
local _info = { local _info = {
name = "DynASM", name = "DynASM",
description = "A dynamic assembler for code generation engines", description = "A dynamic assembler for code generation engines",
version = "1.4.0", version = "1.5.0",
vernum = 10400, vernum = 10500,
release = "2015-10-18", release = "2021-05-02",
author = "Mike Pall", author = "Mike Pall",
url = "https://luajit.org/dynasm.html", url = "https://luajit.org/dynasm.html",
license = "MIT", license = "MIT",
copyright = [[ copyright = [[
Copyright (C) 2005-2020 Mike Pall. All rights reserved. Copyright (C) 2005-2021 Mike Pall. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
+1 -1
View File
@@ -74,7 +74,7 @@ luajit \-jv \-e "for i=1,10 do for j=1,10 do for k=1,100 do end end end"
Runs some nested loops and shows the resulting traces. Runs some nested loops and shows the resulting traces.
.SH COPYRIGHT .SH COPYRIGHT
.PP .PP
\fBLuaJIT\fR is Copyright \(co 2005-2020 Mike Pall. \fBLuaJIT\fR is Copyright \(co 2005-2021 Mike Pall.
.br .br
\fBLuaJIT\fR is open source software, released under the MIT license. \fBLuaJIT\fR is open source software, released under the MIT license.
.SH SEE ALSO .SH SEE ALSO
+15 -8
View File
@@ -7,7 +7,7 @@
# Also works with MinGW and Cygwin on Windows. # Also works with MinGW and Cygwin on Windows.
# Please check msvcbuild.bat for building with MSVC on Windows. # Please check msvcbuild.bat for building with MSVC on Windows.
# #
# Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h # Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
############################################################################## ##############################################################################
MAJVER= 2 MAJVER= 2
@@ -211,7 +211,7 @@ TARGET_CC= $(STATIC_CC)
TARGET_STCC= $(STATIC_CC) TARGET_STCC= $(STATIC_CC)
TARGET_DYNCC= $(DYNAMIC_CC) TARGET_DYNCC= $(DYNAMIC_CC)
TARGET_LD= $(CROSS)$(CC) TARGET_LD= $(CROSS)$(CC)
TARGET_AR= $(CROSS)ar rcus 2>/dev/null TARGET_AR= $(CROSS)ar rcus
TARGET_STRIP= $(CROSS)strip TARGET_STRIP= $(CROSS)strip
TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib) TARGET_LIBPATH= $(or $(PREFIX),/usr/local)/$(or $(MULTILIB),lib)
@@ -311,6 +311,7 @@ ifeq (Windows,$(TARGET_SYS))
TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME) TARGET_XSHLDFLAGS= -shared -Wl,--out-implib,$(TARGET_DLLDOTANAME)
TARGET_DYNXLDOPTS= TARGET_DYNXLDOPTS=
else else
TARGET_AR+= 2>/dev/null
ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1)) ifeq (,$(shell $(TARGET_CC) -o /dev/null -c -x c /dev/null -fno-stack-protector 2>/dev/null || echo 1))
TARGET_XCFLAGS+= -fno-stack-protector TARGET_XCFLAGS+= -fno-stack-protector
endif endif
@@ -319,13 +320,10 @@ ifeq (Darwin,$(TARGET_SYS))
$(error missing: export MACOSX_DEPLOYMENT_TARGET=XX.YY) $(error missing: export MACOSX_DEPLOYMENT_TARGET=XX.YY)
endif endif
TARGET_STRIP+= -x TARGET_STRIP+= -x
TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL
TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC TARGET_XSHLDFLAGS= -dynamiclib -single_module -undefined dynamic_lookup -fPIC
TARGET_DYNXLDOPTS= TARGET_DYNXLDOPTS=
TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER) TARGET_XSHLDFLAGS+= -install_name $(TARGET_DYLIBPATH) -compatibility_version $(MAJVER).$(MINVER) -current_version $(MAJVER).$(MINVER).$(RELVER)
ifeq (x64,$(TARGET_LJARCH))
TARGET_XLDFLAGS+= -pagezero_size 10000 -image_base 100000000
TARGET_XSHLDFLAGS+= -image_base 7fff04c4a000
endif
else else
ifeq (iOS,$(TARGET_SYS)) ifeq (iOS,$(TARGET_SYS))
TARGET_STRIP+= -x TARGET_STRIP+= -x
@@ -336,6 +334,13 @@ ifeq (iOS,$(TARGET_SYS))
TARGET_XCFLAGS+= -fno-omit-frame-pointer TARGET_XCFLAGS+= -fno-omit-frame-pointer
endif endif
else else
ifeq (,$(findstring LJ_NO_UNWIND 1,$(TARGET_TESTARCH)))
# Find out whether the target toolchain always generates unwind tables.
TARGET_TESTUNWIND=$(shell exec 2>/dev/null; echo 'extern void b(void);int a(void){b();return 0;}' | $(TARGET_CC) -c -x c - -o tmpunwind.o && { grep -qa -e eh_frame -e __unwind_info tmpunwind.o || grep -qU -e eh_frame -e __unwind_info tmpunwind.o; } && echo E; rm -f tmpunwind.o)
ifneq (,$(findstring E,$(TARGET_TESTUNWIND)))
TARGET_XCFLAGS+= -DLUAJIT_UNWIND_EXTERNAL
endif
endif
ifneq (SunOS,$(TARGET_SYS)) ifneq (SunOS,$(TARGET_SYS))
ifneq (PS3,$(TARGET_SYS)) ifneq (PS3,$(TARGET_SYS))
TARGET_XLDFLAGS+= -Wl,-E TARGET_XLDFLAGS+= -Wl,-E
@@ -479,13 +484,15 @@ LJVM_BOUT= $(LJVM_S)
LJVM_MODE= elfasm LJVM_MODE= elfasm
LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \ LJLIB_O= lib_base.o lib_math.o lib_bit.o lib_string.o lib_table.o \
lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o lib_io.o lib_os.o lib_package.o lib_debug.o lib_jit.o lib_ffi.o \
lib_buffer.o
LJLIB_C= $(LJLIB_O:.o=.c) LJLIB_C= $(LJLIB_O:.o=.c)
LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ LJCORE_O= lj_assert.o lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \ lj_prng.o lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o \
lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \ lj_strscan.o lj_strfmt.o lj_strfmt_num.o lj_serialize.o \
lj_api.o lj_profile.o \
lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
+41 -33
View File
@@ -2,14 +2,18 @@ lib_aux.o: lib_aux.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \ lj_arch.h lj_err.h lj_errmsg.h lj_state.h lj_trace.h lj_jit.h lj_ir.h \
lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_lib.h
lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lib_base.o: lib_base.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_str.h \ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h \
lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h lj_cconv.h \ lj_str.h lj_tab.h lj_meta.h lj_state.h lj_frame.h lj_bc.h lj_ctype.h \
lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h lj_strscan.h \ lj_cconv.h lj_ff.h lj_ffdef.h lj_dispatch.h lj_jit.h lj_ir.h lj_char.h \
lj_strfmt.h lj_lib.h lj_libdef.h lj_strscan.h lj_strfmt.h lj_lib.h lj_libdef.h
lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \ lib_bit.o: lib_bit.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h lj_def.h \
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \ lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_strscan.h \
lj_strfmt.h lj_ctype.h lj_cdata.h lj_cconv.h lj_carith.h lj_ff.h \ lj_strfmt.h lj_ctype.h lj_cdata.h lj_cconv.h lj_carith.h lj_ff.h \
lj_ffdef.h lj_lib.h lj_libdef.h lj_ffdef.h lj_lib.h lj_libdef.h
lib_buffer.o: lib_buffer.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
lj_tab.h lj_udata.h lj_meta.h lj_ctype.h lj_cdata.h lj_cconv.h \
lj_strfmt.h lj_serialize.h lj_lib.h lj_libdef.h
lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \ lib_debug.o: lib_debug.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \ lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_lib.h \
lj_libdef.h lj_libdef.h
@@ -48,10 +52,10 @@ lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \ lj_meta.h lj_state.h lj_bc.h lj_frame.h lj_trace.h lj_jit.h lj_ir.h \
lj_dispatch.h lj_traceerr.h lj_vm.h lj_strscan.h lj_strfmt.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_strscan.h lj_strfmt.h
lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_asm.o: lj_asm.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h lj_jit.h \ lj_buf.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ctype.h lj_ir.h \
lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h lj_traceerr.h \ lj_jit.h lj_ircall.h lj_iropt.h lj_mcode.h lj_trace.h lj_dispatch.h \
lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h lj_emit_*.h \ lj_traceerr.h lj_snap.h lj_asm.h lj_vm.h lj_target.h lj_target_*.h \
lj_asm_*.h lj_emit_*.h lj_asm_*.h
lj_assert.o: lj_assert.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_assert.o: lj_assert.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \ lj_bc.o: lj_bc.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_bc.h \
lj_bcdef.h lj_bcdef.h
@@ -77,8 +81,8 @@ lj_ccallback.o: lj_ccallback.c lj_obj.h lua.h luaconf.h lj_def.h \
lj_target_*.h lj_mcode.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h \ lj_target_*.h lj_mcode.h lj_jit.h lj_ir.h lj_trace.h lj_dispatch.h \
lj_traceerr.h lj_vm.h lj_traceerr.h lj_vm.h
lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_cconv.o: lj_cconv.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_gc.h lj_cdata.h lj_cconv.h \ lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h lj_ctype.h \
lj_ccallback.h lj_cdata.h lj_cconv.h lj_ccallback.h
lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_cdata.o: lj_cdata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_cconv.h lj_cdata.h lj_gc.h lj_err.h lj_errmsg.h lj_tab.h lj_ctype.h lj_cconv.h lj_cdata.h
lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h lj_char.o: lj_char.c lj_char.h lj_def.h lua.h luaconf.h
@@ -110,10 +114,10 @@ lj_err.o: lj_err.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_err.h \
lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ lj_ff.h lj_ffdef.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
lj_traceerr.h lj_vm.h lj_strfmt.h lj_traceerr.h lj_vm.h lj_strfmt.h
lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_ffrecord.o: lj_ffrecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_frame.h lj_bc.h lj_ff.h \ lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h lj_frame.h \
lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h lj_trace.h \ lj_bc.h lj_ff.h lj_ffdef.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h lj_crecord.h \ lj_trace.h lj_dispatch.h lj_traceerr.h lj_record.h lj_ffrecord.h \
lj_vm.h lj_strscan.h lj_strfmt.h lj_recdef.h lj_crecord.h lj_vm.h lj_strscan.h lj_strfmt.h lj_serialize.h lj_recdef.h
lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_func.o: lj_func.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \ lj_func.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h lj_bc.h \
lj_traceerr.h lj_vm.h lj_traceerr.h lj_vm.h
@@ -127,15 +131,15 @@ lj_gdbjit.o: lj_gdbjit.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_ir.o: lj_ir.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \ lj_buf.h lj_str.h lj_tab.h lj_ir.h lj_jit.h lj_ircall.h lj_iropt.h \
lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \ lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_ctype.h lj_cdata.h \
lj_carith.h lj_vm.h lj_strscan.h lj_strfmt.h lj_prng.h lj_carith.h lj_vm.h lj_strscan.h lj_serialize.h lj_strfmt.h lj_prng.h
lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_lex.o: lj_lex.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \ lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_ctype.h lj_cdata.h \
lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \ lualib.h lj_state.h lj_lex.h lj_parse.h lj_char.h lj_strscan.h \
lj_strfmt.h lj_strfmt.h
lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \ lj_lib.o: lj_lib.c lauxlib.h lua.h luaconf.h lj_obj.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \ lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_func.h lj_bc.h \
lj_dispatch.h lj_jit.h lj_ir.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lex.h \ lj_dispatch.h lj_jit.h lj_ir.h lj_ctype.h lj_vm.h lj_strscan.h \
lj_bcdump.h lj_lib.h lj_strfmt.h lj_lex.h lj_bcdump.h lj_lib.h
lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \ lj_load.o: lj_load.c lua.h luaconf.h lauxlib.h lj_obj.h lj_def.h \
lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \ lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_func.h \
lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h lj_frame.h lj_bc.h lj_vm.h lj_lex.h lj_bcdump.h lj_parse.h
@@ -170,15 +174,18 @@ lj_parse.o: lj_parse.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \ lj_gc.h lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_str.h lj_tab.h \
lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \ lj_func.h lj_state.h lj_bc.h lj_ctype.h lj_strfmt.h lj_lex.h lj_parse.h \
lj_vm.h lj_vmevent.h lj_vm.h lj_vmevent.h
lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \ lj_buf.h lj_gc.h lj_str.h lj_frame.h lj_bc.h lj_debug.h lj_dispatch.h \
lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
lj_prng.o: lj_prng.c lj_def.h lua.h luaconf.h lj_arch.h lj_prng.h
lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \ lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \ lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \ lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h
lj_serialize.o: lj_serialize.c lj_obj.h lua.h luaconf.h lj_def.h \
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
lj_udata.h lj_ctype.h lj_cdata.h lj_ir.h lj_serialize.h
lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_snap.o: lj_snap.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \ lj_tab.h lj_state.h lj_frame.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h \
lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \ lj_trace.h lj_dispatch.h lj_traceerr.h lj_snap.h lj_target.h \
@@ -189,9 +196,10 @@ lj_state.o: lj_state.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \ lj_ir.h lj_dispatch.h lj_traceerr.h lj_vm.h lj_prng.h lj_lex.h \
lj_alloc.h luajit.h lj_alloc.h luajit.h
lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_err.h lj_errmsg.h lj_str.h lj_char.h lj_err.h lj_errmsg.h lj_str.h lj_char.h lj_prng.h
lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_meta.h lj_state.h \
lj_char.h lj_strfmt.h lj_ctype.h lj_lib.h
lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \ lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \
lj_arch.h lj_buf.h lj_gc.h lj_str.h lj_strfmt.h lj_arch.h lj_buf.h lj_gc.h lj_str.h lj_strfmt.h
lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
@@ -204,7 +212,7 @@ lj_trace.o: lj_trace.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \ lj_dispatch.h lj_traceerr.h lj_snap.h lj_gdbjit.h lj_record.h lj_asm.h \
lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h lj_vm.h lj_vmevent.h lj_target.h lj_target_*.h lj_prng.h
lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_udata.o: lj_udata.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_gc.h lj_udata.h lj_gc.h lj_err.h lj_errmsg.h lj_udata.h
lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_vmevent.o: lj_vmevent.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_str.h lj_tab.h lj_state.h lj_dispatch.h lj_bc.h lj_jit.h lj_ir.h \ lj_str.h lj_tab.h lj_state.h lj_dispatch.h lj_bc.h lj_jit.h lj_ir.h \
lj_vm.h lj_vmevent.h lj_vm.h lj_vmevent.h
@@ -216,23 +224,23 @@ ljamalg.o: ljamalg.c lua.h luaconf.h lauxlib.h lj_assert.c lj_obj.h \
lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \ lj_bc.h lj_ctype.h lj_cdata.h lj_trace.h lj_jit.h lj_ir.h lj_dispatch.h \
lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \ lj_traceerr.h lj_vm.h lj_err.c lj_debug.h lj_ff.h lj_ffdef.h lj_strfmt.h \
lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \ lj_char.c lj_char.h lj_bc.c lj_bcdef.h lj_obj.c lj_buf.c lj_str.c \
lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h lj_debug.c \ lj_prng.h lj_tab.c lj_func.c lj_udata.c lj_meta.c lj_strscan.h lj_lib.h \
lj_prng.c lj_prng.h lj_state.c lj_lex.h lj_alloc.h luajit.h \ lj_debug.c lj_prng.c lj_state.c lj_lex.h lj_alloc.h luajit.h \
lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \ lj_dispatch.c lj_ccallback.h lj_profile.h lj_vmevent.c lj_vmevent.h \
lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_api.c \ lj_vmmath.c lj_strscan.c lj_strfmt.c lj_strfmt_num.c lj_serialize.c \
lj_profile.c lj_lex.c lualib.h lj_parse.h lj_parse.c lj_bcread.c \ lj_serialize.h lj_api.c lj_profile.c lj_lex.c lualib.h lj_parse.h \
lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c lj_cdata.c lj_cconv.h \ lj_parse.c lj_bcread.c lj_bcdump.h lj_bcwrite.c lj_load.c lj_ctype.c \
lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c lj_target.h \ lj_cdata.c lj_cconv.h lj_cconv.c lj_ccall.c lj_ccall.h lj_ccallback.c \
lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c lj_clib.h \ lj_target.h lj_target_*.h lj_mcode.h lj_carith.c lj_carith.h lj_clib.c \
lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h lj_iropt.h \ lj_clib.h lj_cparse.c lj_cparse.h lj_lib.c lj_ir.c lj_ircall.h \
lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c lj_opt_dce.c \ lj_iropt.h lj_opt_mem.c lj_opt_fold.c lj_folddef.h lj_opt_narrow.c \
lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c lj_mcode.c \ lj_opt_dce.c lj_opt_loop.c lj_snap.h lj_opt_split.c lj_opt_sink.c \
lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \ lj_mcode.c lj_snap.c lj_record.c lj_record.h lj_ffrecord.h lj_crecord.c \
lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \ lj_crecord.h lj_ffrecord.c lj_recdef.h lj_asm.c lj_asm.h lj_emit_*.h \
lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \ lj_asm_*.h lj_trace.c lj_gdbjit.h lj_gdbjit.c lj_alloc.c lib_aux.c \
lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \ lib_base.c lj_libdef.h lib_math.c lib_string.c lib_table.c lib_io.c \
lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \ lib_os.c lib_package.c lib_debug.c lib_bit.c lib_jit.c lib_ffi.c \
lib_init.c lib_buffer.c lib_init.c
luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h luajit.o: luajit.c lua.h luaconf.h lauxlib.h lualib.h luajit.h lj_arch.h
host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \ host/buildvm.o: host/buildvm.c host/buildvm.h lj_def.h lua.h luaconf.h \
lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \ lj_arch.h lj_obj.h lj_def.h lj_arch.h lj_gc.h lj_obj.h lj_bc.h lj_ir.h \
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** LuaJIT VM builder. ** LuaJIT VM builder.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** This is a tool to build the hand-tuned assembler code required for ** This is a tool to build the hand-tuned assembler code required for
** LuaJIT's bytecode interpreter. It supports a variety of output formats ** LuaJIT's bytecode interpreter. It supports a variety of output formats
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** LuaJIT VM builder. ** LuaJIT VM builder.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#ifndef _BUILDVM_H #ifndef _BUILDVM_H
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** LuaJIT VM builder: Assembler source code emitter. ** LuaJIT VM builder: Assembler source code emitter.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#include "buildvm.h" #include "buildvm.h"
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** LuaJIT VM builder: IR folding hash table generator. ** LuaJIT VM builder: IR folding hash table generator.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#include "buildvm.h" #include "buildvm.h"
+3 -1
View File
@@ -1,6 +1,6 @@
/* /*
** LuaJIT VM builder: library definition compiler. ** LuaJIT VM builder: library definition compiler.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#include "buildvm.h" #include "buildvm.h"
@@ -385,6 +385,8 @@ void emit_lib(BuildCtx *ctx)
ok = LJ_HASJIT; ok = LJ_HASJIT;
else if (!strcmp(buf, "#if LJ_HASFFI\n")) else if (!strcmp(buf, "#if LJ_HASFFI\n"))
ok = LJ_HASFFI; ok = LJ_HASFFI;
else if (!strcmp(buf, "#if LJ_HASBUFFER\n"))
ok = LJ_HASBUFFER;
if (!ok) { if (!ok) {
int lvl = 1; int lvl = 1;
while (fgets(buf, sizeof(buf), fp) != NULL) { while (fgets(buf, sizeof(buf), fp) != NULL) {
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** LuaJIT VM builder: PE object emitter. ** LuaJIT VM builder: PE object emitter.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Only used for building on Windows, since we cannot assume the presence ** Only used for building on Windows, since we cannot assume the presence
** of a suitable assembler. The host and target byte order must match. ** of a suitable assembler. The host and target byte order must match.
+1 -1
View File
@@ -2,7 +2,7 @@
-- Lua script to dump the bytecode of the library functions written in Lua. -- Lua script to dump the bytecode of the library functions written in Lua.
-- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT. -- The resulting 'buildvm_libbc.h' is used for the build process of LuaJIT.
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
+1 -1
View File
@@ -2,7 +2,7 @@
-- Lua script to generate a customized, minified version of Lua. -- Lua script to generate a customized, minified version of Lua.
-- The resulting 'minilua' is used for the build process of LuaJIT. -- The resulting 'minilua' is used for the build process of LuaJIT.
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
+1 -1
View File
@@ -1134,7 +1134,7 @@ if(!cl->isC){
CallInfo*ci; CallInfo*ci;
StkId st,base; StkId st,base;
Proto*p=cl->p; Proto*p=cl->p;
luaD_checkstack(L,p->maxstacksize); luaD_checkstack(L,p->maxstacksize+p->numparams);
func=restorestack(L,funcr); func=restorestack(L,funcr);
if(!p->is_vararg){ if(!p->is_vararg){
base=func+1; base=func+1;
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT bytecode listing module. -- LuaJIT bytecode listing module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- --
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT module to save/list bytecode. -- LuaJIT module to save/list bytecode.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- --
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT ARM disassembler module. -- LuaJIT ARM disassembler module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This is a helper module used by the LuaJIT machine code dumper module. -- This is a helper module used by the LuaJIT machine code dumper module.
+2 -2
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT ARM64 disassembler module. -- LuaJIT ARM64 disassembler module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
-- --
-- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com. -- Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
@@ -1089,7 +1089,7 @@ local function disass_ins(ctx)
last = "#"..(sf+32 - immr) last = "#"..(sf+32 - immr)
operands[#operands] = last operands[#operands] = last
x = x + 1 x = x + 1
elseif x >= immr then else
name = a2 name = a2
x = x - immr + 1 x = x - immr + 1
end end
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT ARM64BE disassembler wrapper module. -- LuaJIT ARM64BE disassembler wrapper module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- ARM64 instructions are always little-endian. So just forward to the -- ARM64 instructions are always little-endian. So just forward to the
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT MIPS disassembler module. -- LuaJIT MIPS disassembler module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT/X license. See Copyright Notice in luajit.h -- Released under the MIT/X license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This is a helper module used by the LuaJIT machine code dumper module. -- This is a helper module used by the LuaJIT machine code dumper module.
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT MIPS64 disassembler wrapper module. -- LuaJIT MIPS64 disassembler wrapper module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This module just exports the big-endian functions from the -- This module just exports the big-endian functions from the
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT MIPS64EL disassembler wrapper module. -- LuaJIT MIPS64EL disassembler wrapper module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This module just exports the little-endian functions from the -- This module just exports the little-endian functions from the
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT MIPS64R6 disassembler wrapper module. -- LuaJIT MIPS64R6 disassembler wrapper module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This module just exports the r6 big-endian functions from the -- This module just exports the r6 big-endian functions from the
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT MIPS64R6EL disassembler wrapper module. -- LuaJIT MIPS64R6EL disassembler wrapper module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This module just exports the r6 little-endian functions from the -- This module just exports the r6 little-endian functions from the
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT MIPSEL disassembler wrapper module. -- LuaJIT MIPSEL disassembler wrapper module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This module just exports the little-endian functions from the -- This module just exports the little-endian functions from the
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT PPC disassembler module. -- LuaJIT PPC disassembler module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT/X license. See Copyright Notice in luajit.h -- Released under the MIT/X license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This is a helper module used by the LuaJIT machine code dumper module. -- This is a helper module used by the LuaJIT machine code dumper module.
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT x64 disassembler wrapper module. -- LuaJIT x64 disassembler wrapper module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This module just exports the 64 bit functions from the combined -- This module just exports the 64 bit functions from the combined
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT x86/x64 disassembler module. -- LuaJIT x86/x64 disassembler module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- This is a helper module used by the LuaJIT machine code dumper module. -- This is a helper module used by the LuaJIT machine code dumper module.
+26 -14
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT compiler dump module. -- LuaJIT compiler dump module.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- --
@@ -102,10 +102,12 @@ end
local function fillsymtab(tr, nexit) local function fillsymtab(tr, nexit)
local t = symtab local t = symtab
if nexitsym == 0 then if nexitsym == 0 then
local maskaddr = jit.arch == "arm" and -2
local ircall = vmdef.ircall local ircall = vmdef.ircall
for i=0,#ircall do for i=0,#ircall do
local addr = ircalladdr(i) local addr = ircalladdr(i)
if addr ~= 0 then if addr ~= 0 then
if maskaddr then addr = band(addr, maskaddr) end
if addr < 0 then addr = addr + 2^32 end if addr < 0 then addr = addr + 2^32 end
t[addr] = ircall[i] t[addr] = ircall[i]
end end
@@ -217,8 +219,10 @@ local function colorize_text(s)
return s return s
end end
local function colorize_ansi(s, t) local function colorize_ansi(s, t, extra)
return format(colortype_ansi[t], s) local out = format(colortype_ansi[t], s)
if extra then out = "\027[3m"..out end
return out
end end
local irtype_ansi = setmetatable({}, local irtype_ansi = setmetatable({},
@@ -227,9 +231,10 @@ local irtype_ansi = setmetatable({},
local html_escape = { ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;", } local html_escape = { ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;", }
local function colorize_html(s, t) local function colorize_html(s, t, extra)
s = gsub(s, "[<>&]", html_escape) s = gsub(s, "[<>&]", html_escape)
return format('<span class="irt_%s">%s</span>', irtype_text[t], s) return format('<span class="irt_%s%s">%s</span>',
irtype_text[t], extra and " irt_extra" or "", s)
end end
local irtype_html = setmetatable({}, local irtype_html = setmetatable({},
@@ -254,6 +259,7 @@ span.irt_tab { color: #c00000; }
span.irt_udt, span.irt_lud { color: #00c0c0; } span.irt_udt, span.irt_lud { color: #00c0c0; }
span.irt_num { color: #4040c0; } span.irt_num { color: #4040c0; }
span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; } span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b040b0; }
span.irt_extra { font-style: italic; }
</style> </style>
]] ]]
@@ -269,6 +275,7 @@ local litname = {
if band(mode, 8) ~= 0 then s = s.."C" end if band(mode, 8) ~= 0 then s = s.."C" end
if band(mode, 16) ~= 0 then s = s.."R" end if band(mode, 16) ~= 0 then s = s.."R" end
if band(mode, 32) ~= 0 then s = s.."I" end if band(mode, 32) ~= 0 then s = s.."I" end
if band(mode, 64) ~= 0 then s = s.."K" end
t[mode] = s t[mode] = s
return s return s
end}), end}),
@@ -277,15 +284,18 @@ local litname = {
local s = irtype[band(mode, 31)] local s = irtype[band(mode, 31)]
s = irtype[band(shr(mode, 5), 31)].."."..s s = irtype[band(shr(mode, 5), 31)].."."..s
if band(mode, 0x800) ~= 0 then s = s.." sext" end if band(mode, 0x800) ~= 0 then s = s.." sext" end
local c = shr(mode, 14) local c = shr(mode, 12)
if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end if c == 1 then s = s.." none"
elseif c == 2 then s = s.." index"
elseif c == 3 then s = s.." check" end
t[mode] = s t[mode] = s
return s return s
end}), end}),
["FLOAD "] = vmdef.irfield, ["FLOAD "] = vmdef.irfield,
["FREF "] = vmdef.irfield, ["FREF "] = vmdef.irfield,
["FPMATH"] = vmdef.irfpm, ["FPMATH"] = vmdef.irfpm,
["BUFHDR"] = { [0] = "RESET", "APPEND" }, ["TMPREF"] = { [0] = "", "IN", "OUT", "INOUT", "", "", "OUT2", "INOUT2" },
["BUFHDR"] = { [0] = "RESET", "APPEND", "WRITE" },
["TOSTR "] = { [0] = "INT", "NUM", "CHAR" }, ["TOSTR "] = { [0] = "INT", "NUM", "CHAR" },
} }
@@ -345,7 +355,7 @@ local function formatk(tr, idx, sn)
else else
s = tostring(k) -- For primitives. s = tostring(k) -- For primitives.
end end
s = colorize(format("%-4s", s), t) s = colorize(format("%-4s", s), t, band(sn or 0, 0x100000) ~= 0)
if slot then if slot then
s = format("%s @%d", s, slot) s = format("%s @%d", s, slot)
end end
@@ -365,7 +375,7 @@ local function printsnap(tr, snap)
out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) out:write(colorize(format("%04d/%04d", ref, ref+1), 14))
else else
local m, ot, op1, op2 = traceir(tr, ref) local m, ot, op1, op2 = traceir(tr, ref)
out:write(colorize(format("%04d", ref), band(ot, 31))) out:write(colorize(format("%04d", ref), band(ot, 31), band(sn, 0x100000) ~= 0))
end end
out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME
else else
@@ -584,7 +594,7 @@ local function dump_trace(what, tr, func, pc, otr, oex)
end end
-- Dump recorded bytecode. -- Dump recorded bytecode.
local function dump_record(tr, func, pc, depth, callee) local function dump_record(tr, func, pc, depth)
if depth ~= recdepth then if depth ~= recdepth then
recdepth = depth recdepth = depth
recprefix = rep(" .", depth) recprefix = rep(" .", depth)
@@ -595,7 +605,6 @@ local function dump_record(tr, func, pc, depth, callee)
if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end
else else
line = "0000 "..recprefix.." FUNCC \n" line = "0000 "..recprefix.." FUNCC \n"
callee = func
end end
if pc <= 0 then if pc <= 0 then
out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n") out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n")
@@ -609,12 +618,15 @@ end
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
local gpr64 = jit.arch:match("64")
local fprmips32 = jit.arch == "mips" or jit.arch == "mipsel"
-- Dump taken trace exits. -- Dump taken trace exits.
local function dump_texit(tr, ex, ngpr, nfpr, ...) local function dump_texit(tr, ex, ngpr, nfpr, ...)
out:write("---- TRACE ", tr, " exit ", ex, "\n") out:write("---- TRACE ", tr, " exit ", ex, "\n")
if dumpmode.X then if dumpmode.X then
local regs = {...} local regs = {...}
if jit.arch:sub(-2) == "64" then if gpr64 then
for i=1,ngpr do for i=1,ngpr do
out:write(format(" %016x", regs[i])) out:write(format(" %016x", regs[i]))
if i % 4 == 0 then out:write("\n") end if i % 4 == 0 then out:write("\n") end
@@ -625,7 +637,7 @@ local function dump_texit(tr, ex, ngpr, nfpr, ...)
if i % 8 == 0 then out:write("\n") end if i % 8 == 0 then out:write("\n") end
end end
end end
if jit.arch == "mips" or jit.arch == "mipsel" then if fprmips32 then
for i=1,nfpr,2 do for i=1,nfpr,2 do
out:write(format(" %+17.14g", regs[ngpr+i])) out:write(format(" %+17.14g", regs[ngpr+i]))
if i % 8 == 7 then out:write("\n") end if i % 8 == 7 then out:write("\n") end
+2 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT profiler. -- LuaJIT profiler.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- --
@@ -238,6 +238,7 @@ local function prof_finish()
prof_count1 = nil prof_count1 = nil
prof_count2 = nil prof_count2 = nil
prof_ud = nil prof_ud = nil
if out ~= stdout then out:close() end
end end
end end
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Verbose mode of the LuaJIT compiler. -- Verbose mode of the LuaJIT compiler.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- --
+1 -1
View File
@@ -1,7 +1,7 @@
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- LuaJIT profiler zones. -- LuaJIT profiler zones.
-- --
-- Copyright (C) 2005-2020 Mike Pall. All rights reserved. -- Copyright (C) 2005-2021 Mike Pall. All rights reserved.
-- Released under the MIT license. See Copyright Notice in luajit.h -- Released under the MIT license. See Copyright Notice in luajit.h
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- --
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Auxiliary library for the Lua/C API. ** Auxiliary library for the Lua/C API.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major parts taken verbatim or adapted from the Lua interpreter. ** Major parts taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
+19 -5
View File
@@ -1,6 +1,6 @@
/* /*
** Base and coroutine library. ** Base and coroutine library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
@@ -19,6 +19,7 @@
#include "lj_gc.h" #include "lj_gc.h"
#include "lj_err.h" #include "lj_err.h"
#include "lj_debug.h" #include "lj_debug.h"
#include "lj_buf.h"
#include "lj_str.h" #include "lj_str.h"
#include "lj_tab.h" #include "lj_tab.h"
#include "lj_meta.h" #include "lj_meta.h"
@@ -75,9 +76,10 @@ LJLIB_ASM_(type) LJLIB_REC(.)
/* This solves a circular dependency problem -- change FF_next_N as needed. */ /* This solves a circular dependency problem -- change FF_next_N as needed. */
LJ_STATIC_ASSERT((int)FF_next == FF_next_N); LJ_STATIC_ASSERT((int)FF_next == FF_next_N);
LJLIB_ASM(next) LJLIB_ASM(next) LJLIB_REC(.)
{ {
lj_lib_checktab(L, 1); lj_lib_checktab(L, 1);
lj_err_msg(L, LJ_ERR_NEXTIDX);
return FFH_UNREACHABLE; return FFH_UNREACHABLE;
} }
@@ -406,10 +408,22 @@ LJLIB_CF(load)
GCstr *name = lj_lib_optstr(L, 2); GCstr *name = lj_lib_optstr(L, 2);
GCstr *mode = lj_lib_optstr(L, 3); GCstr *mode = lj_lib_optstr(L, 3);
int status; int status;
if (L->base < L->top && (tvisstr(L->base) || tvisnumber(L->base))) { if (L->base < L->top &&
GCstr *s = lj_lib_checkstr(L, 1); (tvisstr(L->base) || tvisnumber(L->base) || tvisbuf(L->base))) {
const char *s;
MSize len;
if (tvisbuf(L->base)) {
SBufExt *sbx = bufV(L->base);
s = sbx->r;
len = sbufxlen(sbx);
if (!name) name = &G(L)->strempty; /* Buffers are not NUL-terminated. */
} else {
GCstr *str = lj_lib_checkstr(L, 1);
s = strdata(str);
len = str->len;
}
lua_settop(L, 4); /* Ensure env arg exists. */ lua_settop(L, 4); /* Ensure env arg exists. */
status = luaL_loadbufferx(L, strdata(s), s->len, strdata(name ? name : s), status = luaL_loadbufferx(L, s, len, name ? strdata(name) : s,
mode ? strdata(mode) : NULL); mode ? strdata(mode) : NULL);
} else { } else {
lj_lib_checkfunc(L, 1); lj_lib_checkfunc(L, 1);
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Bit manipulation library. ** Bit manipulation library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lib_bit_c #define lib_bit_c
+356
View File
@@ -0,0 +1,356 @@
/*
** Buffer library.
** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/
#define lib_buffer_c
#define LUA_LIB
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
#include "lj_obj.h"
#if LJ_HASBUFFER
#include "lj_gc.h"
#include "lj_err.h"
#include "lj_buf.h"
#include "lj_str.h"
#include "lj_tab.h"
#include "lj_udata.h"
#include "lj_meta.h"
#if LJ_HASFFI
#include "lj_ctype.h"
#include "lj_cdata.h"
#include "lj_cconv.h"
#endif
#include "lj_strfmt.h"
#include "lj_serialize.h"
#include "lj_lib.h"
/* -- Helper functions ---------------------------------------------------- */
/* Check that the first argument is a string buffer. */
static SBufExt *buffer_tobuf(lua_State *L)
{
if (!(L->base < L->top && tvisbuf(L->base)))
lj_err_argtype(L, 1, "buffer");
return bufV(L->base);
}
/* Ditto, but for writers. */
static LJ_AINLINE SBufExt *buffer_tobufw(lua_State *L)
{
SBufExt *sbx = buffer_tobuf(L);
setsbufXL_(sbx, L);
return sbx;
}
#define buffer_toudata(sbx) ((GCudata *)(sbx)-1)
/* -- Buffer methods ------------------------------------------------------ */
#define LJLIB_MODULE_buffer_method
LJLIB_CF(buffer_method_free)
{
SBufExt *sbx = buffer_tobuf(L);
lj_bufx_free(L, sbx);
L->top = L->base+1; /* Chain buffer object. */
return 1;
}
LJLIB_CF(buffer_method_reset) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
lj_bufx_reset(sbx);
L->top = L->base+1; /* Chain buffer object. */
return 1;
}
LJLIB_CF(buffer_method_skip) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
MSize n = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF);
MSize len = sbufxlen(sbx);
if (n < len) {
sbx->r += n;
} else {
sbx->r = sbx->w = sbx->b;
}
L->top = L->base+1; /* Chain buffer object. */
return 1;
}
LJLIB_CF(buffer_method_set) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
GCobj *ref;
const char *p;
MSize len;
#if LJ_HASFFI
if (tviscdata(L->base+1)) {
CTState *cts = ctype_cts(L);
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p,
L->base+1, CCF_ARG(2));
len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF);
} else
#endif
{
GCstr *str = lj_lib_checkstrx(L, 2);
p = strdata(str);
len = str->len;
}
lj_bufx_free(L, sbx);
lj_bufx_set_cow(L, sbx, p, len);
ref = gcV(L->base+1);
setgcref(sbx->cowref, ref);
lj_gc_objbarrier(L, buffer_toudata(sbx), ref);
L->top = L->base+1; /* Chain buffer object. */
return 1;
}
LJLIB_CF(buffer_method_put) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobufw(L);
ptrdiff_t arg, narg = L->top - L->base;
for (arg = 1; arg < narg; arg++) {
cTValue *o = &L->base[arg], *mo = NULL;
retry:
if (tvisstr(o)) {
lj_buf_putstr((SBuf *)sbx, strV(o));
} else if (tvisint(o)) {
lj_strfmt_putint((SBuf *)sbx, intV(o));
} else if (tvisnum(o)) {
lj_strfmt_putfnum((SBuf *)sbx, STRFMT_G14, numV(o));
} else if (tvisbuf(o)) {
SBufExt *sbx2 = bufV(o);
if (sbx2 == sbx) lj_err_arg(L, arg+1, LJ_ERR_BUFFER_SELF);
lj_buf_putmem((SBuf *)sbx, sbx2->r, sbufxlen(sbx2));
} else if (!mo && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
/* Call __tostring metamethod inline. */
copyTV(L, L->top++, mo);
copyTV(L, L->top++, o);
lua_call(L, 1, 1);
o = &L->base[arg]; /* The stack may have been reallocated. */
copyTV(L, &L->base[arg], L->top-1);
L->top = L->base + narg;
goto retry; /* Retry with the result. */
} else {
lj_err_argtype(L, arg+1, "string/number/__tostring");
}
/* Probably not useful to inline other __tostring MMs, e.g. FFI numbers. */
}
L->top = L->base+1; /* Chain buffer object. */
lj_gc_check(L);
return 1;
}
LJLIB_CF(buffer_method_putf) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobufw(L);
lj_strfmt_putarg(L, (SBuf *)sbx, 2, 2);
L->top = L->base+1; /* Chain buffer object. */
lj_gc_check(L);
return 1;
}
LJLIB_CF(buffer_method_get) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
ptrdiff_t arg, narg = L->top - L->base;
if (narg == 1) {
narg++;
setnilV(L->top++); /* get() is the same as get(nil). */
}
for (arg = 1; arg < narg; arg++) {
TValue *o = &L->base[arg];
MSize n = tvisnil(o) ? LJ_MAX_BUF :
(MSize) lj_lib_checkintrange(L, arg+1, 0, LJ_MAX_BUF);
MSize len = sbufxlen(sbx);
if (n > len) n = len;
setstrV(L, o, lj_str_new(L, sbx->r, n));
sbx->r += n;
}
if (sbx->r == sbx->w) sbx->r = sbx->w = sbx->b;
lj_gc_check(L);
return narg-1;
}
#if LJ_HASFFI
LJLIB_CF(buffer_method_putcdata) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobufw(L);
const char *p;
MSize len;
if (tviscdata(L->base+1)) {
CTState *cts = ctype_cts(L);
lj_cconv_ct_tv(cts, ctype_get(cts, CTID_P_CVOID), (uint8_t *)&p,
L->base+1, CCF_ARG(2));
} else {
lj_err_argtype(L, 2, "cdata");
}
len = (MSize)lj_lib_checkintrange(L, 3, 0, LJ_MAX_BUF);
lj_buf_putmem((SBuf *)sbx, p, len);
L->top = L->base+1; /* Chain buffer object. */
return 1;
}
LJLIB_CF(buffer_method_reserve) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobufw(L);
MSize sz = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF);
GCcdata *cd;
lj_buf_more((SBuf *)sbx, sz);
ctype_loadffi(L);
cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR);
*(void **)cdataptr(cd) = sbx->w;
setcdataV(L, L->top++, cd);
setintV(L->top++, sbufleft(sbx));
return 2;
}
LJLIB_CF(buffer_method_commit) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
MSize len = (MSize)lj_lib_checkintrange(L, 2, 0, LJ_MAX_BUF);
if (len > sbufleft(sbx)) lj_err_arg(L, 2, LJ_ERR_NUMRNG);
sbx->w += len;
L->top = L->base+1; /* Chain buffer object. */
return 1;
}
LJLIB_CF(buffer_method_ref) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
GCcdata *cd;
ctype_loadffi(L);
cd = lj_cdata_new_(L, CTID_P_UINT8, CTSIZE_PTR);
*(void **)cdataptr(cd) = sbx->r;
setcdataV(L, L->top++, cd);
setintV(L->top++, sbufxlen(sbx));
return 2;
}
#endif
LJLIB_CF(buffer_method_encode) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobufw(L);
cTValue *o = lj_lib_checkany(L, 2);
lj_serialize_put(sbx, o);
lj_gc_check(L);
L->top = L->base+1; /* Chain buffer object. */
return 1;
}
LJLIB_CF(buffer_method_decode) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobufw(L);
setnilV(L->top++);
sbx->r = lj_serialize_get(sbx, L->top-1);
lj_gc_check(L);
return 1;
}
LJLIB_CF(buffer_method___gc)
{
SBufExt *sbx = buffer_tobuf(L);
lj_bufx_free(L, sbx);
return 0;
}
LJLIB_CF(buffer_method___tostring) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
setstrV(L, L->top-1, lj_str_new(L, sbx->r, sbufxlen(sbx)));
lj_gc_check(L);
return 1;
}
LJLIB_CF(buffer_method___len) LJLIB_REC(.)
{
SBufExt *sbx = buffer_tobuf(L);
setintV(L->top-1, (int32_t)sbufxlen(sbx));
return 1;
}
LJLIB_PUSH("buffer") LJLIB_SET(__metatable)
LJLIB_PUSH(top-1) LJLIB_SET(__index)
/* -- Buffer library functions -------------------------------------------- */
#define LJLIB_MODULE_buffer
LJLIB_PUSH(top-2) LJLIB_SET(!) /* Set environment. */
LJLIB_CF(buffer_new)
{
MSize sz = 0;
int targ = 1;
GCtab *env, *dict_str = NULL, *dict_mt = NULL;
GCudata *ud;
SBufExt *sbx;
if (L->base < L->top && !tvistab(L->base)) {
targ = 2;
if (!tvisnil(L->base))
sz = (MSize)lj_lib_checkintrange(L, 1, 0, LJ_MAX_BUF);
}
if (L->base+targ-1 < L->top) {
GCtab *options = lj_lib_checktab(L, targ);
cTValue *opt_dict, *opt_mt;
opt_dict = lj_tab_getstr(options, lj_str_newlit(L, "dict"));
if (opt_dict && tvistab(opt_dict)) {
dict_str = tabV(opt_dict);
lj_serialize_dict_prep_str(L, dict_str);
}
opt_mt = lj_tab_getstr(options, lj_str_newlit(L, "metatable"));
if (opt_mt && tvistab(opt_mt)) {
dict_mt = tabV(opt_mt);
lj_serialize_dict_prep_mt(L, dict_mt);
}
}
env = tabref(curr_func(L)->c.env);
ud = lj_udata_new(L, sizeof(SBufExt), env);
ud->udtype = UDTYPE_BUFFER;
/* NOBARRIER: The GCudata is new (marked white). */
setgcref(ud->metatable, obj2gco(env));
setudataV(L, L->top++, ud);
sbx = (SBufExt *)uddata(ud);
lj_bufx_init(L, sbx);
setgcref(sbx->dict_str, obj2gco(dict_str));
setgcref(sbx->dict_mt, obj2gco(dict_mt));
if (sz > 0) lj_buf_need2((SBuf *)sbx, sz);
return 1;
}
LJLIB_CF(buffer_encode) LJLIB_REC(.)
{
cTValue *o = lj_lib_checkany(L, 1);
setstrV(L, L->top++, lj_serialize_encode(L, o));
lj_gc_check(L);
return 1;
}
LJLIB_CF(buffer_decode) LJLIB_REC(.)
{
GCstr *str = lj_lib_checkstrx(L, 1);
setnilV(L->top++);
lj_serialize_decode(L, L->top-1, str);
return 1;
}
/* ------------------------------------------------------------------------ */
#include "lj_libdef.h"
int luaopen_string_buffer(lua_State *L)
{
LJ_LIB_REG(L, NULL, buffer_method);
lua_getfield(L, -1, "__tostring");
lua_setfield(L, -2, "tostring");
LJ_LIB_REG(L, NULL, buffer);
return 1;
}
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Debug library. ** Debug library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
+2 -1
View File
@@ -1,6 +1,6 @@
/* /*
** FFI library. ** FFI library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lib_ffi_c #define lib_ffi_c
@@ -573,6 +573,7 @@ LJLIB_CF(ffi_typeinfo)
setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib); setintV(lj_tab_setstr(L, t, lj_str_newlit(L, "sib")), (int32_t)ct->sib);
if (gcref(ct->name)) { if (gcref(ct->name)) {
GCstr *s = gco2str(gcref(ct->name)); GCstr *s = gco2str(gcref(ct->name));
if (isdead(G(L), obj2gco(s))) flipwhite(obj2gco(s));
setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s); setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "name")), s);
} }
lj_gc_check(L); lj_gc_check(L);
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Library initialization. ** Library initialization.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major parts taken verbatim from the Lua interpreter. ** Major parts taken verbatim from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
+20 -14
View File
@@ -1,6 +1,6 @@
/* /*
** I/O library. ** I/O library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2011 Lua.org, PUC-Rio. See Copyright Notice in lua.h
@@ -60,12 +60,12 @@ static IOFileUD *io_tofile(lua_State *L)
return iof; return iof;
} }
static FILE *io_stdfile(lua_State *L, ptrdiff_t id) static IOFileUD *io_stdfile(lua_State *L, ptrdiff_t id)
{ {
IOFileUD *iof = IOSTDF_IOF(L, id); IOFileUD *iof = IOSTDF_IOF(L, id);
if (iof->fp == NULL) if (iof->fp == NULL)
lj_err_caller(L, LJ_ERR_IOSTDCL); lj_err_caller(L, LJ_ERR_IOSTDCL);
return iof->fp; return iof;
} }
static IOFileUD *io_file_new(lua_State *L) static IOFileUD *io_file_new(lua_State *L)
@@ -178,7 +178,7 @@ static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
MSize n = (MSize)fread(buf, 1, m, fp); MSize n = (MSize)fread(buf, 1, m, fp);
setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n)); setstrV(L, L->top++, lj_str_new(L, buf, (size_t)n));
lj_gc_check(L); lj_gc_check(L);
return (n > 0 || m == 0); return n > 0;
} else { } else {
int c = getc(fp); int c = getc(fp);
ungetc(c, fp); ungetc(c, fp);
@@ -187,8 +187,9 @@ static int io_file_readlen(lua_State *L, FILE *fp, MSize m)
} }
} }
static int io_file_read(lua_State *L, FILE *fp, int start) static int io_file_read(lua_State *L, IOFileUD *iof, int start)
{ {
FILE *fp = iof->fp;
int ok, n, nargs = (int)(L->top - L->base) - start; int ok, n, nargs = (int)(L->top - L->base) - start;
clearerr(fp); clearerr(fp);
if (nargs == 0) { if (nargs == 0) {
@@ -224,8 +225,9 @@ static int io_file_read(lua_State *L, FILE *fp, int start)
return n - start; return n - start;
} }
static int io_file_write(lua_State *L, FILE *fp, int start) static int io_file_write(lua_State *L, IOFileUD *iof, int start)
{ {
FILE *fp = iof->fp;
cTValue *tv; cTValue *tv;
int status = 1; int status = 1;
for (tv = L->base+start; tv < L->top; tv++) { for (tv = L->base+start; tv < L->top; tv++) {
@@ -253,13 +255,11 @@ static int io_file_iter(lua_State *L)
lj_err_caller(L, LJ_ERR_IOCLFL); lj_err_caller(L, LJ_ERR_IOCLFL);
L->top = L->base; L->top = L->base;
if (n) { /* Copy upvalues with options to stack. */ if (n) { /* Copy upvalues with options to stack. */
if (n > LUAI_MAXCSTACK)
lj_err_caller(L, LJ_ERR_STKOV);
lj_state_checkstack(L, (MSize)n); lj_state_checkstack(L, (MSize)n);
memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue)); memcpy(L->top, &fn->c.upvalue[1], n*sizeof(TValue));
L->top += n; L->top += n;
} }
n = io_file_read(L, iof->fp, 0); n = io_file_read(L, iof, 0);
if (ferror(iof->fp)) if (ferror(iof->fp))
lj_err_callermsg(L, strVdata(L->top-2)); lj_err_callermsg(L, strVdata(L->top-2));
if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) { if (tvisnil(L->base) && (iof->type & IOFILE_FLAG_CLOSE)) {
@@ -284,19 +284,25 @@ static int io_file_lines(lua_State *L)
LJLIB_CF(io_method_close) LJLIB_CF(io_method_close)
{ {
IOFileUD *iof = L->base < L->top ? io_tofile(L) : IOFileUD *iof;
IOSTDF_IOF(L, GCROOT_IO_OUTPUT); if (L->base < L->top) {
iof = io_tofile(L);
} else {
iof = IOSTDF_IOF(L, GCROOT_IO_OUTPUT);
if (iof->fp == NULL)
lj_err_caller(L, LJ_ERR_IOCLFL);
}
return io_file_close(L, iof); return io_file_close(L, iof);
} }
LJLIB_CF(io_method_read) LJLIB_CF(io_method_read)
{ {
return io_file_read(L, io_tofile(L)->fp, 1); return io_file_read(L, io_tofile(L), 1);
} }
LJLIB_CF(io_method_write) LJLIB_REC(io_write 0) LJLIB_CF(io_method_write) LJLIB_REC(io_write 0)
{ {
return io_file_write(L, io_tofile(L)->fp, 1); return io_file_write(L, io_tofile(L), 1);
} }
LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0) LJLIB_CF(io_method_flush) LJLIB_REC(io_flush 0)
@@ -458,7 +464,7 @@ LJLIB_CF(io_write) LJLIB_REC(io_write GCROOT_IO_OUTPUT)
LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT) LJLIB_CF(io_flush) LJLIB_REC(io_flush GCROOT_IO_OUTPUT)
{ {
return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)) == 0, NULL); return luaL_fileresult(L, fflush(io_stdfile(L, GCROOT_IO_OUTPUT)->fp) == 0, NULL);
} }
static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode) static int io_std_getset(lua_State *L, ptrdiff_t id, const char *mode)
+2 -6
View File
@@ -1,6 +1,6 @@
/* /*
** JIT library. ** JIT library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lib_jit_c #define lib_jit_c
@@ -346,11 +346,7 @@ LJLIB_CF(jit_util_tracek)
ir = &T->ir[ir->op1]; ir = &T->ir[ir->op1];
} }
#if LJ_HASFFI #if LJ_HASFFI
if (ir->o == IR_KINT64 && !ctype_ctsG(G(L))) { if (ir->o == IR_KINT64) ctype_loadffi(L);
ptrdiff_t oldtop = savestack(L, L->top);
luaopen_ffi(L); /* Load FFI library on-demand. */
L->top = restorestack(L, oldtop);
}
#endif #endif
lj_ir_kvalue(L, L->top-2, ir); lj_ir_kvalue(L, L->top-2, ir);
setintV(L->top-1, (int32_t)irt_type(ir->t)); setintV(L->top-1, (int32_t)irt_type(ir->t));
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Math library. ** Math library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#include <math.h> #include <math.h>
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** OS library. ** OS library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Package library. ** Package library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2012 Lua.org, PUC-Rio. See Copyright Notice in lua.h
+9 -81
View File
@@ -1,6 +1,6 @@
/* /*
** String library. ** String library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
@@ -640,89 +640,14 @@ LJLIB_CF(string_gsub)
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* Emulate tostring() inline. */
static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry)
{
TValue *o = L->base+arg-1;
cTValue *mo;
lj_assertL(o < L->top, "bad usage"); /* Caller already checks for existence. */
if (LJ_LIKELY(tvisstr(o)))
return strV(o);
if (retry != 2 && !tvisnil(mo = lj_meta_lookup(L, o, MM_tostring))) {
copyTV(L, L->top++, mo);
copyTV(L, L->top++, o);
lua_call(L, 1, 1);
copyTV(L, L->base+arg-1, --L->top);
return NULL; /* Buffer may be overwritten, retry. */
}
return lj_strfmt_obj(L, o);
}
LJLIB_CF(string_format) LJLIB_REC(.) LJLIB_CF(string_format) LJLIB_REC(.)
{ {
int arg, top = (int)(L->top - L->base);
GCstr *fmt;
SBuf *sb;
FormatState fs;
SFormat sf;
int retry = 0; int retry = 0;
again: SBuf *sb;
arg = 1; do {
sb = lj_buf_tmp_(L); sb = lj_buf_tmp_(L);
fmt = lj_lib_checkstr(L, arg); retry = lj_strfmt_putarg(L, sb, 1, -retry);
lj_strfmt_init(&fs, strdata(fmt), fmt->len); } while (retry > 0);
while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) {
if (sf == STRFMT_LIT) {
lj_buf_putmem(sb, fs.str, fs.len);
} else if (sf == STRFMT_ERR) {
lj_err_callerv(L, LJ_ERR_STRFMT, strdata(lj_str_new(L, fs.str, fs.len)));
} else {
if (++arg > top)
luaL_argerror(L, arg, lj_obj_typename[0]);
switch (STRFMT_TYPE(sf)) {
case STRFMT_INT:
if (tvisint(L->base+arg-1)) {
int32_t k = intV(L->base+arg-1);
if (sf == STRFMT_INT)
lj_strfmt_putint(sb, k); /* Shortcut for plain %d. */
else
lj_strfmt_putfxint(sb, sf, k);
} else {
lj_strfmt_putfnum_int(sb, sf, lj_lib_checknum(L, arg));
}
break;
case STRFMT_UINT:
if (tvisint(L->base+arg-1))
lj_strfmt_putfxint(sb, sf, intV(L->base+arg-1));
else
lj_strfmt_putfnum_uint(sb, sf, lj_lib_checknum(L, arg));
break;
case STRFMT_NUM:
lj_strfmt_putfnum(sb, sf, lj_lib_checknum(L, arg));
break;
case STRFMT_STR: {
GCstr *str = string_fmt_tostring(L, arg, retry);
if (str == NULL)
retry = 1;
else if ((sf & STRFMT_T_QUOTED))
lj_strfmt_putquoted(sb, str); /* No formatting. */
else
lj_strfmt_putfstr(sb, sf, str);
break;
}
case STRFMT_CHAR:
lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg));
break;
case STRFMT_PTR: /* No formatting. */
lj_strfmt_putptr(sb, lj_obj_ptr(G(L), L->base+arg-1));
break;
default:
lj_assertL(0, "bad string format type");
break;
}
}
}
if (retry++ == 1) goto again;
setstrV(L, L->top-1, lj_buf_str(L, sb)); setstrV(L, L->top-1, lj_buf_str(L, sb));
lj_gc_check(L); lj_gc_check(L);
return 1; return 1;
@@ -743,6 +668,9 @@ LUALIB_API int luaopen_string(lua_State *L)
setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt)); setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1)); settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
mt->nomm = (uint8_t)(~(1u<<MM_index)); mt->nomm = (uint8_t)(~(1u<<MM_index));
#if LJ_HASBUFFER
lj_lib_prereg(L, LUA_STRLIBNAME ".buffer", luaopen_string_buffer, tabV(L->top-1));
#endif
return 1; return 1;
} }
+2 -2
View File
@@ -1,6 +1,6 @@
/* /*
** Table library. ** Table library.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
@@ -159,7 +159,7 @@ LJLIB_CF(table_concat) LJLIB_REC(.)
SBuf *sb = lj_buf_tmp_(L); SBuf *sb = lj_buf_tmp_(L);
SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e); SBuf *sbx = lj_buf_puttab(sb, t, sep, i, e);
if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */ if (LJ_UNLIKELY(!sbx)) { /* Error: bad element type. */
int32_t idx = (int32_t)(intptr_t)sbufP(sb); int32_t idx = (int32_t)(intptr_t)sb->w;
cTValue *o = lj_tab_getint(t, idx); cTValue *o = lj_tab_getint(t, idx);
lj_err_callerv(L, LJ_ERR_TABCAT, lj_err_callerv(L, LJ_ERR_TABCAT,
lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx); lj_obj_itypename[o ? itypemap(o) : ~LJ_TNIL], idx);
+1 -1
View File
@@ -365,7 +365,7 @@ static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
#define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv)) #define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
#define CALL_MREMAP_NOMOVE 0 #define CALL_MREMAP_NOMOVE 0
#define CALL_MREMAP_MAYMOVE 1 #define CALL_MREMAP_MAYMOVE 1
#if LJ_64 && !LJ_GC64 #if LJ_64 && (!LJ_GC64 || LJ_TARGET_ARM64)
#define CALL_MREMAP_MV CALL_MREMAP_NOMOVE #define CALL_MREMAP_MV CALL_MREMAP_NOMOVE
#else #else
#define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE #define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE
+8 -32
View File
@@ -1,6 +1,6 @@
/* /*
** Public Lua/C API. ** Public Lua/C API.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Major portions taken verbatim or adapted from the Lua interpreter. ** Major portions taken verbatim or adapted from the Lua interpreter.
** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
@@ -707,36 +707,10 @@ LUA_API void lua_pushboolean(lua_State *L, int b)
incr_top(L); incr_top(L);
} }
#if LJ_64
static void *lightud_intern(lua_State *L, void *p)
{
global_State *g = G(L);
uint64_t u = (uint64_t)p;
uint32_t up = lightudup(u);
uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
MSize segnum = g->gc.lightudnum;
if (segmap) {
MSize seg;
for (seg = 0; seg <= segnum; seg++)
if (segmap[seg] == up) /* Fast path. */
return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
segnum++;
}
if (!((segnum-1) & segnum) && segnum != 1) {
if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)) lj_err_msg(L, LJ_ERR_BADLU);
lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t);
setmref(g->gc.lightudseg, segmap);
}
g->gc.lightudnum = segnum;
segmap[segnum] = up;
return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
}
#endif
LUA_API void lua_pushlightuserdata(lua_State *L, void *p) LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
{ {
#if LJ_64 #if LJ_64
p = lightud_intern(L, p); p = lj_lightud_intern(L, p);
#endif #endif
setrawlightudV(L->top, p); setrawlightudV(L->top, p);
incr_top(L); incr_top(L);
@@ -919,11 +893,13 @@ LUA_API int lua_next(lua_State *L, int idx)
cTValue *t = index2adr(L, idx); cTValue *t = index2adr(L, idx);
int more; int more;
lj_checkapi(tvistab(t), "stack slot %d is not a table", idx); lj_checkapi(tvistab(t), "stack slot %d is not a table", idx);
more = lj_tab_next(L, tabV(t), L->top-1); more = lj_tab_next(tabV(t), L->top-1, L->top-1);
if (more) { if (more > 0) {
incr_top(L); /* Return new key and value slot. */ incr_top(L); /* Return new key and value slot. */
} else { /* End of traversal. */ } else if (!more) { /* End of traversal. */
L->top--; /* Remove key slot. */ L->top--; /* Remove key slot. */
} else {
lj_err_msg(L, LJ_ERR_NEXTIDX);
} }
return more; return more;
} }
@@ -1179,7 +1155,7 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
setfuncV(L, top++, fn); setfuncV(L, top++, fn);
if (LJ_FR2) setnilV(top++); if (LJ_FR2) setnilV(top++);
#if LJ_64 #if LJ_64
ud = lightud_intern(L, ud); ud = lj_lightud_intern(L, ud);
#endif #endif
setrawlightudV(top++, ud); setrawlightudV(top++, ud);
cframe_nres(L->cframe) = 1+0; /* Zero results. */ cframe_nres(L->cframe) = 1+0; /* Zero results. */
+36 -18
View File
@@ -1,6 +1,6 @@
/* /*
** Target architecture selection. ** Target architecture selection.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#ifndef _LJ_ARCH_H #ifndef _LJ_ARCH_H
@@ -170,14 +170,10 @@
#define LJ_ARCH_NAME "x86" #define LJ_ARCH_NAME "x86"
#define LJ_ARCH_BITS 32 #define LJ_ARCH_BITS 32
#define LJ_ARCH_ENDIAN LUAJIT_LE #define LJ_ARCH_ENDIAN LUAJIT_LE
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
#define LJ_ABI_WIN 1
#else
#define LJ_ABI_WIN 0
#endif
#define LJ_TARGET_X86 1 #define LJ_TARGET_X86 1
#define LJ_TARGET_X86ORX64 1 #define LJ_TARGET_X86ORX64 1
#define LJ_TARGET_EHRETREG 0 #define LJ_TARGET_EHRETREG 0
#define LJ_TARGET_EHRAREG 8
#define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKSHIFT 1
#define LJ_TARGET_MASKROT 1 #define LJ_TARGET_MASKROT 1
#define LJ_TARGET_UNALIGNED 1 #define LJ_TARGET_UNALIGNED 1
@@ -188,14 +184,10 @@
#define LJ_ARCH_NAME "x64" #define LJ_ARCH_NAME "x64"
#define LJ_ARCH_BITS 64 #define LJ_ARCH_BITS 64
#define LJ_ARCH_ENDIAN LUAJIT_LE #define LJ_ARCH_ENDIAN LUAJIT_LE
#if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
#define LJ_ABI_WIN 1
#else
#define LJ_ABI_WIN 0
#endif
#define LJ_TARGET_X64 1 #define LJ_TARGET_X64 1
#define LJ_TARGET_X86ORX64 1 #define LJ_TARGET_X86ORX64 1
#define LJ_TARGET_EHRETREG 0 #define LJ_TARGET_EHRETREG 0
#define LJ_TARGET_EHRAREG 16
#define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */ #define LJ_TARGET_JUMPRANGE 31 /* +-2^31 = +-2GB */
#define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKSHIFT 1
#define LJ_TARGET_MASKROT 1 #define LJ_TARGET_MASKROT 1
@@ -203,6 +195,8 @@
#define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL #define LJ_ARCH_NUMMODE LJ_NUMMODE_SINGLE_DUAL
#ifndef LUAJIT_DISABLE_GC64 #ifndef LUAJIT_DISABLE_GC64
#define LJ_TARGET_GC64 1 #define LJ_TARGET_GC64 1
#elif LJ_TARGET_OSX
#error "macOS requires GC64 -- don't disable it"
#endif #endif
#elif LUAJIT_TARGET == LUAJIT_ARCH_ARM #elif LUAJIT_TARGET == LUAJIT_ARCH_ARM
@@ -219,6 +213,7 @@
#define LJ_ABI_EABI 1 #define LJ_ABI_EABI 1
#define LJ_TARGET_ARM 1 #define LJ_TARGET_ARM 1
#define LJ_TARGET_EHRETREG 0 #define LJ_TARGET_EHRETREG 0
#define LJ_TARGET_EHRAREG 14
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
#define LJ_TARGET_MASKSHIFT 0 #define LJ_TARGET_MASKSHIFT 0
#define LJ_TARGET_MASKROT 1 #define LJ_TARGET_MASKROT 1
@@ -249,6 +244,7 @@
#endif #endif
#define LJ_TARGET_ARM64 1 #define LJ_TARGET_ARM64 1
#define LJ_TARGET_EHRETREG 0 #define LJ_TARGET_EHRETREG 0
#define LJ_TARGET_EHRAREG 30
#define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */ #define LJ_TARGET_JUMPRANGE 27 /* +-2^27 = +-128MB */
#define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKSHIFT 1
#define LJ_TARGET_MASKROT 1 #define LJ_TARGET_MASKROT 1
@@ -304,6 +300,7 @@
#define LJ_TARGET_PPC 1 #define LJ_TARGET_PPC 1
#define LJ_TARGET_EHRETREG 3 #define LJ_TARGET_EHRETREG 3
#define LJ_TARGET_EHRAREG 65
#define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */ #define LJ_TARGET_JUMPRANGE 25 /* +-2^25 = +-32MB */
#define LJ_TARGET_MASKSHIFT 0 #define LJ_TARGET_MASKSHIFT 0
#define LJ_TARGET_MASKROT 1 #define LJ_TARGET_MASKROT 1
@@ -406,6 +403,7 @@
#endif #endif
#define LJ_TARGET_MIPS 1 #define LJ_TARGET_MIPS 1
#define LJ_TARGET_EHRETREG 4 #define LJ_TARGET_EHRETREG 4
#define LJ_TARGET_EHRAREG 31
#define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */ #define LJ_TARGET_JUMPRANGE 27 /* 2*2^27 = 256MB-aligned region */
#define LJ_TARGET_MASKSHIFT 1 #define LJ_TARGET_MASKSHIFT 1
#define LJ_TARGET_MASKROT 1 #define LJ_TARGET_MASKROT 1
@@ -551,6 +549,13 @@
#define LJ_HASFFI 1 #define LJ_HASFFI 1
#endif #endif
/* Disable or enable the string buffer extension. */
#if defined(LUAJIT_DISABLE_BUFFER)
#define LJ_HASBUFFER 0
#else
#define LJ_HASBUFFER 1
#endif
#if defined(LUAJIT_DISABLE_PROFILE) #if defined(LUAJIT_DISABLE_PROFILE)
#define LJ_HASPROFILE 0 #define LJ_HASPROFILE 0
#elif LJ_TARGET_POSIX #elif LJ_TARGET_POSIX
@@ -611,13 +616,10 @@
#define LJ_NO_SYSTEM 1 #define LJ_NO_SYSTEM 1
#endif #endif
#if !defined(LUAJIT_NO_UNWIND) && __GNU_COMPACT_EH__ #if LJ_TARGET_WINDOWS || LJ_TARGET_CYGWIN
/* NYI: no support for compact unwind specification, yet. */ #define LJ_ABI_WIN 1
#define LUAJIT_NO_UNWIND 1 #else
#endif #define LJ_ABI_WIN 0
#if defined(LUAJIT_NO_UNWIND) || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
#define LJ_NO_UNWIND 1
#endif #endif
#if LJ_TARGET_WINDOWS #if LJ_TARGET_WINDOWS
@@ -632,6 +634,22 @@ extern void *LJ_WIN_LOADLIBA(const char *path);
#endif #endif
#endif #endif
#if defined(LUAJIT_NO_UNWIND) || __GNU_COMPACT_EH__ || defined(__symbian__) || LJ_TARGET_IOS || LJ_TARGET_PS3 || LJ_TARGET_PS4
#define LJ_NO_UNWIND 1
#endif
#if !LJ_NO_UNWIND && !defined(LUAJIT_UNWIND_INTERNAL) && (LJ_ABI_WIN || (defined(LUAJIT_UNWIND_EXTERNAL) && (defined(__GNUC__) || defined(__clang__))))
#define LJ_UNWIND_EXT 1
#else
#define LJ_UNWIND_EXT 0
#endif
#if LJ_UNWIND_EXT && LJ_HASJIT && !LJ_TARGET_ARM && !(LJ_ABI_WIN && LJ_TARGET_X86)
#define LJ_UNWIND_JIT 1
#else
#define LJ_UNWIND_JIT 0
#endif
/* Compatibility with Lua 5.1 vs. 5.2. */ /* Compatibility with Lua 5.1 vs. 5.2. */
#ifdef LUAJIT_ENABLE_LUA52COMPAT #ifdef LUAJIT_ENABLE_LUA52COMPAT
#define LJ_52 1 #define LJ_52 1
+155 -63
View File
@@ -1,6 +1,6 @@
/* /*
** IR assembler (SSA IR -> machine code). ** IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lj_asm_c #define lj_asm_c
@@ -11,6 +11,7 @@
#if LJ_HASJIT #if LJ_HASJIT
#include "lj_gc.h" #include "lj_gc.h"
#include "lj_buf.h"
#include "lj_str.h" #include "lj_str.h"
#include "lj_tab.h" #include "lj_tab.h"
#include "lj_frame.h" #include "lj_frame.h"
@@ -71,6 +72,8 @@ typedef struct ASMState {
IRRef snaprename; /* Rename highwater mark for snapshot check. */ IRRef snaprename; /* Rename highwater mark for snapshot check. */
SnapNo snapno; /* Current snapshot number. */ SnapNo snapno; /* Current snapshot number. */
SnapNo loopsnapno; /* Loop snapshot number. */ SnapNo loopsnapno; /* Loop snapshot number. */
int snapalloc; /* Current snapshot needs allocation. */
BloomFilter snapfilt1, snapfilt2; /* Filled with snapshot refs. */
IRRef fuseref; /* Fusion limit (loopref, 0 or FUSE_DISABLED). */ IRRef fuseref; /* Fusion limit (loopref, 0 or FUSE_DISABLED). */
IRRef sectref; /* Section base reference (loopref or 0). */ IRRef sectref; /* Section base reference (loopref or 0). */
@@ -84,6 +87,7 @@ typedef struct ASMState {
MCode *mcbot; /* Bottom of reserved MCode. */ MCode *mcbot; /* Bottom of reserved MCode. */
MCode *mctop; /* Top of generated MCode. */ MCode *mctop; /* Top of generated MCode. */
MCode *mctoporig; /* Original top of generated MCode. */
MCode *mcloop; /* Pointer to loop MCode (or NULL). */ MCode *mcloop; /* Pointer to loop MCode (or NULL). */
MCode *invmcp; /* Points to invertible loop branch (or NULL). */ MCode *invmcp; /* Points to invertible loop branch (or NULL). */
MCode *flagmcp; /* Pending opportunity to merge flag setting ins. */ MCode *flagmcp; /* Pending opportunity to merge flag setting ins. */
@@ -694,7 +698,14 @@ static void ra_rename(ASMState *as, Reg down, Reg up)
RA_DBGX((as, "rename $f $r $r", regcost_ref(as->cost[up]), down, up)); RA_DBGX((as, "rename $f $r $r", regcost_ref(as->cost[up]), down, up));
emit_movrr(as, ir, down, up); /* Backwards codegen needs inverse move. */ emit_movrr(as, ir, down, up); /* Backwards codegen needs inverse move. */
if (!ra_hasspill(IR(ref)->s)) { /* Add the rename to the IR. */ if (!ra_hasspill(IR(ref)->s)) { /* Add the rename to the IR. */
ra_addrename(as, down, ref, as->snapno); /*
** The rename is effective at the subsequent (already emitted) exit
** branch. This is for the current snapshot (as->snapno). Except if we
** haven't yet allocated any refs for the snapshot (as->snapalloc == 1),
** then it belongs to the next snapshot.
** See also the discussion at asm_snap_checkrename().
*/
ra_addrename(as, down, ref, as->snapno + as->snapalloc);
} }
} }
@@ -807,11 +818,11 @@ static void ra_leftov(ASMState *as, Reg dest, IRRef lref)
} }
#endif #endif
#if !LJ_64
/* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */ /* Force a RID_RETLO/RID_RETHI destination register pair (marked as free). */
static void ra_destpair(ASMState *as, IRIns *ir) static void ra_destpair(ASMState *as, IRIns *ir)
{ {
Reg destlo = ir->r, desthi = (ir+1)->r; Reg destlo = ir->r, desthi = (ir+1)->r;
IRIns *irx = (LJ_64 && !irt_is64(ir->t)) ? ir+1 : ir;
/* First spill unrelated refs blocking the destination registers. */ /* First spill unrelated refs blocking the destination registers. */
if (!rset_test(as->freeset, RID_RETLO) && if (!rset_test(as->freeset, RID_RETLO) &&
destlo != RID_RETLO && desthi != RID_RETLO) destlo != RID_RETLO && desthi != RID_RETLO)
@@ -835,29 +846,28 @@ static void ra_destpair(ASMState *as, IRIns *ir)
/* Check for conflicts and shuffle the registers as needed. */ /* Check for conflicts and shuffle the registers as needed. */
if (destlo == RID_RETHI) { if (destlo == RID_RETHI) {
if (desthi == RID_RETLO) { if (desthi == RID_RETLO) {
#if LJ_TARGET_X86 #if LJ_TARGET_X86ORX64
*--as->mcp = XI_XCHGa + RID_RETHI; *--as->mcp = REX_64IR(irx, XI_XCHGa + RID_RETHI);
#else #else
emit_movrr(as, ir, RID_RETHI, RID_TMP); emit_movrr(as, irx, RID_RETHI, RID_TMP);
emit_movrr(as, ir, RID_RETLO, RID_RETHI); emit_movrr(as, irx, RID_RETLO, RID_RETHI);
emit_movrr(as, ir, RID_TMP, RID_RETLO); emit_movrr(as, irx, RID_TMP, RID_RETLO);
#endif #endif
} else { } else {
emit_movrr(as, ir, RID_RETHI, RID_RETLO); emit_movrr(as, irx, RID_RETHI, RID_RETLO);
if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI); if (desthi != RID_RETHI) emit_movrr(as, irx, desthi, RID_RETHI);
} }
} else if (desthi == RID_RETLO) { } else if (desthi == RID_RETLO) {
emit_movrr(as, ir, RID_RETLO, RID_RETHI); emit_movrr(as, irx, RID_RETLO, RID_RETHI);
if (destlo != RID_RETLO) emit_movrr(as, ir, destlo, RID_RETLO); if (destlo != RID_RETLO) emit_movrr(as, irx, destlo, RID_RETLO);
} else { } else {
if (desthi != RID_RETHI) emit_movrr(as, ir, desthi, RID_RETHI); if (desthi != RID_RETHI) emit_movrr(as, irx, desthi, RID_RETHI);
if (destlo != RID_RETLO) emit_movrr(as, ir, destlo, RID_RETLO); if (destlo != RID_RETLO) emit_movrr(as, irx, destlo, RID_RETLO);
} }
/* Restore spill slots (if any). */ /* Restore spill slots (if any). */
if (ra_hasspill((ir+1)->s)) ra_save(as, ir+1, RID_RETHI); if (ra_hasspill((ir+1)->s)) ra_save(as, ir+1, RID_RETHI);
if (ra_hasspill(ir->s)) ra_save(as, ir, RID_RETLO); if (ra_hasspill(ir->s)) ra_save(as, ir, RID_RETLO);
} }
#endif
/* -- Snapshot handling --------- ----------------------------------------- */ /* -- Snapshot handling --------- ----------------------------------------- */
@@ -892,7 +902,10 @@ static int asm_sunk_store(ASMState *as, IRIns *ira, IRIns *irs)
static void asm_snap_alloc1(ASMState *as, IRRef ref) static void asm_snap_alloc1(ASMState *as, IRRef ref)
{ {
IRIns *ir = IR(ref); IRIns *ir = IR(ref);
if (!irref_isk(ref) && (!(ra_used(ir) || ir->r == RID_SUNK))) { if (!irref_isk(ref) && ir->r != RID_SUNK) {
bloomset(as->snapfilt1, ref);
bloomset(as->snapfilt2, hashrot(ref, ref + HASH_BIAS));
if (ra_used(ir)) return;
if (ir->r == RID_SINK) { if (ir->r == RID_SINK) {
ir->r = RID_SUNK; ir->r = RID_SUNK;
#if LJ_HASFFI #if LJ_HASFFI
@@ -947,11 +960,12 @@ static void asm_snap_alloc1(ASMState *as, IRRef ref)
} }
/* Allocate refs escaping to a snapshot. */ /* Allocate refs escaping to a snapshot. */
static void asm_snap_alloc(ASMState *as) static void asm_snap_alloc(ASMState *as, int snapno)
{ {
SnapShot *snap = &as->T->snap[as->snapno]; SnapShot *snap = &as->T->snap[snapno];
SnapEntry *map = &as->T->snapmap[snap->mapofs]; SnapEntry *map = &as->T->snapmap[snap->mapofs];
MSize n, nent = snap->nent; MSize n, nent = snap->nent;
as->snapfilt1 = as->snapfilt2 = 0;
for (n = 0; n < nent; n++) { for (n = 0; n < nent; n++) {
SnapEntry sn = map[n]; SnapEntry sn = map[n];
IRRef ref = snap_ref(sn); IRRef ref = snap_ref(sn);
@@ -960,7 +974,7 @@ static void asm_snap_alloc(ASMState *as)
if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) { if (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM)) {
lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP, lj_assertA(irt_type(IR(ref+1)->t) == IRT_SOFTFP,
"snap %d[%d] points to bad SOFTFP IR %04d", "snap %d[%d] points to bad SOFTFP IR %04d",
as->snapno, n, ref - REF_BIAS); snapno, n, ref - REF_BIAS);
asm_snap_alloc1(as, ref+1); asm_snap_alloc1(as, ref+1);
} }
} }
@@ -976,35 +990,26 @@ static void asm_snap_alloc(ASMState *as)
*/ */
static int asm_snap_checkrename(ASMState *as, IRRef ren) static int asm_snap_checkrename(ASMState *as, IRRef ren)
{ {
SnapShot *snap = &as->T->snap[as->snapno]; if (bloomtest(as->snapfilt1, ren) &&
SnapEntry *map = &as->T->snapmap[snap->mapofs]; bloomtest(as->snapfilt2, hashrot(ren, ren + HASH_BIAS))) {
MSize n, nent = snap->nent; IRIns *ir = IR(ren);
for (n = 0; n < nent; n++) { ra_spill(as, ir); /* Register renamed, so force a spill slot. */
SnapEntry sn = map[n]; RA_DBGX((as, "snaprensp $f $s", ren, ir->s));
IRRef ref = snap_ref(sn); return 1; /* Found. */
if (ref == ren || (LJ_SOFTFP && (sn & SNAP_SOFTFPNUM) && ++ref == ren)) {
IRIns *ir = IR(ref);
ra_spill(as, ir); /* Register renamed, so force a spill slot. */
RA_DBGX((as, "snaprensp $f $s", ref, ir->s));
return 1; /* Found. */
}
} }
return 0; /* Not found. */ return 0; /* Not found. */
} }
/* Prepare snapshot for next guard instruction. */ /* Prepare snapshot for next guard or throwing instruction. */
static void asm_snap_prep(ASMState *as) static void asm_snap_prep(ASMState *as)
{ {
if (as->curins < as->snapref) { if (as->snapalloc) {
do { /* Alloc on first invocation for each snapshot. */
if (as->snapno == 0) return; /* Called by sunk stores before snap #0. */ as->snapalloc = 0;
as->snapno--; asm_snap_alloc(as, as->snapno);
as->snapref = as->T->snap[as->snapno].ref;
} while (as->curins < as->snapref);
asm_snap_alloc(as);
as->snaprename = as->T->nins; as->snaprename = as->T->nins;
} else { } else {
/* Process any renames above the highwater mark. */ /* Check any renames above the highwater mark. */
for (; as->snaprename < as->T->nins; as->snaprename++) { for (; as->snaprename < as->T->nins; as->snaprename++) {
IRIns *ir = &as->T->ir[as->snaprename]; IRIns *ir = &as->T->ir[as->snaprename];
if (asm_snap_checkrename(as, ir->op1)) if (asm_snap_checkrename(as, ir->op1))
@@ -1013,6 +1018,35 @@ static void asm_snap_prep(ASMState *as)
} }
} }
/* Move to previous snapshot when we cross the current snapshot ref. */
static void asm_snap_prev(ASMState *as)
{
if (as->curins < as->snapref) {
uintptr_t ofs = (uintptr_t)(as->mctoporig - as->mcp);
if (ofs >= 0x10000) lj_trace_err(as->J, LJ_TRERR_MCODEOV);
do {
if (as->snapno == 0) return;
as->snapno--;
as->snapref = as->T->snap[as->snapno].ref;
as->T->snap[as->snapno].mcofs = (uint16_t)ofs; /* Remember mcode ofs. */
} while (as->curins < as->snapref); /* May have no ins inbetween. */
as->snapalloc = 1;
}
}
/* Fixup snapshot mcode offsetst. */
static void asm_snap_fixup_mcofs(ASMState *as)
{
uint32_t sz = (uint32_t)(as->mctoporig - as->mcp);
SnapShot *snap = as->T->snap;
SnapNo i;
for (i = as->T->nsnap-1; i > 0; i--) {
/* Compute offset from mcode start and store in correct snapshot. */
snap[i].mcofs = (uint16_t)(sz - snap[i-1].mcofs);
}
snap[0].mcofs = 0;
}
/* -- Miscellaneous helpers ----------------------------------------------- */ /* -- Miscellaneous helpers ----------------------------------------------- */
/* Calculate stack adjustment. */ /* Calculate stack adjustment. */
@@ -1057,6 +1091,7 @@ static void asm_snew(ASMState *as, IRIns *ir)
{ {
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_new]; const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_str_new];
IRRef args[3]; IRRef args[3];
asm_snap_prep(as);
args[0] = ASMREF_L; /* lua_State *L */ args[0] = ASMREF_L; /* lua_State *L */
args[1] = ir->op1; /* const char *str */ args[1] = ir->op1; /* const char *str */
args[2] = ir->op2; /* size_t len */ args[2] = ir->op2; /* size_t len */
@@ -1069,6 +1104,7 @@ static void asm_tnew(ASMState *as, IRIns *ir)
{ {
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_new1]; const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_new1];
IRRef args[2]; IRRef args[2];
asm_snap_prep(as);
args[0] = ASMREF_L; /* lua_State *L */ args[0] = ASMREF_L; /* lua_State *L */
args[1] = ASMREF_TMP1; /* uint32_t ahsize */ args[1] = ASMREF_TMP1; /* uint32_t ahsize */
as->gcsteps++; as->gcsteps++;
@@ -1081,6 +1117,7 @@ static void asm_tdup(ASMState *as, IRIns *ir)
{ {
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_dup]; const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_tab_dup];
IRRef args[2]; IRRef args[2];
asm_snap_prep(as);
args[0] = ASMREF_L; /* lua_State *L */ args[0] = ASMREF_L; /* lua_State *L */
args[1] = ir->op1; /* const GCtab *kt */ args[1] = ir->op1; /* const GCtab *kt */
as->gcsteps++; as->gcsteps++;
@@ -1106,28 +1143,43 @@ static void asm_gcstep(ASMState *as, IRIns *ir)
/* -- Buffer operations --------------------------------------------------- */ /* -- Buffer operations --------------------------------------------------- */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref); static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode);
#if LJ_HASBUFFER
static void asm_bufhdr_write(ASMState *as, Reg sb);
#endif
static void asm_bufhdr(ASMState *as, IRIns *ir) static void asm_bufhdr(ASMState *as, IRIns *ir)
{ {
Reg sb = ra_dest(as, ir, RSET_GPR); Reg sb = ra_dest(as, ir, RSET_GPR);
if ((ir->op2 & IRBUFHDR_APPEND)) { switch (ir->op2) {
case IRBUFHDR_RESET: {
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
IRIns irbp;
irbp.ot = IRT(0, IRT_PTR); /* Buffer data pointer type. */
emit_storeofs(as, &irbp, tmp, sb, offsetof(SBuf, w));
emit_loadofs(as, &irbp, tmp, sb, offsetof(SBuf, b));
break;
}
case IRBUFHDR_APPEND: {
/* Rematerialize const buffer pointer instead of likely spill. */ /* Rematerialize const buffer pointer instead of likely spill. */
IRIns *irp = IR(ir->op1); IRIns *irp = IR(ir->op1);
if (!(ra_hasreg(irp->r) || irp == ir-1 || if (!(ra_hasreg(irp->r) || irp == ir-1 ||
(irp == ir-2 && !ra_used(ir-1)))) { (irp == ir-2 && !ra_used(ir-1)))) {
while (!(irp->o == IR_BUFHDR && !(irp->op2 & IRBUFHDR_APPEND))) while (!(irp->o == IR_BUFHDR && irp->op2 == IRBUFHDR_RESET))
irp = IR(irp->op1); irp = IR(irp->op1);
if (irref_isk(irp->op1)) { if (irref_isk(irp->op1)) {
ra_weak(as, ra_allocref(as, ir->op1, RSET_GPR)); ra_weak(as, ra_allocref(as, ir->op1, RSET_GPR));
ir = irp; ir = irp;
} }
} }
} else { break;
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb)); }
/* Passing ir isn't strictly correct, but it's an IRT_PGC, too. */ #if LJ_HASBUFFER
emit_storeofs(as, ir, tmp, sb, offsetof(SBuf, p)); case IRBUFHDR_WRITE:
emit_loadofs(as, ir, tmp, sb, offsetof(SBuf, b)); asm_bufhdr_write(as, sb);
break;
#endif
default: lj_assertA(0, "bad BUFHDR op2 %d", ir->op2); break;
} }
#if LJ_TARGET_X86ORX64 #if LJ_TARGET_X86ORX64
ra_left(as, sb, ir->op1); ra_left(as, sb, ir->op1);
@@ -1179,7 +1231,7 @@ static void asm_bufput(ASMState *as, IRIns *ir)
if (args[1] == ASMREF_TMP1) { if (args[1] == ASMREF_TMP1) {
Reg tmp = ra_releasetmp(as, ASMREF_TMP1); Reg tmp = ra_releasetmp(as, ASMREF_TMP1);
if (kchar == -129) if (kchar == -129)
asm_tvptr(as, tmp, irs->op1); asm_tvptr(as, tmp, irs->op1, IRTMPREF_IN1);
else else
ra_allockreg(as, kchar, tmp); ra_allockreg(as, kchar, tmp);
} }
@@ -1201,6 +1253,7 @@ static void asm_tostr(ASMState *as, IRIns *ir)
{ {
const CCallInfo *ci; const CCallInfo *ci;
IRRef args[2]; IRRef args[2];
asm_snap_prep(as);
args[0] = ASMREF_L; args[0] = ASMREF_L;
as->gcsteps++; as->gcsteps++;
if (ir->op2 == IRTOSTR_NUM) { if (ir->op2 == IRTOSTR_NUM) {
@@ -1216,7 +1269,7 @@ static void asm_tostr(ASMState *as, IRIns *ir)
asm_setupresult(as, ir, ci); /* GCstr * */ asm_setupresult(as, ir, ci); /* GCstr * */
asm_gencall(as, ci, args); asm_gencall(as, ci, args);
if (ir->op2 == IRTOSTR_NUM) if (ir->op2 == IRTOSTR_NUM)
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1); asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op1, IRTMPREF_IN1);
} }
#if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86 #if LJ_32 && LJ_HASFFI && !LJ_SOFTFP && !LJ_TARGET_X86
@@ -1257,12 +1310,19 @@ static void asm_newref(ASMState *as, IRIns *ir)
IRRef args[3]; IRRef args[3];
if (ir->r == RID_SINK) if (ir->r == RID_SINK)
return; return;
asm_snap_prep(as);
args[0] = ASMREF_L; /* lua_State *L */ args[0] = ASMREF_L; /* lua_State *L */
args[1] = ir->op1; /* GCtab *t */ args[1] = ir->op1; /* GCtab *t */
args[2] = ASMREF_TMP1; /* cTValue *key */ args[2] = ASMREF_TMP1; /* cTValue *key */
asm_setupresult(as, ir, ci); /* TValue * */ asm_setupresult(as, ir, ci); /* TValue * */
asm_gencall(as, ci, args); asm_gencall(as, ci, args);
asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2); asm_tvptr(as, ra_releasetmp(as, ASMREF_TMP1), ir->op2, IRTMPREF_IN1);
}
static void asm_tmpref(ASMState *as, IRIns *ir)
{
Reg r = ra_dest(as, ir, RSET_GPR);
asm_tvptr(as, r, ir->op1, ir->op2);
} }
static void asm_lref(ASMState *as, IRIns *ir) static void asm_lref(ASMState *as, IRIns *ir)
@@ -1744,6 +1804,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
case IR_NEWREF: asm_newref(as, ir); break; case IR_NEWREF: asm_newref(as, ir); break;
case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break; case IR_UREFO: case IR_UREFC: asm_uref(as, ir); break;
case IR_FREF: asm_fref(as, ir); break; case IR_FREF: asm_fref(as, ir); break;
case IR_TMPREF: asm_tmpref(as, ir); break;
case IR_STRREF: asm_strref(as, ir); break; case IR_STRREF: asm_strref(as, ir); break;
case IR_LREF: asm_lref(as, ir); break; case IR_LREF: asm_lref(as, ir); break;
@@ -1838,8 +1899,7 @@ static void asm_head_side(ASMState *as)
if (as->snapno && as->topslot > as->parent->topslot) { if (as->snapno && as->topslot > as->parent->topslot) {
/* Force snap #0 alloc to prevent register overwrite in stack check. */ /* Force snap #0 alloc to prevent register overwrite in stack check. */
as->snapno = 0; asm_snap_alloc(as, 0);
asm_snap_alloc(as);
} }
allow = asm_head_side_base(as, irp, allow); allow = asm_head_side_base(as, irp, allow);
@@ -2078,6 +2138,9 @@ static void asm_setup_regsp(ASMState *as)
#endif #endif
ra_setup(as); ra_setup(as);
#if LJ_TARGET_ARM64
ra_setkref(as, RID_GL, (intptr_t)J2G(as->J));
#endif
/* Clear reg/sp for constants. */ /* Clear reg/sp for constants. */
for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++) { for (ir = IR(T->nk), lastir = IR(REF_BASE); ir < lastir; ir++) {
@@ -2100,6 +2163,7 @@ static void asm_setup_regsp(ASMState *as)
as->snaprename = nins; as->snaprename = nins;
as->snapref = nins; as->snapref = nins;
as->snapno = T->nsnap; as->snapno = T->nsnap;
as->snapalloc = 0;
as->stopins = REF_BASE; as->stopins = REF_BASE;
as->orignins = nins; as->orignins = nins;
@@ -2148,6 +2212,10 @@ static void asm_setup_regsp(ASMState *as)
ir->prev = (uint16_t)REGSP_HINT((rload & 15)); ir->prev = (uint16_t)REGSP_HINT((rload & 15));
rload = lj_ror(rload, 4); rload = lj_ror(rload, 4);
continue; continue;
case IR_TMPREF:
if ((ir->op2 & IRTMPREF_OUT2) && as->evenspill < 4)
as->evenspill = 4; /* TMPREF OUT2 needs two TValues on the stack. */
break;
#endif #endif
case IR_CALLXS: { case IR_CALLXS: {
CCallInfo ci; CCallInfo ci;
@@ -2157,7 +2225,17 @@ static void asm_setup_regsp(ASMState *as)
as->modset |= RSET_SCRATCH; as->modset |= RSET_SCRATCH;
continue; continue;
} }
case IR_CALLN: case IR_CALLA: case IR_CALLL: case IR_CALLS: { case IR_CALLL:
/* lj_vm_next needs two TValues on the stack. */
#if LJ_TARGET_X64 && LJ_ABI_WIN
if (ir->op2 == IRCALL_lj_vm_next && as->evenspill < SPS_FIRST + 4)
as->evenspill = SPS_FIRST + 4;
#else
if (SPS_FIRST < 4 && ir->op2 == IRCALL_lj_vm_next && as->evenspill < 4)
as->evenspill = 4;
#endif
/* fallthrough */
case IR_CALLN: case IR_CALLA: case IR_CALLS: {
const CCallInfo *ci = &lj_ir_callinfo[ir->op2]; const CCallInfo *ci = &lj_ir_callinfo[ir->op2];
ir->prev = asm_setup_call_slots(as, ir, ci); ir->prev = asm_setup_call_slots(as, ir, ci);
if (inloop) if (inloop)
@@ -2165,7 +2243,6 @@ static void asm_setup_regsp(ASMState *as)
(RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH; (RSET_SCRATCH & ~RSET_FPR) : RSET_SCRATCH;
continue; continue;
} }
#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
case IR_HIOP: case IR_HIOP:
switch ((ir-1)->o) { switch ((ir-1)->o) {
#if LJ_SOFTFP && LJ_TARGET_ARM #if LJ_SOFTFP && LJ_TARGET_ARM
@@ -2176,7 +2253,7 @@ static void asm_setup_regsp(ASMState *as)
} }
break; break;
#endif #endif
#if !LJ_SOFTFP && LJ_NEED_FP64 #if !LJ_SOFTFP && LJ_NEED_FP64 && LJ_32 && LJ_HASFFI
case IR_CONV: case IR_CONV:
if (irt_isfp((ir-1)->t)) { if (irt_isfp((ir-1)->t)) {
ir->prev = REGSP_HINT(RID_FPRET); ir->prev = REGSP_HINT(RID_FPRET);
@@ -2184,7 +2261,7 @@ static void asm_setup_regsp(ASMState *as)
} }
#endif #endif
/* fallthrough */ /* fallthrough */
case IR_CALLN: case IR_CALLXS: case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
#if LJ_SOFTFP #if LJ_SOFTFP
case IR_MIN: case IR_MAX: case IR_MIN: case IR_MAX:
#endif #endif
@@ -2195,7 +2272,6 @@ static void asm_setup_regsp(ASMState *as)
break; break;
} }
break; break;
#endif
#if LJ_SOFTFP #if LJ_SOFTFP
case IR_MIN: case IR_MAX: case IR_MIN: case IR_MAX:
if ((ir+1)->o != IR_HIOP) break; if ((ir+1)->o != IR_HIOP) break;
@@ -2250,13 +2326,23 @@ static void asm_setup_regsp(ASMState *as)
} }
/* fallthrough */ /* for integer POW */ /* fallthrough */ /* for integer POW */
case IR_DIV: case IR_MOD: case IR_DIV: case IR_MOD:
if (!irt_isnum(ir->t)) { if ((LJ_64 && LJ_SOFTFP) || !irt_isnum(ir->t)) {
ir->prev = REGSP_HINT(RID_RET); ir->prev = REGSP_HINT(RID_RET);
if (inloop) if (inloop)
as->modset |= (RSET_SCRATCH & RSET_GPR); as->modset |= (RSET_SCRATCH & RSET_GPR);
continue; continue;
} }
break; break;
#if LJ_64 && LJ_SOFTFP
case IR_ADD: case IR_SUB: case IR_MUL:
if (irt_isnum(ir->t)) {
ir->prev = REGSP_HINT(RID_RET);
if (inloop)
as->modset |= (RSET_SCRATCH & RSET_GPR);
continue;
}
break;
#endif
case IR_FPMATH: case IR_FPMATH:
#if LJ_TARGET_X86ORX64 #if LJ_TARGET_X86ORX64
if (ir->op2 <= IRFPM_TRUNC) { if (ir->op2 <= IRFPM_TRUNC) {
@@ -2327,7 +2413,6 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
{ {
ASMState as_; ASMState as_;
ASMState *as = &as_; ASMState *as = &as_;
MCode *origtop;
/* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */ /* Remove nops/renames left over from ASM restart due to LJ_TRERR_MCODELM. */
{ {
@@ -2355,7 +2440,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
as->parent = J->parent ? traceref(J, J->parent) : NULL; as->parent = J->parent ? traceref(J, J->parent) : NULL;
/* Reserve MCode memory. */ /* Reserve MCode memory. */
as->mctop = origtop = lj_mcode_reserve(J, &as->mcbot); as->mctop = as->mctoporig = lj_mcode_reserve(J, &as->mcbot);
as->mcp = as->mctop; as->mcp = as->mctop;
as->mclim = as->mcbot + MCLIM_REDZONE; as->mclim = as->mcbot + MCLIM_REDZONE;
asm_setup_target(as); asm_setup_target(as);
@@ -2417,6 +2502,7 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
lj_assertA(!(LJ_32 && irt_isint64(ir->t)), lj_assertA(!(LJ_32 && irt_isint64(ir->t)),
"IR %04d has unsplit 64 bit type", "IR %04d has unsplit 64 bit type",
(int)(ir - as->ir) - REF_BIAS); (int)(ir - as->ir) - REF_BIAS);
asm_snap_prev(as);
if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE)) if (!ra_used(ir) && !ir_sideeff(ir) && (as->flags & JIT_F_OPT_DCE))
continue; /* Dead-code elimination can be soooo easy. */ continue; /* Dead-code elimination can be soooo easy. */
if (irt_isguard(ir->t)) if (irt_isguard(ir->t))
@@ -2450,6 +2536,9 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins, memcpy(J->curfinal->ir + as->orignins, T->ir + as->orignins,
(T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */ (T->nins - as->orignins) * sizeof(IRIns)); /* Copy RENAMEs. */
T->nins = J->curfinal->nins; T->nins = J->curfinal->nins;
/* Fill mcofs of any unprocessed snapshots. */
as->curins = REF_FIRST;
asm_snap_prev(as);
break; /* Done. */ break; /* Done. */
} }
@@ -2468,13 +2557,16 @@ void lj_asm_trace(jit_State *J, GCtrace *T)
/* Set trace entry point before fixing up tail to allow link to self. */ /* Set trace entry point before fixing up tail to allow link to self. */
T->mcode = as->mcp; T->mcode = as->mcp;
T->mcloop = as->mcloop ? (MSize)((char *)as->mcloop - (char *)as->mcp) : 0; T->mcloop = as->mcloop ? (MSize)((char *)as->mcloop - (char *)as->mcp) : 0;
if (!as->loopref) if (as->loopref)
asm_loop_tail_fixup(as);
else
asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */ asm_tail_fixup(as, T->link); /* Note: this may change as->mctop! */
T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp); T->szmcode = (MSize)((char *)as->mctop - (char *)as->mcp);
asm_snap_fixup_mcofs(as);
#if LJ_TARGET_MCODE_FIXUP #if LJ_TARGET_MCODE_FIXUP
asm_mcode_fixup(T->mcode, T->szmcode); asm_mcode_fixup(T->mcode, T->szmcode);
#endif #endif
lj_mcode_sync(T->mcode, origtop); lj_mcode_sync(T->mcode, as->mctoporig);
} }
#undef IR #undef IR
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** IR assembler (SSA IR -> machine code). ** IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#ifndef _LJ_ASM_H #ifndef _LJ_ASM_H
+90 -39
View File
@@ -1,6 +1,6 @@
/* /*
** ARM IR assembler (SSA IR -> machine code). ** ARM IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
/* -- Register allocator extensions --------------------------------------- */ /* -- Register allocator extensions --------------------------------------- */
@@ -185,6 +185,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
*ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */ *ofsp = (ofs & 255); /* Mask out less bits to allow LDRD. */
return ra_allock(as, (ofs & ~255), allow); return ra_allock(as, (ofs & ~255), allow);
} }
} else if (ir->o == IR_TMPREF) {
*ofsp = 0;
return RID_SP;
} }
} }
*ofsp = 0; *ofsp = 0;
@@ -498,6 +501,30 @@ static void asm_retf(ASMState *as, IRIns *ir)
emit_lso(as, ARMI_LDR, RID_TMP, base, -4); emit_lso(as, ARMI_LDR, RID_TMP, base, -4);
} }
/* -- Buffer operations --------------------------------------------------- */
#if LJ_HASBUFFER
static void asm_bufhdr_write(ASMState *as, Reg sb)
{
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
IRIns irgc;
int32_t addr = i32ptr((void *)&J2G(as->J)->cur_L);
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
if ((as->flags & JIT_F_ARMV6T2)) {
emit_dnm(as, ARMI_BFI, RID_TMP, lj_fls(SBUF_MASK_FLAG), tmp);
} else {
emit_dnm(as, ARMI_ORR, RID_TMP, RID_TMP, tmp);
emit_dn(as, ARMI_AND|ARMI_K12|SBUF_MASK_FLAG, tmp, tmp);
}
emit_lso(as, ARMI_LDR, RID_TMP,
ra_allock(as, (addr & ~4095),
rset_exclude(rset_exclude(RSET_GPR, sb), tmp)),
(addr & 4095));
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
}
#endif
/* -- Type conversions ---------------------------------------------------- */ /* -- Type conversions ---------------------------------------------------- */
#if !LJ_SOFTFP #if !LJ_SOFTFP
@@ -666,35 +693,55 @@ static void asm_strto(ASMState *as, IRIns *ir)
/* -- Memory references --------------------------------------------------- */ /* -- Memory references --------------------------------------------------- */
/* Get pointer to TValue. */ /* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{ {
IRIns *ir = IR(ref); if ((mode & IRTMPREF_IN1)) {
if (irt_isnum(ir->t)) { IRIns *ir = IR(ref);
if (irref_isk(ref)) { if (irt_isnum(ir->t)) {
/* Use the number constant itself as a TValue. */ if ((mode & IRTMPREF_OUT1)) {
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
} else {
#if LJ_SOFTFP #if LJ_SOFTFP
lj_assertA(0, "unsplit FP op"); lj_assertA(irref_isk(ref), "unsplit FP op");
emit_dm(as, ARMI_MOV, dest, RID_SP);
emit_lso(as, ARMI_STR,
ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
RID_SP, 0);
emit_lso(as, ARMI_STR,
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
RID_SP, 4);
#else #else
/* Otherwise force a spill and use the spill slot. */ Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR); emit_dm(as, ARMI_MOV, dest, RID_SP);
emit_vlso(as, ARMI_VSTR_D, src, RID_SP, 0);
#endif #endif
} else if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
} else {
#if LJ_SOFTFP
lj_assertA(0, "unsplit FP op");
#else
/* Otherwise force a spill and use the spill slot. */
emit_opk(as, ARMI_ADD, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
#endif
}
} else {
/* Otherwise use [sp] and [sp+4] to hold the TValue.
** This assumes the following call has max. 4 args.
*/
Reg type;
emit_dm(as, ARMI_MOV, dest, RID_SP);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_GPR);
emit_lso(as, ARMI_STR, src, RID_SP, 0);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
type = ra_alloc1(as, ref+1, RSET_GPR);
else
type = ra_allock(as, irt_toitype(ir->t), RSET_GPR);
emit_lso(as, ARMI_STR, type, RID_SP, 4);
} }
} else { } else {
/* Otherwise use [sp] and [sp+4] to hold the TValue. */
RegSet allow = rset_exclude(RSET_GPR, dest);
Reg type;
emit_dm(as, ARMI_MOV, dest, RID_SP); emit_dm(as, ARMI_MOV, dest, RID_SP);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, allow);
emit_lso(as, ARMI_STR, src, RID_SP, 0);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
type = ra_alloc1(as, ref+1, allow);
else
type = ra_allock(as, irt_toitype(ir->t), allow);
emit_lso(as, ARMI_STR, type, RID_SP, 4);
} }
} }
@@ -1086,6 +1133,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
} }
idx = asm_fuseahuref(as, ir->op1, &ofs, allow, idx = asm_fuseahuref(as, ir->op1, &ofs, allow,
(!LJ_SOFTFP && t == IRT_NUM) ? 1024 : 4096); (!LJ_SOFTFP && t == IRT_NUM) ? 1024 : 4096);
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
if (!hiop || type == RID_NONE) { if (!hiop || type == RID_NONE) {
rset_clear(allow, idx); rset_clear(allow, idx);
if (ofs < 256 && ra_hasreg(dest) && (dest & 1) == 0 && if (ofs < 256 && ra_hasreg(dest) && (dest & 1) == 0 &&
@@ -1837,15 +1885,15 @@ static void asm_int64comp(ASMState *as, IRIns *ir)
} }
#endif #endif
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ /* -- Split register ops -------------------------------------------------- */
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ /* Hiword op of a split 32/32 bit op. Previous op is the loword op. */
static void asm_hiop(ASMState *as, IRIns *ir) static void asm_hiop(ASMState *as, IRIns *ir)
{ {
#if LJ_HASFFI || LJ_SOFTFP
/* HIOP is marked as a store because it needs its own DCE logic. */ /* HIOP is marked as a store because it needs its own DCE logic. */
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
#if LJ_HASFFI || LJ_SOFTFP
if ((ir-1)->o <= IR_NE) { /* 64 bit integer or FP comparisons. ORDER IR. */ if ((ir-1)->o <= IR_NE) { /* 64 bit integer or FP comparisons. ORDER IR. */
as->curins--; /* Always skip the loword comparison. */ as->curins--; /* Always skip the loword comparison. */
#if LJ_SOFTFP #if LJ_SOFTFP
@@ -1876,6 +1924,7 @@ static void asm_hiop(ASMState *as, IRIns *ir)
asm_xstore_(as, ir, 4); asm_xstore_(as, ir, 4);
return; return;
} }
#endif
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
switch ((ir-1)->o) { switch ((ir-1)->o) {
#if LJ_HASFFI #if LJ_HASFFI
@@ -1894,6 +1943,9 @@ static void asm_hiop(ASMState *as, IRIns *ir)
asm_intneg(as, ir, ARMI_RSC); asm_intneg(as, ir, ARMI_RSC);
asm_intneg(as, ir-1, ARMI_RSB|ARMI_S); asm_intneg(as, ir-1, ARMI_RSB|ARMI_S);
break; break;
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif #endif
#if LJ_SOFTFP #if LJ_SOFTFP
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
@@ -1901,25 +1953,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
if (!uselo) if (!uselo)
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
break; break;
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif #endif
case IR_CALLN: case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
case IR_CALLS:
case IR_CALLXS:
if (!uselo) if (!uselo)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break; break;
#if LJ_SOFTFP
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
#endif
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
} }
#else
/* Unused without SOFTFP or FFI. */
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
#endif
} }
/* -- Profiling ----------------------------------------------------------- */ /* -- Profiling ----------------------------------------------------------- */
@@ -2021,6 +2064,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
} else if ((sn & SNAP_SOFTFPNUM)) { } else if ((sn & SNAP_SOFTFPNUM)) {
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPRODD, RID_BASE)); type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPRODD, RID_BASE));
#endif #endif
} else if ((sn & SNAP_KEYINDEX)) {
type = ra_allock(as, (int32_t)LJ_KEYINDEX, odd);
} else { } else {
type = ra_allock(as, (int32_t)irt_toitype(ir->t), odd); type = ra_allock(as, (int32_t)irt_toitype(ir->t), odd);
} }
@@ -2082,6 +2127,12 @@ static void asm_loop_fixup(ASMState *as)
} }
} }
/* Fixup the tail of the loop. */
static void asm_loop_tail_fixup(ASMState *as)
{
UNUSED(as); /* Nothing to do. */
}
/* -- Head of trace ------------------------------------------------------- */ /* -- Head of trace ------------------------------------------------------- */
/* Reload L register from g->cur_L. */ /* Reload L register from g->cur_L. */
+79 -36
View File
@@ -1,6 +1,6 @@
/* /*
** ARM64 IR assembler (SSA IR -> machine code). ** ARM64 IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
** **
** Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com. ** Contributed by Djordje Kovacevic and Stefan Pejic from RT-RK.com.
** Sponsored by Cisco Systems, Inc. ** Sponsored by Cisco Systems, Inc.
@@ -198,6 +198,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow,
return RID_GL; return RID_GL;
} }
} }
} else if (ir->o == IR_TMPREF) {
*ofsp = (int32_t)glofs(as, &J2G(as->J)->tmptv);
return RID_GL;
} }
} }
*ofsp = 0; *ofsp = 0;
@@ -457,8 +460,11 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
{ {
RegSet drop = RSET_SCRATCH; RegSet drop = RSET_SCRATCH;
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
if (ra_hasreg(ir->r)) if (ra_hasreg(ir->r))
rset_clear(drop, ir->r); /* Dest reg handled below. */ rset_clear(drop, ir->r); /* Dest reg handled below. */
if (hiop && ra_hasreg((ir+1)->r))
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
ra_evictset(as, drop); /* Evictions must be performed first. */ ra_evictset(as, drop); /* Evictions must be performed first. */
if (ra_used(ir)) { if (ra_used(ir)) {
lj_assertA(!irt_ispri(ir->t), "PRI dest"); lj_assertA(!irt_ispri(ir->t), "PRI dest");
@@ -470,6 +476,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
} else { } else {
ra_destreg(as, ir, RID_FPRET); ra_destreg(as, ir, RID_FPRET);
} }
} else if (hiop) {
ra_destpair(as, ir);
} else { } else {
ra_destreg(as, ir, RID_RET); ra_destreg(as, ir, RID_RET);
} }
@@ -519,6 +527,21 @@ static void asm_retf(ASMState *as, IRIns *ir)
emit_lso(as, A64I_LDRx, RID_TMP, base, -8); emit_lso(as, A64I_LDRx, RID_TMP, base, -8);
} }
/* -- Buffer operations --------------------------------------------------- */
#if LJ_HASBUFFER
static void asm_bufhdr_write(ASMState *as, Reg sb)
{
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
IRIns irgc;
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
emit_dn(as, A64I_BFMx | A64F_IMMS(lj_fls(SBUF_MASK_FLAG)) | A64F_IMMR(0), RID_TMP, tmp);
emit_getgl(as, RID_TMP, cur_L);
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
}
#endif
/* -- Type conversions ---------------------------------------------------- */ /* -- Type conversions ---------------------------------------------------- */
static void asm_tointg(ASMState *as, IRIns *ir, Reg left) static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
@@ -602,7 +625,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
emit_dn(as, A64I_SXTW, dest, left); emit_dn(as, A64I_SXTW, dest, left);
} }
} else { } else {
if (st64) { if (st64 && !(ir->op2 & IRCONV_NONE)) {
/* This is either a 32 bit reg/reg mov which zeroes the hiword /* This is either a 32 bit reg/reg mov which zeroes the hiword
** or a load of the loword from a 64 bit address. ** or a load of the loword from a 64 bit address.
*/ */
@@ -675,22 +698,23 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
} }
/* Get pointer to TValue. */ /* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{ {
IRIns *ir = IR(ref); if ((mode & IRTMPREF_IN1)) {
if (irt_isnum(ir->t)) { IRIns *ir = IR(ref);
if (irref_isk(ref)) { if (irt_isnum(ir->t)) {
/* Use the number constant itself as a TValue. */ if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) {
ra_allockreg(as, i64ptr(ir_knum(ir)), dest); /* Use the number constant itself as a TValue. */
ra_allockreg(as, i64ptr(ir_knum(ir)), dest);
return;
}
emit_lso(as, A64I_STRd, (ra_alloc1(as, ref, RSET_FPR) & 31), dest, 0);
} else { } else {
/* Otherwise force a spill and use the spill slot. */ asm_tvstore64(as, dest, 0, ref);
emit_opk(as, A64I_ADDx, dest, RID_SP, ra_spill(as, ir), RSET_GPR);
} }
} else {
/* Otherwise use g->tmptv to hold the TValue. */
asm_tvstore64(as, dest, 0, ref);
ra_allockreg(as, i64ptr(&J2G(as->J)->tmptv), dest);
} }
/* g->tmptv holds the TValue(s). */
emit_dn(as, A64I_ADDx^emit_isk12(glofs(as, &J2G(as->J)->tmptv)), dest, RID_GL);
} }
static void asm_aref(ASMState *as, IRIns *ir) static void asm_aref(ASMState *as, IRIns *ir)
@@ -767,7 +791,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
} }
} else if (irt_isaddr(kt)) { } else if (irt_isaddr(kt)) {
if (isk) { if (isk) {
int64_t kk = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; int64_t kk = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
scr = ra_allock(as, kk, allow); scr = ra_allock(as, kk, allow);
} else { } else {
scr = ra_scratch(as, allow); scr = ra_scratch(as, allow);
@@ -775,7 +799,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
rset_clear(allow, scr); rset_clear(allow, scr);
} else { } else {
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type"); lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
type = ra_allock(as, ~((int64_t)~irt_toitype(ir->t) << 47), allow); type = ra_allock(as, ~((int64_t)~irt_toitype(kt) << 47), allow);
scr = ra_scratch(as, rset_clear(allow, type)); scr = ra_scratch(as, rset_clear(allow, type));
rset_clear(allow, scr); rset_clear(allow, scr);
} }
@@ -824,7 +848,7 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64)); emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key.u64));
} }
} else { } else {
emit_nm(as, A64I_CMPw, scr, type); emit_nm(as, A64I_CMPx, scr, type);
emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key)); emit_lso(as, A64I_LDRx, scr, dest, offsetof(Node, key));
} }
@@ -1059,6 +1083,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
} }
type = ra_scratch(as, rset_clear(gpr, tmp)); type = ra_scratch(as, rset_clear(gpr, tmp));
idx = asm_fuseahuref(as, ir->op1, &ofs, rset_clear(gpr, type), A64I_LDRx); idx = asm_fuseahuref(as, ir->op1, &ofs, rset_clear(gpr, type), A64I_LDRx);
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
/* Always do the type check, even if the load result is unused. */ /* Always do the type check, even if the load result is unused. */
asm_guardcc(as, irt_isnum(ir->t) ? CC_LS : CC_NE); asm_guardcc(as, irt_isnum(ir->t) ? CC_LS : CC_NE);
if (irt_type(ir->t) >= IRT_NUM) { if (irt_type(ir->t) >= IRT_NUM) {
@@ -1261,17 +1286,13 @@ static void asm_tbar(ASMState *as, IRIns *ir)
{ {
Reg tab = ra_alloc1(as, ir->op1, RSET_GPR); Reg tab = ra_alloc1(as, ir->op1, RSET_GPR);
Reg link = ra_scratch(as, rset_exclude(RSET_GPR, tab)); Reg link = ra_scratch(as, rset_exclude(RSET_GPR, tab));
Reg gr = ra_allock(as, i64ptr(J2G(as->J)),
rset_exclude(rset_exclude(RSET_GPR, tab), link));
Reg mark = RID_TMP; Reg mark = RID_TMP;
MCLabel l_end = emit_label(as); MCLabel l_end = emit_label(as);
emit_lso(as, A64I_STRx, link, tab, (int32_t)offsetof(GCtab, gclist)); emit_lso(as, A64I_STRx, link, tab, (int32_t)offsetof(GCtab, gclist));
emit_lso(as, A64I_STRB, mark, tab, (int32_t)offsetof(GCtab, marked)); emit_lso(as, A64I_STRB, mark, tab, (int32_t)offsetof(GCtab, marked));
emit_lso(as, A64I_STRx, tab, gr, emit_setgl(as, tab, gc.grayagain);
(int32_t)offsetof(global_State, gc.grayagain));
emit_dn(as, A64I_ANDw^emit_isk13(~LJ_GC_BLACK, 0), mark, mark); emit_dn(as, A64I_ANDw^emit_isk13(~LJ_GC_BLACK, 0), mark, mark);
emit_lso(as, A64I_LDRx, link, gr, emit_getgl(as, link, gc.grayagain);
(int32_t)offsetof(global_State, gc.grayagain));
emit_cond_branch(as, CC_EQ, l_end); emit_cond_branch(as, CC_EQ, l_end);
emit_n(as, A64I_TSTw^emit_isk13(LJ_GC_BLACK, 0), mark); emit_n(as, A64I_TSTw^emit_isk13(LJ_GC_BLACK, 0), mark);
emit_lso(as, A64I_LDRB, mark, tab, (int32_t)offsetof(GCtab, marked)); emit_lso(as, A64I_LDRB, mark, tab, (int32_t)offsetof(GCtab, marked));
@@ -1291,7 +1312,7 @@ static void asm_obar(ASMState *as, IRIns *ir)
args[0] = ASMREF_TMP1; /* global_State *g */ args[0] = ASMREF_TMP1; /* global_State *g */
args[1] = ir->op1; /* TValue *tv */ args[1] = ir->op1; /* TValue *tv */
asm_gencall(as, ci, args); asm_gencall(as, ci, args);
ra_allockreg(as, i64ptr(J2G(as->J)), ra_releasetmp(as, ASMREF_TMP1) ); emit_dm(as, A64I_MOVx, ra_releasetmp(as, ASMREF_TMP1), RID_GL);
obj = IR(ir->op1)->r; obj = IR(ir->op1)->r;
tmp = ra_scratch(as, rset_exclude(allow, obj)); tmp = ra_scratch(as, rset_exclude(allow, obj));
emit_cond_branch(as, CC_EQ, l_end); emit_cond_branch(as, CC_EQ, l_end);
@@ -1704,13 +1725,25 @@ static void asm_comp(ASMState *as, IRIns *ir)
#define asm_equal(as, ir) asm_comp(as, ir) #define asm_equal(as, ir) asm_comp(as, ir)
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ /* -- Split register ops -------------------------------------------------- */
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ /* Hiword op of a split 64/64 bit op. Previous op is the loword op. */
static void asm_hiop(ASMState *as, IRIns *ir) static void asm_hiop(ASMState *as, IRIns *ir)
{ {
UNUSED(as); UNUSED(ir); /* HIOP is marked as a store because it needs its own DCE logic. */
lj_assertA(0, "unexpected HIOP"); /* Unused on 64 bit. */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
switch ((ir-1)->o) {
case IR_CALLN:
case IR_CALLL:
case IR_CALLS:
case IR_CALLXS:
if (!uselo)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break;
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
}
} }
/* -- Profiling ----------------------------------------------------------- */ /* -- Profiling ----------------------------------------------------------- */
@@ -1781,7 +1814,14 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
IRIns *ir = IR(ref); IRIns *ir = IR(ref);
if ((sn & SNAP_NORESTORE)) if ((sn & SNAP_NORESTORE))
continue; continue;
if (irt_isnum(ir->t)) { if ((sn & SNAP_KEYINDEX)) {
RegSet allow = rset_exclude(RSET_GPR, RID_BASE);
Reg r = irref_isk(ref) ? ra_allock(as, ir->i, allow) :
ra_alloc1(as, ref, allow);
rset_clear(allow, r);
emit_lso(as, A64I_STRw, r, RID_BASE, ofs);
emit_lso(as, A64I_STRw, ra_allock(as, LJ_KEYINDEX, allow), RID_BASE, ofs+4);
} else if (irt_isnum(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_FPR); Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_lso(as, A64I_STRd, (src & 31), RID_BASE, ofs); emit_lso(as, A64I_STRd, (src & 31), RID_BASE, ofs);
} else { } else {
@@ -1804,7 +1844,7 @@ static void asm_gc_check(ASMState *as)
const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit]; const CCallInfo *ci = &lj_ir_callinfo[IRCALL_lj_gc_step_jit];
IRRef args[2]; IRRef args[2];
MCLabel l_end; MCLabel l_end;
Reg tmp1, tmp2; Reg tmp2;
ra_evictset(as, RSET_SCRATCH); ra_evictset(as, RSET_SCRATCH);
l_end = emit_label(as); l_end = emit_label(as);
/* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */ /* Exit trace if in GCSatomic or GCSfinalize. Avoids syncing GC objects. */
@@ -1813,17 +1853,14 @@ static void asm_gc_check(ASMState *as)
args[0] = ASMREF_TMP1; /* global_State *g */ args[0] = ASMREF_TMP1; /* global_State *g */
args[1] = ASMREF_TMP2; /* MSize steps */ args[1] = ASMREF_TMP2; /* MSize steps */
asm_gencall(as, ci, args); asm_gencall(as, ci, args);
tmp1 = ra_releasetmp(as, ASMREF_TMP1); emit_dm(as, A64I_MOVx, ra_releasetmp(as, ASMREF_TMP1), RID_GL);
tmp2 = ra_releasetmp(as, ASMREF_TMP2); tmp2 = ra_releasetmp(as, ASMREF_TMP2);
emit_loadi(as, tmp2, as->gcsteps); emit_loadi(as, tmp2, as->gcsteps);
/* Jump around GC step if GC total < GC threshold. */ /* Jump around GC step if GC total < GC threshold. */
emit_cond_branch(as, CC_LS, l_end); emit_cond_branch(as, CC_LS, l_end);
emit_nm(as, A64I_CMPx, RID_TMP, tmp2); emit_nm(as, A64I_CMPx, RID_TMP, tmp2);
emit_lso(as, A64I_LDRx, tmp2, tmp1, emit_getgl(as, tmp2, gc.threshold);
(int32_t)offsetof(global_State, gc.threshold)); emit_getgl(as, RID_TMP, gc.total);
emit_lso(as, A64I_LDRx, RID_TMP, tmp1,
(int32_t)offsetof(global_State, gc.total));
ra_allockreg(as, i64ptr(J2G(as->J)), tmp1);
as->gcsteps = 0; as->gcsteps = 0;
checkmclim(as); checkmclim(as);
} }
@@ -1846,6 +1883,12 @@ static void asm_loop_fixup(ASMState *as)
} }
} }
/* Fixup the tail of the loop. */
static void asm_loop_tail_fixup(ASMState *as)
{
UNUSED(as); /* Nothing to do. */
}
/* -- Head of trace ------------------------------------------------------- */ /* -- Head of trace ------------------------------------------------------- */
/* Reload L register from g->cur_L. */ /* Reload L register from g->cur_L. */
+143 -93
View File
@@ -1,6 +1,6 @@
/* /*
** MIPS IR assembler (SSA IR -> machine code). ** MIPS IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
/* -- Register allocator extensions --------------------------------------- */ /* -- Register allocator extensions --------------------------------------- */
@@ -64,19 +64,31 @@ static Reg ra_alloc2(ASMState *as, IRIns *ir, RegSet allow)
/* Setup spare long-range jump slots per mcarea. */ /* Setup spare long-range jump slots per mcarea. */
static void asm_sparejump_setup(ASMState *as) static void asm_sparejump_setup(ASMState *as)
{ {
MCode *mxp = as->mcbot; MCode *mxp = as->mctop;
if (((uintptr_t)mxp & (LJ_PAGESIZE-1)) == sizeof(MCLink)) { if ((char *)mxp == (char *)as->J->mcarea + as->J->szmcarea) {
mxp -= MIPS_SPAREJUMP*2;
lj_assertA(MIPSI_NOP == 0, "bad NOP"); lj_assertA(MIPSI_NOP == 0, "bad NOP");
memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode)); memset(mxp, 0, MIPS_SPAREJUMP*2*sizeof(MCode));
mxp += MIPS_SPAREJUMP*2; as->mctop = mxp;
lj_assertA(mxp < as->mctop, "MIPS_SPAREJUMP too big");
lj_mcode_sync(as->mcbot, mxp);
lj_mcode_commitbot(as->J, mxp);
as->mcbot = mxp;
as->mclim = as->mcbot + MCLIM_REDZONE;
} }
} }
static MCode *asm_sparejump_use(MCode *mcarea, MCode tjump)
{
MCode *mxp = (MCode *)((char *)mcarea + ((MCLink *)mcarea)->size);
int slot = MIPS_SPAREJUMP;
while (slot--) {
mxp -= 2;
if (*mxp == tjump) {
return mxp;
} else if (*mxp == MIPSI_NOP) {
*mxp = tjump;
return mxp;
}
}
return NULL;
}
/* Setup exit stub after the end of each trace. */ /* Setup exit stub after the end of each trace. */
static void asm_exitstub_setup(ASMState *as) static void asm_exitstub_setup(ASMState *as)
{ {
@@ -181,6 +193,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
return ra_allock(as, ofs-(int16_t)ofs, allow); return ra_allock(as, ofs-(int16_t)ofs, allow);
} }
} }
} else if (ir->o == IR_TMPREF) {
*ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
return RID_JGL;
} }
} }
*ofsp = 0; *ofsp = 0;
@@ -336,19 +351,15 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
{ {
RegSet drop = RSET_SCRATCH; RegSet drop = RSET_SCRATCH;
#if LJ_32
int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
#endif
#if !LJ_SOFTFP #if !LJ_SOFTFP
if ((ci->flags & CCI_NOFPRCLOBBER)) if ((ci->flags & CCI_NOFPRCLOBBER))
drop &= ~RSET_FPR; drop &= ~RSET_FPR;
#endif #endif
if (ra_hasreg(ir->r)) if (ra_hasreg(ir->r))
rset_clear(drop, ir->r); /* Dest reg handled below. */ rset_clear(drop, ir->r); /* Dest reg handled below. */
#if LJ_32
if (hiop && ra_hasreg((ir+1)->r)) if (hiop && ra_hasreg((ir+1)->r))
rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */ rset_clear(drop, (ir+1)->r); /* Dest reg handled below. */
#endif
ra_evictset(as, drop); /* Evictions must be performed first. */ ra_evictset(as, drop); /* Evictions must be performed first. */
if (ra_used(ir)) { if (ra_used(ir)) {
lj_assertA(!irt_ispri(ir->t), "PRI dest"); lj_assertA(!irt_ispri(ir->t), "PRI dest");
@@ -377,10 +388,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
} else { } else {
ra_destreg(as, ir, RID_FPRET); ra_destreg(as, ir, RID_FPRET);
} }
#if LJ_32
} else if (hiop) { } else if (hiop) {
ra_destpair(as, ir); ra_destpair(as, ir);
#endif
} else { } else {
ra_destreg(as, ir, RID_RET); ra_destreg(as, ir, RID_RET);
} }
@@ -450,6 +459,27 @@ static void asm_retf(ASMState *as, IRIns *ir)
emit_tsi(as, MIPSI_AL, RID_TMP, base, -8); emit_tsi(as, MIPSI_AL, RID_TMP, base, -8);
} }
/* -- Buffer operations --------------------------------------------------- */
#if LJ_HASBUFFER
static void asm_bufhdr_write(ASMState *as, Reg sb)
{
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
IRIns irgc;
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
if ((as->flags & JIT_F_MIPSXXR2)) {
emit_tsml(as, LJ_64 ? MIPSI_DINS : MIPSI_INS, RID_TMP, tmp,
lj_fls(SBUF_MASK_FLAG), 0);
} else {
emit_dst(as, MIPSI_OR, RID_TMP, RID_TMP, tmp);
emit_tsi(as, MIPSI_ANDI, tmp, tmp, SBUF_MASK_FLAG);
}
emit_getgl(as, RID_TMP, cur_L);
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
}
#endif
/* -- Type conversions ---------------------------------------------------- */ /* -- Type conversions ---------------------------------------------------- */
#if !LJ_SOFTFP #if !LJ_SOFTFP
@@ -739,7 +769,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
} }
} }
} else { } else {
if (st64) { if (st64 && !(ir->op2 & IRCONV_NONE)) {
/* This is either a 32 bit reg/reg mov which zeroes the hiword /* This is either a 32 bit reg/reg mov which zeroes the hiword
** or a load of the loword from a 64 bit address. ** or a load of the loword from a 64 bit address.
*/ */
@@ -827,34 +857,63 @@ static void asm_tvstore64(ASMState *as, Reg base, int32_t ofs, IRRef ref)
#endif #endif
/* Get pointer to TValue. */ /* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{ {
IRIns *ir = IR(ref); int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
if (irt_isnum(ir->t)) { if ((mode & IRTMPREF_IN1)) {
if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ IRIns *ir = IR(ref);
ra_allockreg(as, igcptr(ir_knum(ir)), dest); if (irt_isnum(ir->t)) {
else /* Otherwise force a spill and use the spill slot. */ if ((mode & IRTMPREF_OUT1)) {
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir)); #if LJ_SOFTFP
} else { emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
/* Otherwise use g->tmptv to hold the TValue. */ #if LJ_64
#if LJ_32 emit_setgl(as, ra_alloc1(as, ref, RSET_GPR), tmptv.u64);
RegSet allow = rset_exclude(RSET_GPR, dest);
Reg type;
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, (int32_t)(offsetof(global_State, tmptv)-32768));
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, allow);
emit_setgl(as, src, tmptv.gcr);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP)
type = ra_alloc1(as, ref+1, allow);
else
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
emit_setgl(as, type, tmptv.it);
#else #else
asm_tvstore64(as, dest, 0, ref); lj_assertA(irref_isk(ref), "unsplit FP op");
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, emit_setgl(as,
(int32_t)(offsetof(global_State, tmptv)-32768)); ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
tmptv.u32.lo);
emit_setgl(as,
ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
tmptv.u32.hi);
#endif #endif
#else
Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
emit_tsi(as, MIPSI_SDC1, (src & 31), RID_JGL, tmpofs);
#endif
} else if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, igcptr(ir_knum(ir)), dest);
} else {
#if LJ_SOFTFP32
lj_assertA(0, "unsplit FP op");
#else
/* Otherwise force a spill and use the spill slot. */
emit_tsi(as, MIPSI_AADDIU, dest, RID_SP, ra_spill(as, ir));
#endif
}
} else {
/* Otherwise use g->tmptv to hold the TValue. */
#if LJ_32
Reg type;
emit_tsi(as, MIPSI_ADDIU, dest, RID_JGL, tmpofs);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_GPR);
emit_setgl(as, src, tmptv.gcr);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
type = ra_alloc1(as, ref+1, RSET_GPR);
else
type = ra_allock(as, (int32_t)irt_toitype(ir->t), RSET_GPR);
emit_setgl(as, type, tmptv.it);
#else
asm_tvstore64(as, dest, 0, ref);
emit_tsi(as, MIPSI_DADDIU, dest, RID_JGL, tmpofs);
#endif
}
} else {
emit_tsi(as, MIPSI_AADDIU, dest, RID_JGL, tmpofs);
} }
} }
@@ -909,11 +968,16 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
MCLabel l_end, l_loop, l_next; MCLabel l_end, l_loop, l_next;
rset_clear(allow, tab); rset_clear(allow, tab);
#if LJ_SOFTFP32 if (!LJ_SOFTFP && irt_isnum(kt)) {
if (!isk) { key = ra_alloc1(as, refkey, RSET_FPR);
key = ra_alloc1(as, refkey, allow); tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
rset_clear(allow, key); } else {
if (irkey[1].o == IR_HIOP) { if (!irt_ispri(kt)) {
key = ra_alloc1(as, refkey, allow);
rset_clear(allow, key);
}
#if LJ_32
if (LJ_SOFTFP && irkey[1].o == IR_HIOP) {
if (ra_hasreg((irkey+1)->r)) { if (ra_hasreg((irkey+1)->r)) {
type = tmpnum = (irkey+1)->r; type = tmpnum = (irkey+1)->r;
tmp1 = ra_scratch(as, allow); tmp1 = ra_scratch(as, allow);
@@ -924,23 +988,11 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
} }
rset_clear(allow, tmpnum); rset_clear(allow, tmpnum);
} else { } else {
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow); type = ra_allock(as, (int32_t)irt_toitype(kt), allow);
rset_clear(allow, type); rset_clear(allow, type);
} }
}
#else
if (!LJ_SOFTFP && irt_isnum(kt)) {
key = ra_alloc1(as, refkey, RSET_FPR);
tmpnum = ra_scratch(as, rset_exclude(RSET_FPR, key));
} else if (!irt_ispri(kt)) {
key = ra_alloc1(as, refkey, allow);
rset_clear(allow, key);
#if LJ_32
type = ra_allock(as, (int32_t)irt_toitype(irkey->t), allow);
rset_clear(allow, type);
#endif #endif
} }
#endif
tmp2 = ra_scratch(as, allow); tmp2 = ra_scratch(as, allow);
rset_clear(allow, tmp2); rset_clear(allow, tmp2);
#if LJ_64 #if LJ_64
@@ -953,10 +1005,10 @@ static void asm_href(ASMState *as, IRIns *ir, IROp merge)
} else { } else {
int64_t k; int64_t k;
if (isk && irt_isaddr(kt)) { if (isk && irt_isaddr(kt)) {
k = ((int64_t)irt_toitype(irkey->t) << 47) | irkey[1].tv.u64; k = ((int64_t)irt_toitype(kt) << 47) | irkey[1].tv.u64;
} else { } else {
lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type"); lj_assertA(irt_ispri(kt) && !irt_isnil(kt), "bad HREF key type");
k = ~((int64_t)~irt_toitype(ir->t) << 47); k = ~((int64_t)~irt_toitype(kt) << 47);
} }
cmp64 = ra_allock(as, k, allow); cmp64 = ra_allock(as, k, allow);
rset_clear(allow, cmp64); rset_clear(allow, cmp64);
@@ -1352,6 +1404,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
#endif #endif
} }
idx = asm_fuseahuref(as, ir->op1, &ofs, allow); idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
if (ir->o == IR_VLOAD) ofs += 8 * ir->op2;
rset_clear(allow, idx); rset_clear(allow, idx);
if (irt_isnum(t)) { if (irt_isnum(t)) {
asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO); asm_guard(as, MIPSI_BEQ, RID_TMP, RID_ZERO);
@@ -2327,15 +2380,15 @@ static void asm_comp64eq(ASMState *as, IRIns *ir)
} }
#endif #endif
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ /* -- Split register ops -------------------------------------------------- */
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ /* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */
static void asm_hiop(ASMState *as, IRIns *ir) static void asm_hiop(ASMState *as, IRIns *ir)
{ {
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
/* HIOP is marked as a store because it needs its own DCE logic. */ /* HIOP is marked as a store because it needs its own DCE logic. */
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
#if LJ_32 && (LJ_HASFFI || LJ_SOFTFP)
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
as->curins--; /* Always skip the CONV. */ as->curins--; /* Always skip the CONV. */
#if LJ_HASFFI && !LJ_SOFTFP #if LJ_HASFFI && !LJ_SOFTFP
@@ -2382,38 +2435,33 @@ static void asm_hiop(ASMState *as, IRIns *ir)
} }
return; return;
} }
#endif
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
switch ((ir-1)->o) { switch ((ir-1)->o) {
#if LJ_HASFFI #if LJ_32 && LJ_HASFFI
case IR_ADD: as->curins--; asm_add64(as, ir); break; case IR_ADD: as->curins--; asm_add64(as, ir); break;
case IR_SUB: as->curins--; asm_sub64(as, ir); break; case IR_SUB: as->curins--; asm_sub64(as, ir); break;
case IR_NEG: as->curins--; asm_neg64(as, ir); break; case IR_NEG: as->curins--; asm_neg64(as, ir); break;
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif #endif
#if LJ_SOFTFP #if LJ_32 && LJ_SOFTFP
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
case IR_STRTO: case IR_STRTO:
if (!uselo) if (!uselo)
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
break; break;
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif #endif
case IR_CALLN: case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
case IR_CALLS:
case IR_CALLXS:
if (!uselo) if (!uselo)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break; break;
#if LJ_SOFTFP
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
#endif
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
} }
#else
/* Unused on MIPS64 or without SOFTFP or FFI. */
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
#endif
} }
/* -- Profiling ----------------------------------------------------------- */ /* -- Profiling ----------------------------------------------------------- */
@@ -2513,6 +2561,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
} else if ((sn & SNAP_SOFTFPNUM)) { } else if ((sn & SNAP_SOFTFPNUM)) {
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE)); type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
#endif #endif
} else if ((sn & SNAP_KEYINDEX)) {
type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow);
} else { } else {
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
} }
@@ -2575,6 +2625,12 @@ static void asm_loop_fixup(ASMState *as)
} }
} }
/* Fixup the tail of the loop. */
static void asm_loop_tail_fixup(ASMState *as)
{
if (as->loopinv) as->mctop--;
}
/* -- Head of trace ------------------------------------------------------- */ /* -- Head of trace ------------------------------------------------------- */
/* Coalesce BASE register for a root trace. */ /* Coalesce BASE register for a root trace. */
@@ -2582,7 +2638,6 @@ static void asm_head_root_base(ASMState *as)
{ {
IRIns *ir = IR(REF_BASE); IRIns *ir = IR(REF_BASE);
Reg r = ir->r; Reg r = ir->r;
if (as->loopinv) as->mctop--;
if (ra_hasreg(r)) { if (ra_hasreg(r)) {
ra_free(as, r); ra_free(as, r);
if (rset_test(as->modset, r) || irt_ismarked(ir->t)) if (rset_test(as->modset, r) || irt_ismarked(ir->t))
@@ -2597,7 +2652,6 @@ static RegSet asm_head_side_base(ASMState *as, IRIns *irp, RegSet allow)
{ {
IRIns *ir = IR(REF_BASE); IRIns *ir = IR(REF_BASE);
Reg r = ir->r; Reg r = ir->r;
if (as->loopinv) as->mctop--;
if (ra_hasreg(r)) { if (ra_hasreg(r)) {
ra_free(as, r); ra_free(as, r);
if (rset_test(as->modset, r) || irt_ismarked(ir->t)) if (rset_test(as->modset, r) || irt_ismarked(ir->t))
@@ -2704,21 +2758,17 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target)
patchbranch: patchbranch:
p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu); p[-1] = (p[-1] & 0xffff0000u) | (delta & 0xffffu);
*p = MIPSI_NOP; /* Replace the load of the exit number. */ *p = MIPSI_NOP; /* Replace the load of the exit number. */
cstop = p; cstop = p+1;
if (!cstart) cstart = p-1; if (!cstart) cstart = p-1;
} else { /* Branch out of range. Use spare jump slot in mcarea. */ } else { /* Branch out of range. Use spare jump slot in mcarea. */
int i; MCode *mcjump = asm_sparejump_use(mcarea, tjump);
for (i = (int)(sizeof(MCLink)/sizeof(MCode)); if (mcjump) {
i < (int)(sizeof(MCLink)/sizeof(MCode)+MIPS_SPAREJUMP*2); lj_mcode_sync(mcjump, mcjump+1);
i += 2) { delta = mcjump - p;
if (mcarea[i] == tjump) { if (((delta + 0x8000) >> 16) == 0) {
delta = mcarea+i - p;
goto patchbranch;
} else if (mcarea[i] == MIPSI_NOP) {
mcarea[i] = tjump;
cstart = mcarea+i;
delta = mcarea+i - p;
goto patchbranch; goto patchbranch;
} else {
lj_assertJ(0, "spare jump out of range: -Osizemcode too big");
} }
} }
/* Ignore jump slot overflow. Child trace is simply not attached. */ /* Ignore jump slot overflow. Child trace is simply not attached. */
+91 -41
View File
@@ -1,6 +1,6 @@
/* /*
** PPC IR assembler (SSA IR -> machine code). ** PPC IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
/* -- Register allocator extensions --------------------------------------- */ /* -- Register allocator extensions --------------------------------------- */
@@ -156,6 +156,9 @@ static Reg asm_fuseahuref(ASMState *as, IRRef ref, int32_t *ofsp, RegSet allow)
return ra_allock(as, ofs-(int16_t)ofs, allow); return ra_allock(as, ofs-(int16_t)ofs, allow);
} }
} }
} else if (ir->o == IR_TMPREF) {
*ofsp = (int32_t)(offsetof(global_State, tmptv)-32768);
return RID_JGL;
} }
} }
*ofsp = 0; *ofsp = 0;
@@ -337,10 +340,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
} else { } else {
ra_destreg(as, ir, RID_FPRET); ra_destreg(as, ir, RID_FPRET);
} }
#if LJ_32
} else if (hiop) { } else if (hiop) {
ra_destpair(as, ir); ra_destpair(as, ir);
#endif
} else { } else {
ra_destreg(as, ir, RID_RET); ra_destreg(as, ir, RID_RET);
} }
@@ -389,6 +390,21 @@ static void asm_retf(ASMState *as, IRIns *ir)
emit_tai(as, PPCI_LWZ, RID_TMP, base, -8); emit_tai(as, PPCI_LWZ, RID_TMP, base, -8);
} }
/* -- Buffer operations --------------------------------------------------- */
#if LJ_HASBUFFER
static void asm_bufhdr_write(ASMState *as, Reg sb)
{
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
IRIns irgc;
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
emit_storeofs(as, &irgc, RID_TMP, sb, offsetof(SBuf, L));
emit_rot(as, PPCI_RLWIMI, RID_TMP, tmp, 0, 31-lj_fls(SBUF_MASK_FLAG), 31);
emit_getgl(as, RID_TMP, cur_L);
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
}
#endif
/* -- Type conversions ---------------------------------------------------- */ /* -- Type conversions ---------------------------------------------------- */
#if !LJ_SOFTFP #if !LJ_SOFTFP
@@ -567,28 +583,54 @@ static void asm_strto(ASMState *as, IRIns *ir)
/* -- Memory references --------------------------------------------------- */ /* -- Memory references --------------------------------------------------- */
/* Get pointer to TValue. */ /* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{ {
IRIns *ir = IR(ref); int32_t tmpofs = (int32_t)(offsetof(global_State, tmptv)-32768);
if (irt_isnum(ir->t)) { if ((mode & IRTMPREF_IN1)) {
if (irref_isk(ref)) /* Use the number constant itself as a TValue. */ IRIns *ir = IR(ref);
ra_allockreg(as, i32ptr(ir_knum(ir)), dest); if (irt_isnum(ir->t)) {
else /* Otherwise force a spill and use the spill slot. */ if ((mode & IRTMPREF_OUT1)) {
emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir)); #if LJ_SOFTFP
} else { lj_assertA(irref_isk(ref), "unsplit FP op");
/* Otherwise use g->tmptv to hold the TValue. */ emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
RegSet allow = rset_exclude(RSET_GPR, dest); emit_setgl(as,
Reg type; ra_allock(as, (int32_t)ir_knum(ir)->u32.lo, RSET_GPR),
emit_tai(as, PPCI_ADDI, dest, RID_JGL, (int32_t)offsetof(global_State, tmptv)-32768); tmptv.u32.lo);
if (!irt_ispri(ir->t)) { emit_setgl(as,
Reg src = ra_alloc1(as, ref, allow); ra_allock(as, (int32_t)ir_knum(ir)->u32.hi, RSET_GPR),
emit_setgl(as, src, tmptv.gcr); tmptv.u32.hi);
#else
Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
emit_fai(as, PPCI_STFD, src, RID_JGL, tmpofs);
#endif
} else if (irref_isk(ref)) {
/* Use the number constant itself as a TValue. */
ra_allockreg(as, i32ptr(ir_knum(ir)), dest);
} else {
#if LJ_SOFTFP
lj_assertA(0, "unsplit FP op");
#else
/* Otherwise force a spill and use the spill slot. */
emit_tai(as, PPCI_ADDI, dest, RID_SP, ra_spill(as, ir));
#endif
}
} else {
/* Otherwise use g->tmptv to hold the TValue. */
Reg type;
emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
if (!irt_ispri(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_GPR);
emit_setgl(as, src, tmptv.gcr);
}
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t))
type = ra_alloc1(as, ref+1, RSET_GPR);
else
type = ra_allock(as, irt_toitype(ir->t), RSET_GPR);
emit_setgl(as, type, tmptv.it);
} }
if (LJ_SOFTFP && (ir+1)->o == IR_HIOP) } else {
type = ra_alloc1(as, ref+1, allow); emit_tai(as, PPCI_ADDI, dest, RID_JGL, tmpofs);
else
type = ra_allock(as, irt_toitype(ir->t), allow);
emit_setgl(as, type, tmptv.it);
} }
} }
@@ -894,7 +936,7 @@ static void asm_fload(ASMState *as, IRIns *ir)
int32_t ofs; int32_t ofs;
if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */ if (ir->op1 == REF_NIL) { /* FLOAD from GG_State with offset. */
idx = RID_JGL; idx = RID_JGL;
ofs = (ir->op2 << 2) - 32768; ofs = (ir->op2 << 2) - 32768 - GG_OFS(g);
} else { } else {
idx = ra_alloc1(as, ir->op1, RSET_GPR); idx = ra_alloc1(as, ir->op1, RSET_GPR);
if (ir->op2 == IRFL_TAB_ARRAY) { if (ir->op2 == IRFL_TAB_ARRAY) {
@@ -975,6 +1017,10 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
rset_clear(allow, dest); rset_clear(allow, dest);
} }
idx = asm_fuseahuref(as, ir->op1, &ofs, allow); idx = asm_fuseahuref(as, ir->op1, &ofs, allow);
if (ir->o == IR_VLOAD) {
ofs = ofs != AHUREF_LSX ? ofs + 8 * ir->op2 :
ir->op2 ? 8 * ir->op2 : AHUREF_LSX;
}
if (irt_isnum(t)) { if (irt_isnum(t)) {
Reg tisnum = ra_allock(as, (int32_t)LJ_TISNUM, rset_exclude(allow, idx)); Reg tisnum = ra_allock(as, (int32_t)LJ_TISNUM, rset_exclude(allow, idx));
asm_guardcc(as, CC_GE); asm_guardcc(as, CC_GE);
@@ -1057,7 +1103,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK), lj_assertA(irt_isguard(ir->t) || !(ir->op2 & IRSLOAD_TYPECHECK),
"inconsistent SLOAD variant"); "inconsistent SLOAD variant");
lj_assertA(LJ_DUALNUM || lj_assertA(LJ_DUALNUM ||
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)), !irt_isint(t) ||
(ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME|IRSLOAD_KEYINDEX)),
"bad SLOAD type"); "bad SLOAD type");
#if LJ_SOFTFP #if LJ_SOFTFP
lj_assertA(!(ir->op2 & IRSLOAD_CONVERT), lj_assertA(!(ir->op2 & IRSLOAD_CONVERT),
@@ -1894,15 +1941,15 @@ static void asm_comp64(ASMState *as, IRIns *ir)
} }
#endif #endif
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ /* -- Split register ops -------------------------------------------------- */
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ /* Hiword op of a split 32/32 bit op. Previous op is be the loword op. */
static void asm_hiop(ASMState *as, IRIns *ir) static void asm_hiop(ASMState *as, IRIns *ir)
{ {
#if LJ_HASFFI || LJ_SOFTFP
/* HIOP is marked as a store because it needs its own DCE logic. */ /* HIOP is marked as a store because it needs its own DCE logic. */
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
#if LJ_HASFFI || LJ_SOFTFP
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
as->curins--; /* Always skip the CONV. */ as->curins--; /* Always skip the CONV. */
#if LJ_HASFFI && !LJ_SOFTFP #if LJ_HASFFI && !LJ_SOFTFP
@@ -1937,12 +1984,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
} }
return; return;
} }
#endif
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
switch ((ir-1)->o) { switch ((ir-1)->o) {
#if LJ_HASFFI #if LJ_HASFFI
case IR_ADD: as->curins--; asm_add64(as, ir); break; case IR_ADD: as->curins--; asm_add64(as, ir); break;
case IR_SUB: as->curins--; asm_sub64(as, ir); break; case IR_SUB: as->curins--; asm_sub64(as, ir); break;
case IR_NEG: as->curins--; asm_neg64(as, ir); break; case IR_NEG: as->curins--; asm_neg64(as, ir); break;
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif #endif
#if LJ_SOFTFP #if LJ_SOFTFP
case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD: case IR_SLOAD: case IR_ALOAD: case IR_HLOAD: case IR_ULOAD: case IR_VLOAD:
@@ -1950,25 +2001,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
if (!uselo) if (!uselo)
ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */ ra_allocref(as, ir->op1, RSET_GPR); /* Mark lo op as used. */
break; break;
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR: case IR_TMPREF:
/* Nothing to do here. Handled by lo op itself. */
break;
#endif #endif
case IR_CALLN: case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
case IR_CALLS:
case IR_CALLXS:
if (!uselo) if (!uselo)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */ ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break; break;
#if LJ_SOFTFP
case IR_ASTORE: case IR_HSTORE: case IR_USTORE: case IR_TOSTR:
#endif
case IR_CNEWI:
/* Nothing to do here. Handled by lo op itself. */
break;
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
} }
#else
/* Unused without SOFTFP or FFI. */
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
#endif
} }
/* -- Profiling ----------------------------------------------------------- */ /* -- Profiling ----------------------------------------------------------- */
@@ -2055,6 +2097,8 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
} else if ((sn & SNAP_SOFTFPNUM)) { } else if ((sn & SNAP_SOFTFPNUM)) {
type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE)); type = ra_alloc1(as, ref+1, rset_exclude(RSET_GPR, RID_BASE));
#endif #endif
} else if ((sn & SNAP_KEYINDEX)) {
type = ra_allock(as, (int32_t)LJ_KEYINDEX, allow);
} else { } else {
type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow); type = ra_allock(as, (int32_t)irt_toitype(ir->t), allow);
} }
@@ -2113,6 +2157,12 @@ static void asm_loop_fixup(ASMState *as)
} }
} }
/* Fixup the tail of the loop. */
static void asm_loop_tail_fixup(ASMState *as)
{
UNUSED(as); /* Nothing to do. */
}
/* -- Head of trace ------------------------------------------------------- */ /* -- Head of trace ------------------------------------------------------- */
/* Coalesce BASE register for a root trace. */ /* Coalesce BASE register for a root trace. */
+96 -58
View File
@@ -1,6 +1,6 @@
/* /*
** x86/x64 IR assembler (SSA IR -> machine code). ** x86/x64 IR assembler (SSA IR -> machine code).
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
/* -- Guard handling ------------------------------------------------------ */ /* -- Guard handling ------------------------------------------------------ */
@@ -216,10 +216,17 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow)
#endif #endif
} }
break; break;
case IR_TMPREF:
#if LJ_GC64
as->mrm.ofs = (int32_t)dispofs(as, &J2G(as->J)->tmptv);
as->mrm.base = RID_DISPATCH;
as->mrm.idx = RID_NONE;
#else
as->mrm.ofs = igcptr(&J2G(as->J)->tmptv);
as->mrm.base = as->mrm.idx = RID_NONE;
#endif
return;
default: default:
lj_assertA(ir->o == IR_HREF || ir->o == IR_NEWREF || ir->o == IR_UREFO ||
ir->o == IR_KKPTR,
"bad IR op %d", ir->o);
break; break;
} }
} }
@@ -480,6 +487,7 @@ static Reg asm_fuseload(ASMState *as, IRRef ref, RegSet allow)
} }
} else if (ir->o == IR_VLOAD && !(LJ_GC64 && irt_isaddr(ir->t))) { } else if (ir->o == IR_VLOAD && !(LJ_GC64 && irt_isaddr(ir->t))) {
asm_fuseahuref(as, ir->op1, xallow); asm_fuseahuref(as, ir->op1, xallow);
as->mrm.ofs += 8 * ir->op2;
return RID_MRM; return RID_MRM;
} }
} }
@@ -651,7 +659,7 @@ static void asm_gencall(ASMState *as, const CCallInfo *ci, IRRef *args)
static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci) static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
{ {
RegSet drop = RSET_SCRATCH; RegSet drop = RSET_SCRATCH;
int hiop = (LJ_32 && (ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t)); int hiop = ((ir+1)->o == IR_HIOP && !irt_isnil((ir+1)->t));
if ((ci->flags & CCI_NOFPRCLOBBER)) if ((ci->flags & CCI_NOFPRCLOBBER))
drop &= ~RSET_FPR; drop &= ~RSET_FPR;
if (ra_hasreg(ir->r)) if (ra_hasreg(ir->r))
@@ -691,10 +699,8 @@ static void asm_setupresult(ASMState *as, IRIns *ir, const CCallInfo *ci)
irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs); irt_isnum(ir->t) ? XOg_FSTPq : XOg_FSTPd, RID_ESP, ofs);
} }
#endif #endif
#if LJ_32
} else if (hiop) { } else if (hiop) {
ra_destpair(as, ir); ra_destpair(as, ir);
#endif
} else { } else {
lj_assertA(!irt_ispri(ir->t), "PRI dest"); lj_assertA(!irt_ispri(ir->t), "PRI dest");
ra_destreg(as, ir, RID_RET); ra_destreg(as, ir, RID_RET);
@@ -781,6 +787,21 @@ static void asm_retf(ASMState *as, IRIns *ir)
#endif #endif
} }
/* -- Buffer operations --------------------------------------------------- */
#if LJ_HASBUFFER
static void asm_bufhdr_write(ASMState *as, Reg sb)
{
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, sb));
IRIns irgc;
irgc.ot = IRT(0, IRT_PGC); /* GC type. */
emit_storeofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
emit_opgl(as, XO_ARITH(XOg_OR), tmp|REX_GC64, cur_L);
emit_gri(as, XG_ARITHi(XOg_AND), tmp, SBUF_MASK_FLAG);
emit_loadofs(as, &irgc, tmp, sb, offsetof(SBuf, L));
}
#endif
/* -- Type conversions ---------------------------------------------------- */ /* -- Type conversions ---------------------------------------------------- */
static void asm_tointg(ASMState *as, IRIns *ir, Reg left) static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
@@ -924,7 +945,7 @@ static void asm_conv(ASMState *as, IRIns *ir)
} }
} else { } else {
Reg dest = ra_dest(as, ir, RSET_GPR); Reg dest = ra_dest(as, ir, RSET_GPR);
if (st64) { if (st64 && !(ir->op2 & IRCONV_NONE)) {
Reg left = asm_fuseload(as, lref, RSET_GPR); Reg left = asm_fuseload(as, lref, RSET_GPR);
/* This is either a 32 bit reg/reg mov which zeroes the hiword /* This is either a 32 bit reg/reg mov which zeroes the hiword
** or a load of the loword from a 64 bit address. ** or a load of the loword from a 64 bit address.
@@ -1050,47 +1071,48 @@ static void asm_strto(ASMState *as, IRIns *ir)
/* -- Memory references --------------------------------------------------- */ /* -- Memory references --------------------------------------------------- */
/* Get pointer to TValue. */ /* Get pointer to TValue. */
static void asm_tvptr(ASMState *as, Reg dest, IRRef ref) static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
{ {
IRIns *ir = IR(ref); if ((mode & IRTMPREF_IN1)) {
if (irt_isnum(ir->t)) { IRIns *ir = IR(ref);
/* For numbers use the constant itself or a spill slot as a TValue. */ if (irt_isnum(ir->t)) {
if (irref_isk(ref)) if (irref_isk(ref) && !(mode & IRTMPREF_OUT1)) {
emit_loada(as, dest, ir_knum(ir)); /* Use the number constant itself as a TValue. */
else emit_loada(as, dest, ir_knum(ir));
emit_rmro(as, XO_LEA, dest|REX_64, RID_ESP, ra_spill(as, ir)); return;
} else { }
/* Otherwise use g->tmptv to hold the TValue. */ emit_rmro(as, XO_MOVSDto, ra_alloc1(as, ref, RSET_FPR), dest, 0);
#if LJ_GC64 } else {
if (irref_isk(ref)) { #if LJ_GC64
TValue k; if (irref_isk(ref)) {
lj_ir_kvalue(as->J->L, &k, ir); TValue k;
emit_movmroi(as, dest, 4, k.u32.hi); lj_ir_kvalue(as->J->L, &k, ir);
emit_movmroi(as, dest, 0, k.u32.lo); emit_movmroi(as, dest, 4, k.u32.hi);
} else { emit_movmroi(as, dest, 0, k.u32.lo);
/* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */ } else {
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); /* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */
if (irt_is64(ir->t)) { Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
emit_u32(as, irt_toitype(ir->t) << 15); if (irt_is64(ir->t)) {
emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4); emit_u32(as, irt_toitype(ir->t) << 15);
} else { emit_rmro(as, XO_ARITHi, XOg_OR, dest, 4);
/* Currently, no caller passes integers that might end up here. */ } else {
emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15)); emit_movmroi(as, dest, 4, (irt_toitype(ir->t) << 15));
}
emit_movtomro(as, REX_64IR(ir, src), dest, 0);
} }
emit_movtomro(as, REX_64IR(ir, src), dest, 0);
}
#else #else
if (!irref_isk(ref)) { if (!irref_isk(ref)) {
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest)); Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
emit_movtomro(as, REX_64IR(ir, src), dest, 0); emit_movtomro(as, REX_64IR(ir, src), dest, 0);
} else if (!irt_ispri(ir->t)) { } else if (!irt_ispri(ir->t)) {
emit_movmroi(as, dest, 0, ir->i); emit_movmroi(as, dest, 0, ir->i);
} }
if (!(LJ_64 && irt_islightud(ir->t))) if (!(LJ_64 && irt_islightud(ir->t)))
emit_movmroi(as, dest, 4, irt_toitype(ir->t)); emit_movmroi(as, dest, 4, irt_toitype(ir->t));
#endif #endif
emit_loada(as, dest, &J2G(as->J)->tmptv); }
} }
emit_loada(as, dest, &J2G(as->J)->tmptv); /* g->tmptv holds the TValue(s). */
} }
static void asm_aref(ASMState *as, IRIns *ir) static void asm_aref(ASMState *as, IRIns *ir)
@@ -1524,6 +1546,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
Reg dest = asm_load_lightud64(as, ir, 1); Reg dest = asm_load_lightud64(as, ir, 1);
if (ra_hasreg(dest)) { if (ra_hasreg(dest)) {
asm_fuseahuref(as, ir->op1, RSET_GPR); asm_fuseahuref(as, ir->op1, RSET_GPR);
if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2;
emit_mrm(as, XO_MOV, dest|REX_64, RID_MRM); emit_mrm(as, XO_MOV, dest|REX_64, RID_MRM);
} }
return; return;
@@ -1533,6 +1556,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
RegSet allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR; RegSet allow = irt_isnum(ir->t) ? RSET_FPR : RSET_GPR;
Reg dest = ra_dest(as, ir, allow); Reg dest = ra_dest(as, ir, allow);
asm_fuseahuref(as, ir->op1, RSET_GPR); asm_fuseahuref(as, ir->op1, RSET_GPR);
if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2;
#if LJ_GC64 #if LJ_GC64
if (irt_isaddr(ir->t)) { if (irt_isaddr(ir->t)) {
emit_shifti(as, XOg_SHR|REX_64, dest, 17); emit_shifti(as, XOg_SHR|REX_64, dest, 17);
@@ -1560,6 +1584,7 @@ static void asm_ahuvload(ASMState *as, IRIns *ir)
} }
#endif #endif
asm_fuseahuref(as, ir->op1, gpr); asm_fuseahuref(as, ir->op1, gpr);
if (ir->o == IR_VLOAD) as->mrm.ofs += 8 * ir->op2;
} }
/* Always do the type check, even if the load result is unused. */ /* Always do the type check, even if the load result is unused. */
as->mrm.ofs += 4; as->mrm.ofs += 4;
@@ -1675,7 +1700,8 @@ static void asm_sload(ASMState *as, IRIns *ir)
lj_assertA(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK), lj_assertA(irt_isguard(t) || !(ir->op2 & IRSLOAD_TYPECHECK),
"inconsistent SLOAD variant"); "inconsistent SLOAD variant");
lj_assertA(LJ_DUALNUM || lj_assertA(LJ_DUALNUM ||
!irt_isint(t) || (ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME)), !irt_isint(t) ||
(ir->op2 & (IRSLOAD_CONVERT|IRSLOAD_FRAME|IRSLOAD_KEYINDEX)),
"bad SLOAD type"); "bad SLOAD type");
if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) { if ((ir->op2 & IRSLOAD_CONVERT) && irt_isguard(t) && irt_isint(t)) {
Reg left = ra_scratch(as, RSET_FPR); Reg left = ra_scratch(as, RSET_FPR);
@@ -2584,15 +2610,15 @@ static void asm_comp_int64(ASMState *as, IRIns *ir)
} }
#endif #endif
/* -- Support for 64 bit ops in 32 bit mode ------------------------------- */ /* -- Split register ops -------------------------------------------------- */
/* Hiword op of a split 64 bit op. Previous op must be the loword op. */ /* Hiword op of a split 32/32 or 64/64 bit op. Previous op is the loword op. */
static void asm_hiop(ASMState *as, IRIns *ir) static void asm_hiop(ASMState *as, IRIns *ir)
{ {
#if LJ_32 && LJ_HASFFI
/* HIOP is marked as a store because it needs its own DCE logic. */ /* HIOP is marked as a store because it needs its own DCE logic. */
int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */ int uselo = ra_used(ir-1), usehi = ra_used(ir); /* Loword/hiword used? */
if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1; if (LJ_UNLIKELY(!(as->flags & JIT_F_OPT_DCE))) uselo = usehi = 1;
#if LJ_32 && LJ_HASFFI
if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */ if ((ir-1)->o == IR_CONV) { /* Conversions to/from 64 bit. */
as->curins--; /* Always skip the CONV. */ as->curins--; /* Always skip the CONV. */
if (usehi || uselo) if (usehi || uselo)
@@ -2606,8 +2632,10 @@ static void asm_hiop(ASMState *as, IRIns *ir)
asm_fxstore(as, ir); asm_fxstore(as, ir);
return; return;
} }
#endif
if (!usehi) return; /* Skip unused hiword op for all remaining ops. */ if (!usehi) return; /* Skip unused hiword op for all remaining ops. */
switch ((ir-1)->o) { switch ((ir-1)->o) {
#if LJ_32 && LJ_HASFFI
case IR_ADD: case IR_ADD:
as->flagmcp = NULL; as->flagmcp = NULL;
as->curins--; as->curins--;
@@ -2630,20 +2658,16 @@ static void asm_hiop(ASMState *as, IRIns *ir)
asm_neg_not(as, ir-1, XOg_NEG); asm_neg_not(as, ir-1, XOg_NEG);
break; break;
} }
case IR_CALLN:
case IR_CALLXS:
if (!uselo)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break;
case IR_CNEWI: case IR_CNEWI:
/* Nothing to do here. Handled by CNEWI itself. */ /* Nothing to do here. Handled by CNEWI itself. */
break; break;
#endif
case IR_CALLN: case IR_CALLL: case IR_CALLS: case IR_CALLXS:
if (!uselo)
ra_allocref(as, ir->op1, RID2RSET(RID_RETLO)); /* Mark lo op as used. */
break;
default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break; default: lj_assertA(0, "bad HIOP for op %d", (ir-1)->o); break;
} }
#else
/* Unused on x64 or without FFI. */
UNUSED(as); UNUSED(ir); lj_assertA(0, "unexpected HIOP");
#endif
} }
/* -- Profiling ----------------------------------------------------------- */ /* -- Profiling ----------------------------------------------------------- */
@@ -2704,7 +2728,15 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
IRIns *ir = IR(ref); IRIns *ir = IR(ref);
if ((sn & SNAP_NORESTORE)) if ((sn & SNAP_NORESTORE))
continue; continue;
if (irt_isnum(ir->t)) { if ((sn & SNAP_KEYINDEX)) {
emit_movmroi(as, RID_BASE, ofs+4, LJ_KEYINDEX);
if (irref_isk(ref)) {
emit_movmroi(as, RID_BASE, ofs, ir->i);
} else {
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, RID_BASE));
emit_movtomro(as, src, RID_BASE, ofs);
}
} else if (irt_isnum(ir->t)) {
Reg src = ra_alloc1(as, ref, RSET_FPR); Reg src = ra_alloc1(as, ref, RSET_FPR);
emit_rmro(as, XO_MOVSDto, src, RID_BASE, ofs); emit_rmro(as, XO_MOVSDto, src, RID_BASE, ofs);
} else { } else {
@@ -2837,6 +2869,12 @@ static void asm_loop_fixup(ASMState *as)
} }
} }
/* Fixup the tail of the loop. */
static void asm_loop_tail_fixup(ASMState *as)
{
UNUSED(as); /* Nothing to do. */
}
/* -- Head of trace ------------------------------------------------------- */ /* -- Head of trace ------------------------------------------------------- */
/* Coalesce BASE register for a root trace. */ /* Coalesce BASE register for a root trace. */
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Internal assertions. ** Internal assertions.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lj_assert_c #define lj_assert_c
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Bytecode instruction modes. ** Bytecode instruction modes.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lj_bc_c #define lj_bc_c
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Bytecode instruction format. ** Bytecode instruction format.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#ifndef _LJ_BC_H #ifndef _LJ_BC_H
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** Bytecode dump definitions. ** Bytecode dump definitions.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#ifndef _LJ_BCDUMP_H #ifndef _LJ_BCDUMP_H
+7 -11
View File
@@ -1,6 +1,6 @@
/* /*
** Bytecode reader. ** Bytecode reader.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lj_bcread_c #define lj_bcread_c
@@ -53,11 +53,11 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
do { do {
const char *buf; const char *buf;
size_t sz; size_t sz;
char *p = sbufB(&ls->sb); char *p = ls->sb.b;
MSize n = (MSize)(ls->pe - ls->p); MSize n = (MSize)(ls->pe - ls->p);
if (n) { /* Copy remainder to buffer. */ if (n) { /* Copy remainder to buffer. */
if (sbuflen(&ls->sb)) { /* Move down in buffer. */ if (sbuflen(&ls->sb)) { /* Move down in buffer. */
lj_assertLS(ls->pe == sbufP(&ls->sb), "bad buffer pointer"); lj_assertLS(ls->pe == ls->sb.w, "bad buffer pointer");
if (ls->p != p) memmove(p, ls->p, n); if (ls->p != p) memmove(p, ls->p, n);
} else { /* Copy from buffer provided by reader. */ } else { /* Copy from buffer provided by reader. */
p = lj_buf_need(&ls->sb, len); p = lj_buf_need(&ls->sb, len);
@@ -66,7 +66,7 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
ls->p = p; ls->p = p;
ls->pe = p + n; ls->pe = p + n;
} }
setsbufP(&ls->sb, p + n); ls->sb.w = p + n;
buf = ls->rfunc(ls->L, ls->rdata, &sz); /* Get more data from reader. */ buf = ls->rfunc(ls->L, ls->rdata, &sz); /* Get more data from reader. */
if (buf == NULL || sz == 0) { /* EOF? */ if (buf == NULL || sz == 0) { /* EOF? */
if (need) bcread_error(ls, LJ_ERR_BCBAD); if (need) bcread_error(ls, LJ_ERR_BCBAD);
@@ -77,8 +77,8 @@ static LJ_NOINLINE void bcread_fill(LexState *ls, MSize len, int need)
if (n) { /* Append to buffer. */ if (n) { /* Append to buffer. */
n += (MSize)sz; n += (MSize)sz;
p = lj_buf_need(&ls->sb, n < len ? len : n); p = lj_buf_need(&ls->sb, n < len ? len : n);
memcpy(sbufP(&ls->sb), buf, sz); memcpy(ls->sb.w, buf, sz);
setsbufP(&ls->sb, p + n); ls->sb.w = p + n;
ls->p = p; ls->p = p;
ls->pe = p + n; ls->pe = p + n;
} else { /* Return buffer provided by reader. */ } else { /* Return buffer provided by reader. */
@@ -399,11 +399,7 @@ static int bcread_header(LexState *ls)
if ((flags & BCDUMP_F_FFI)) { if ((flags & BCDUMP_F_FFI)) {
#if LJ_HASFFI #if LJ_HASFFI
lua_State *L = ls->L; lua_State *L = ls->L;
if (!ctype_ctsG(G(L))) { ctype_loadffi(L);
ptrdiff_t oldtop = savestack(L, L->top);
luaopen_ffi(L); /* Load FFI library on-demand. */
L->top = restorestack(L, oldtop);
}
#else #else
return 0; return 0;
#endif #endif
+12 -12
View File
@@ -1,6 +1,6 @@
/* /*
** Bytecode writer. ** Bytecode writer.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lj_bcwrite_c #define lj_bcwrite_c
@@ -62,7 +62,7 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
if (num == (lua_Number)k) { /* -0 is never a constant. */ if (num == (lua_Number)k) { /* -0 is never a constant. */
*p++ = BCDUMP_KTAB_INT; *p++ = BCDUMP_KTAB_INT;
p = lj_strfmt_wuleb128(p, k); p = lj_strfmt_wuleb128(p, k);
setsbufP(&ctx->sb, p); ctx->sb.w = p;
return; return;
} }
} }
@@ -73,7 +73,7 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow)
lj_assertBCW(tvispri(o), "unhandled type %d", itype(o)); lj_assertBCW(tvispri(o), "unhandled type %d", itype(o));
*p++ = BCDUMP_KTAB_NIL+~itype(o); *p++ = BCDUMP_KTAB_NIL+~itype(o);
} }
setsbufP(&ctx->sb, p); ctx->sb.w = p;
} }
/* Write a template table. */ /* Write a template table. */
@@ -97,7 +97,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t)
/* Write number of array slots and hash slots. */ /* Write number of array slots and hash slots. */
p = lj_strfmt_wuleb128(p, narray); p = lj_strfmt_wuleb128(p, narray);
p = lj_strfmt_wuleb128(p, nhash); p = lj_strfmt_wuleb128(p, nhash);
setsbufP(&ctx->sb, p); ctx->sb.w = p;
if (narray) { /* Write array entries (may contain nil). */ if (narray) { /* Write array entries (may contain nil). */
MSize i; MSize i;
TValue *o = tvref(t->array); TValue *o = tvref(t->array);
@@ -172,7 +172,7 @@ static void bcwrite_kgc(BCWriteCtx *ctx, GCproto *pt)
} }
#endif #endif
} }
setsbufP(&ctx->sb, p); ctx->sb.w = p;
} }
} }
@@ -206,7 +206,7 @@ static void bcwrite_knum(BCWriteCtx *ctx, GCproto *pt)
p = lj_strfmt_wuleb128(p, o->u32.hi); p = lj_strfmt_wuleb128(p, o->u32.hi);
} }
} }
setsbufP(&ctx->sb, p); ctx->sb.w = p;
} }
/* Write bytecode instructions. */ /* Write bytecode instructions. */
@@ -281,7 +281,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
/* Write bytecode instructions and upvalue refs. */ /* Write bytecode instructions and upvalue refs. */
p = bcwrite_bytecode(ctx, p, pt); p = bcwrite_bytecode(ctx, p, pt);
p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2); p = lj_buf_wmem(p, proto_uv(pt), pt->sizeuv*2);
setsbufP(&ctx->sb, p); ctx->sb.w = p;
/* Write constants. */ /* Write constants. */
bcwrite_kgc(ctx, pt); bcwrite_kgc(ctx, pt);
@@ -291,16 +291,16 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
if (sizedbg) { if (sizedbg) {
p = lj_buf_more(&ctx->sb, sizedbg); p = lj_buf_more(&ctx->sb, sizedbg);
p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg); p = lj_buf_wmem(p, proto_lineinfo(pt), sizedbg);
setsbufP(&ctx->sb, p); ctx->sb.w = p;
} }
/* Pass buffer to writer function. */ /* Pass buffer to writer function. */
if (ctx->status == 0) { if (ctx->status == 0) {
MSize n = sbuflen(&ctx->sb) - 5; MSize n = sbuflen(&ctx->sb) - 5;
MSize nn = (lj_fls(n)+8)*9 >> 6; MSize nn = (lj_fls(n)+8)*9 >> 6;
char *q = sbufB(&ctx->sb) + (5 - nn); char *q = ctx->sb.b + (5 - nn);
p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */ p = lj_strfmt_wuleb128(q, n); /* Fill in final size. */
lj_assertBCW(p == sbufB(&ctx->sb) + 5, "bad ULEB128 write"); lj_assertBCW(p == ctx->sb.b + 5, "bad ULEB128 write");
ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata); ctx->status = ctx->wfunc(sbufL(&ctx->sb), q, nn+n, ctx->wdata);
} }
} }
@@ -324,8 +324,8 @@ static void bcwrite_header(BCWriteCtx *ctx)
p = lj_strfmt_wuleb128(p, len); p = lj_strfmt_wuleb128(p, len);
p = lj_buf_wmem(p, name, len); p = lj_buf_wmem(p, name, len);
} }
ctx->status = ctx->wfunc(sbufL(&ctx->sb), sbufB(&ctx->sb), ctx->status = ctx->wfunc(sbufL(&ctx->sb), ctx->sb.b,
(MSize)(p - sbufB(&ctx->sb)), ctx->wdata); (MSize)(p - ctx->sb.b), ctx->wdata);
} }
/* Write footer of bytecode dump. */ /* Write footer of bytecode dump. */
+133 -60
View File
@@ -1,6 +1,6 @@
/* /*
** Buffer handling. ** Buffer handling.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#define lj_buf_c #define lj_buf_c
@@ -20,12 +20,32 @@ static void buf_grow(SBuf *sb, MSize sz)
{ {
MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz; MSize osz = sbufsz(sb), len = sbuflen(sb), nsz = osz;
char *b; char *b;
GCSize flag;
if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF; if (nsz < LJ_MIN_SBUF) nsz = LJ_MIN_SBUF;
while (nsz < sz) nsz += nsz; while (nsz < sz) nsz += nsz;
b = (char *)lj_mem_realloc(sbufL(sb), sbufB(sb), osz, nsz); flag = sbufflag(sb);
setmref(sb->b, b); if ((flag & SBUF_FLAG_COW)) { /* Copy-on-write semantics. */
setmref(sb->p, b + len); lj_assertG_(G(sbufL(sb)), sb->w == sb->e, "bad SBuf COW");
setmref(sb->e, b + nsz); b = (char *)lj_mem_new(sbufL(sb), nsz);
setsbufflag(sb, flag & ~(GCSize)SBUF_FLAG_COW);
setgcrefnull(sbufX(sb)->cowref);
memcpy(b, sb->b, osz);
} else {
b = (char *)lj_mem_realloc(sbufL(sb), sb->b, osz, nsz);
}
if ((flag & SBUF_FLAG_EXT)) {
sbufX(sb)->r = sbufX(sb)->r - sb->b + b; /* Adjust read pointer, too. */
}
/* Adjust buffer pointers. */
sb->b = b;
sb->w = b + len;
sb->e = b + nsz;
if ((flag & SBUF_FLAG_BORROW)) { /* Adjust borrowed buffer pointers. */
SBuf *bsb = mref(sbufX(sb)->bsb, SBuf);
bsb->b = b;
bsb->w = b + len;
bsb->e = b + nsz;
}
} }
LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz) LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
@@ -34,30 +54,51 @@ LJ_NOINLINE char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz)
if (LJ_UNLIKELY(sz > LJ_MAX_BUF)) if (LJ_UNLIKELY(sz > LJ_MAX_BUF))
lj_err_mem(sbufL(sb)); lj_err_mem(sbufL(sb));
buf_grow(sb, sz); buf_grow(sb, sz);
return sbufB(sb); return sb->b;
} }
LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz) LJ_NOINLINE char *LJ_FASTCALL lj_buf_more2(SBuf *sb, MSize sz)
{ {
MSize len = sbuflen(sb); if (sbufisext(sb)) {
lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow"); SBufExt *sbx = (SBufExt *)sb;
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF)) MSize len = sbufxlen(sbx);
lj_err_mem(sbufL(sb)); if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
buf_grow(sb, len + sz); lj_err_mem(sbufL(sbx));
return sbufP(sb); if (len + sz > sbufsz(sbx)) { /* Must grow. */
buf_grow((SBuf *)sbx, len + sz);
} else if (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;
}
if (sbx->r != sbx->b) { /* Compact by moving down. */
memmove(sbx->b, sbx->r, len);
sbx->r = sbx->b;
sbx->w = sbx->b + len;
lj_assertG_(G(sbufL(sbx)), len + sz <= sbufsz(sbx), "bad SBuf compact");
}
} else {
MSize len = sbuflen(sb);
lj_assertG_(G(sbufL(sb)), sz > sbufleft(sb), "SBuf overflow");
if (LJ_UNLIKELY(sz > LJ_MAX_BUF || len + sz > LJ_MAX_BUF))
lj_err_mem(sbufL(sb));
buf_grow(sb, len + sz);
}
return sb->w;
} }
void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb) void LJ_FASTCALL lj_buf_shrink(lua_State *L, SBuf *sb)
{ {
char *b = sbufB(sb); char *b = sb->b;
MSize osz = (MSize)(sbufE(sb) - b); MSize osz = (MSize)(sb->e - b);
if (osz > 2*LJ_MIN_SBUF) { if (osz > 2*LJ_MIN_SBUF) {
MSize n = (MSize)(sbufP(sb) - b); MSize n = (MSize)(sb->w - b);
b = lj_mem_realloc(L, b, osz, (osz >> 1)); b = lj_mem_realloc(L, b, osz, (osz >> 1));
setmref(sb->b, b); sb->b = b;
setmref(sb->p, b + n); sb->w = b + n;
setmref(sb->e, b + (osz >> 1)); sb->e = b + (osz >> 1);
} }
lj_assertG_(G(sbufL(sb)), !sbufisext(sb), "YAGNI shrink SBufExt");
} }
char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz) char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
@@ -67,30 +108,62 @@ char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz)
return lj_buf_need(sb, sz); return lj_buf_need(sb, sz);
} }
#if LJ_HASBUFFER && LJ_HASJIT
void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *ref)
{
lua_State *L = sbufL(sbx);
lj_bufx_free(L, sbx);
lj_bufx_set_cow(L, sbx, p, len);
setgcref(sbx->cowref, ref);
lj_gc_objbarrier(L, (GCudata *)sbx - 1, ref);
}
#if LJ_HASFFI
MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz)
{
lj_buf_more((SBuf *)sbx, sz);
return sbufleft(sbx);
}
#endif
#endif
/* -- Low-level buffer put operations ------------------------------------- */ /* -- Low-level buffer put operations ------------------------------------- */
SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len) SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len)
{ {
char *p = lj_buf_more(sb, len); char *w = lj_buf_more(sb, len);
p = lj_buf_wmem(p, q, len); w = lj_buf_wmem(w, q, len);
setsbufP(sb, p); sb->w = w;
return sb;
}
#if LJ_HASJIT || LJ_HASFFI
static LJ_NOINLINE SBuf * LJ_FASTCALL lj_buf_putchar2(SBuf *sb, int c)
{
char *w = lj_buf_more2(sb, 1);
*w++ = (char)c;
sb->w = w;
return sb; return sb;
} }
SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c) SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c)
{ {
char *p = lj_buf_more(sb, 1); char *w = sb->w;
*p++ = (char)c; if (LJ_LIKELY(w < sb->e)) {
setsbufP(sb, p); *w++ = (char)c;
return sb; sb->w = w;
return sb;
}
return lj_buf_putchar2(sb, c);
} }
#endif
SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s) SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s)
{ {
MSize len = s->len; MSize len = s->len;
char *p = lj_buf_more(sb, len); char *w = lj_buf_more(sb, len);
p = lj_buf_wmem(p, strdata(s), len); w = lj_buf_wmem(w, strdata(s), len);
setsbufP(sb, p); sb->w = w;
return sb; return sb;
} }
@@ -99,47 +172,47 @@ SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s)
SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s) SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s)
{ {
MSize len = s->len; MSize len = s->len;
char *p = lj_buf_more(sb, len), *e = p+len; char *w = lj_buf_more(sb, len), *e = w+len;
const char *q = strdata(s)+len-1; const char *q = strdata(s)+len-1;
while (p < e) while (w < e)
*p++ = *q--; *w++ = *q--;
setsbufP(sb, p); sb->w = w;
return sb; return sb;
} }
SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s) SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s)
{ {
MSize len = s->len; MSize len = s->len;
char *p = lj_buf_more(sb, len), *e = p+len; char *w = lj_buf_more(sb, len), *e = w+len;
const char *q = strdata(s); const char *q = strdata(s);
for (; p < e; p++, q++) { for (; w < e; w++, q++) {
uint32_t c = *(unsigned char *)q; uint32_t c = *(unsigned char *)q;
#if LJ_TARGET_PPC #if LJ_TARGET_PPC
*p = c + ((c >= 'A' && c <= 'Z') << 5); *w = c + ((c >= 'A' && c <= 'Z') << 5);
#else #else
if (c >= 'A' && c <= 'Z') c += 0x20; if (c >= 'A' && c <= 'Z') c += 0x20;
*p = c; *w = c;
#endif #endif
} }
setsbufP(sb, p); sb->w = w;
return sb; return sb;
} }
SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s) SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s)
{ {
MSize len = s->len; MSize len = s->len;
char *p = lj_buf_more(sb, len), *e = p+len; char *w = lj_buf_more(sb, len), *e = w+len;
const char *q = strdata(s); const char *q = strdata(s);
for (; p < e; p++, q++) { for (; w < e; w++, q++) {
uint32_t c = *(unsigned char *)q; uint32_t c = *(unsigned char *)q;
#if LJ_TARGET_PPC #if LJ_TARGET_PPC
*p = c - ((c >= 'a' && c <= 'z') << 5); *w = c - ((c >= 'a' && c <= 'z') << 5);
#else #else
if (c >= 'a' && c <= 'z') c -= 0x20; if (c >= 'a' && c <= 'z') c -= 0x20;
*p = c; *w = c;
#endif #endif
} }
setsbufP(sb, p); sb->w = w;
return sb; return sb;
} }
@@ -148,21 +221,21 @@ SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep)
MSize len = s->len; MSize len = s->len;
if (rep > 0 && len) { if (rep > 0 && len) {
uint64_t tlen = (uint64_t)rep * len; uint64_t tlen = (uint64_t)rep * len;
char *p; char *w;
if (LJ_UNLIKELY(tlen > LJ_MAX_STR)) if (LJ_UNLIKELY(tlen > LJ_MAX_STR))
lj_err_mem(sbufL(sb)); lj_err_mem(sbufL(sb));
p = lj_buf_more(sb, (MSize)tlen); w = lj_buf_more(sb, (MSize)tlen);
if (len == 1) { /* Optimize a common case. */ if (len == 1) { /* Optimize a common case. */
uint32_t c = strdata(s)[0]; uint32_t c = strdata(s)[0];
do { *p++ = c; } while (--rep > 0); do { *w++ = c; } while (--rep > 0);
} else { } else {
const char *e = strdata(s) + len; const char *e = strdata(s) + len;
do { do {
const char *q = strdata(s); const char *q = strdata(s);
do { *p++ = *q++; } while (q < e); do { *w++ = *q++; } while (q < e);
} while (--rep > 0); } while (--rep > 0);
} }
setsbufP(sb, p); sb->w = w;
} }
return sb; return sb;
} }
@@ -173,27 +246,27 @@ SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e)
if (i <= e) { if (i <= e) {
for (;;) { for (;;) {
cTValue *o = lj_tab_getint(t, i); cTValue *o = lj_tab_getint(t, i);
char *p; char *w;
if (!o) { if (!o) {
badtype: /* Error: bad element type. */ badtype: /* Error: bad element type. */
setsbufP(sb, (void *)(intptr_t)i); /* Store failing index. */ sb->w = (char *)(intptr_t)i; /* Store failing index. */
return NULL; return NULL;
} else if (tvisstr(o)) { } else if (tvisstr(o)) {
MSize len = strV(o)->len; MSize len = strV(o)->len;
p = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len); w = lj_buf_wmem(lj_buf_more(sb, len + seplen), strVdata(o), len);
} else if (tvisint(o)) { } else if (tvisint(o)) {
p = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o)); w = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o));
} else if (tvisnum(o)) { } else if (tvisnum(o)) {
p = lj_buf_more(lj_strfmt_putfnum(sb, STRFMT_G14, numV(o)), seplen); w = lj_buf_more(lj_strfmt_putfnum(sb, STRFMT_G14, numV(o)), seplen);
} else { } else {
goto badtype; goto badtype;
} }
if (i++ == e) { if (i++ == e) {
setsbufP(sb, p); sb->w = w;
break; break;
} }
if (seplen) p = lj_buf_wmem(p, strdata(sep), seplen); if (seplen) w = lj_buf_wmem(w, strdata(sep), seplen);
setsbufP(sb, p); sb->w = w;
} }
} }
return sb; return sb;
@@ -203,7 +276,7 @@ SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e)
GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb) GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb)
{ {
return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb)); return lj_str_new(sbufL(sb), sb->b, sbuflen(sb));
} }
/* Concatenate two strings. */ /* Concatenate two strings. */
@@ -219,14 +292,14 @@ GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2)
/* Read ULEB128 from buffer. */ /* Read ULEB128 from buffer. */
uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp) uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp)
{ {
const uint8_t *p = (const uint8_t *)*pp; const uint8_t *w = (const uint8_t *)*pp;
uint32_t v = *p++; uint32_t v = *w++;
if (LJ_UNLIKELY(v >= 0x80)) { if (LJ_UNLIKELY(v >= 0x80)) {
int sh = 0; int sh = 0;
v &= 0x7f; v &= 0x7f;
do { v |= ((*p & 0x7f) << (sh += 7)); } while (*p++ >= 0x80); do { v |= ((*w & 0x7f) << (sh += 7)); } while (*w++ >= 0x80);
} }
*pp = (const char *)p; *pp = (const char *)w;
return v; return v;
} }
+115 -20
View File
@@ -1,6 +1,6 @@
/* /*
** Buffer handling. ** Buffer handling.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#ifndef _LJ_BUF_H #ifndef _LJ_BUF_H
@@ -10,16 +10,60 @@
#include "lj_gc.h" #include "lj_gc.h"
#include "lj_str.h" #include "lj_str.h"
/* Resizable string buffers. Struct definition in lj_obj.h. */ /* Resizable string buffers. */
#define sbufB(sb) (mref((sb)->b, char))
#define sbufP(sb) (mref((sb)->p, char)) /* The SBuf struct definition is in lj_obj.h:
#define sbufE(sb) (mref((sb)->e, char)) ** char *w; Write pointer.
#define sbufL(sb) (mref((sb)->L, lua_State)) ** char *e; End pointer.
#define sbufsz(sb) ((MSize)(sbufE((sb)) - sbufB((sb)))) ** char *b; Base pointer.
#define sbuflen(sb) ((MSize)(sbufP((sb)) - sbufB((sb)))) ** MRef L; lua_State, used for buffer resizing. Extension bits in 3 LSB.
#define sbufleft(sb) ((MSize)(sbufE((sb)) - sbufP((sb)))) */
#define setsbufP(sb, q) (setmref((sb)->p, (q)))
#define setsbufL(sb, l) (setmref((sb)->L, (l))) /* Extended string buffer. */
typedef struct SBufExt {
SBufHeader;
union {
GCRef cowref; /* Copy-on-write object reference. */
MRef bsb; /* Borrowed string buffer. */
};
char *r; /* Read pointer. */
GCRef dict_str; /* Serialization string dictionary table. */
GCRef dict_mt; /* Serialization metatable dictionary table. */
int depth; /* Remaining recursion depth. */
} SBufExt;
#define sbufsz(sb) ((MSize)((sb)->e - (sb)->b))
#define sbuflen(sb) ((MSize)((sb)->w - (sb)->b))
#define sbufleft(sb) ((MSize)((sb)->e - (sb)->w))
#define sbufxlen(sbx) ((MSize)((sbx)->w - (sbx)->r))
#define sbufxslack(sbx) ((MSize)((sbx)->r - (sbx)->b))
#define SBUF_MASK_FLAG (7)
#define SBUF_MASK_L (~(GCSize)SBUF_MASK_FLAG)
#define SBUF_FLAG_EXT 1 /* Extended string buffer. */
#define SBUF_FLAG_COW 2 /* Copy-on-write buffer. */
#define SBUF_FLAG_BORROW 4 /* Borrowed string buffer. */
#define sbufL(sb) \
((lua_State *)(void *)(uintptr_t)(mrefu((sb)->L) & SBUF_MASK_L))
#define setsbufL(sb, l) (setmref((sb)->L, (l)))
#define setsbufXL(sb, l, flag) \
(setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) + (flag)))
#define setsbufXL_(sb, l) \
(setmrefu((sb)->L, (GCSize)(uintptr_t)(void *)(l) | (mrefu((sb)->L) & SBUF_MASK_FLAG)))
#define sbufflag(sb) (mrefu((sb)->L))
#define sbufisext(sb) (sbufflag((sb)) & SBUF_FLAG_EXT)
#define sbufiscow(sb) (sbufflag((sb)) & SBUF_FLAG_COW)
#define sbufisborrow(sb) (sbufflag((sb)) & SBUF_FLAG_BORROW)
#define sbufiscoworborrow(sb) (sbufflag((sb)) & (SBUF_FLAG_COW|SBUF_FLAG_BORROW))
#define sbufX(sb) \
(lj_assertG_(G(sbufL(sb)), sbufisext(sb), "not an SBufExt"), (SBufExt *)(sb))
#define setsbufflag(sb, flag) (setmrefu((sb)->L, (flag)))
#define tvisbuf(o) \
(LJ_HASBUFFER && tvisudata(o) && udataV(o)->udtype == UDTYPE_BUFFER)
#define bufV(o) check_exp(tvisbuf(o), ((SBufExt *)uddata(udataV(o))))
/* Buffer management */ /* Buffer management */
LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz); LJ_FUNC char *LJ_FASTCALL lj_buf_need2(SBuf *sb, MSize sz);
@@ -30,12 +74,12 @@ LJ_FUNC char * LJ_FASTCALL lj_buf_tmp(lua_State *L, MSize sz);
static LJ_AINLINE void lj_buf_init(lua_State *L, SBuf *sb) static LJ_AINLINE void lj_buf_init(lua_State *L, SBuf *sb)
{ {
setsbufL(sb, L); setsbufL(sb, L);
setmref(sb->p, NULL); setmref(sb->e, NULL); setmref(sb->b, NULL); sb->w = sb->e = sb->b = NULL;
} }
static LJ_AINLINE void lj_buf_reset(SBuf *sb) static LJ_AINLINE void lj_buf_reset(SBuf *sb)
{ {
setmrefr(sb->p, sb->b); sb->w = sb->b;
} }
static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L) static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L)
@@ -48,26 +92,77 @@ static LJ_AINLINE SBuf *lj_buf_tmp_(lua_State *L)
static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb) static LJ_AINLINE void lj_buf_free(global_State *g, SBuf *sb)
{ {
lj_mem_free(g, sbufB(sb), sbufsz(sb)); lj_assertG(!sbufisext(sb), "bad free of SBufExt");
lj_mem_free(g, sb->b, sbufsz(sb));
} }
static LJ_AINLINE char *lj_buf_need(SBuf *sb, MSize sz) static LJ_AINLINE char *lj_buf_need(SBuf *sb, MSize sz)
{ {
if (LJ_UNLIKELY(sz > sbufsz(sb))) if (LJ_UNLIKELY(sz > sbufsz(sb)))
return lj_buf_need2(sb, sz); return lj_buf_need2(sb, sz);
return sbufB(sb); return sb->b;
} }
static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz) static LJ_AINLINE char *lj_buf_more(SBuf *sb, MSize sz)
{ {
if (LJ_UNLIKELY(sz > sbufleft(sb))) if (LJ_UNLIKELY(sz > sbufleft(sb)))
return lj_buf_more2(sb, sz); return lj_buf_more2(sb, sz);
return sbufP(sb); return sb->w;
} }
/* Extended buffer management */
static LJ_AINLINE void lj_bufx_init(lua_State *L, SBufExt *sbx)
{
memset(sbx, 0, sizeof(SBufExt));
setsbufXL(sbx, L, SBUF_FLAG_EXT);
}
static LJ_AINLINE void lj_bufx_set_borrow(lua_State *L, SBufExt *sbx, SBuf *sb)
{
setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_BORROW);
setmref(sbx->bsb, sb);
sbx->r = sbx->w = sbx->b = sb->b;
sbx->e = sb->e;
}
static LJ_AINLINE void lj_bufx_set_cow(lua_State *L, SBufExt *sbx,
const char *p, MSize len)
{
setsbufXL(sbx, L, SBUF_FLAG_EXT | SBUF_FLAG_COW);
sbx->r = sbx->b = (char *)p;
sbx->w = sbx->e = (char *)p + len;
}
static LJ_AINLINE void lj_bufx_reset(SBufExt *sbx)
{
if (sbufiscow(sbx)) {
setmrefu(sbx->L, (mrefu(sbx->L) & ~(GCSize)SBUF_FLAG_COW));
setgcrefnull(sbx->cowref);
sbx->b = sbx->e = NULL;
}
sbx->r = sbx->w = sbx->b;
}
static LJ_AINLINE void lj_bufx_free(lua_State *L, SBufExt *sbx)
{
if (!sbufiscoworborrow(sbx)) lj_mem_free(G(L), sbx->b, sbufsz(sbx));
setsbufXL(sbx, L, SBUF_FLAG_EXT);
setgcrefnull(sbx->cowref);
sbx->r = sbx->w = sbx->b = sbx->e = NULL;
}
#if LJ_HASBUFFER && LJ_HASJIT
LJ_FUNC void lj_bufx_set(SBufExt *sbx, const char *p, MSize len, GCobj *o);
#if LJ_HASFFI
LJ_FUNC MSize LJ_FASTCALL lj_bufx_more(SBufExt *sbx, MSize sz);
#endif
#endif
/* Low-level buffer put operations */ /* Low-level buffer put operations */
LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len); LJ_FUNC SBuf *lj_buf_putmem(SBuf *sb, const void *q, MSize len);
#if LJ_HASJIT || LJ_HASFFI
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c); LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putchar(SBuf *sb, int c);
#endif
LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s); LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putstr(SBuf *sb, GCstr *s);
static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len) static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len)
@@ -77,9 +172,9 @@ static LJ_AINLINE char *lj_buf_wmem(char *p, const void *q, MSize len)
static LJ_AINLINE void lj_buf_putb(SBuf *sb, int c) static LJ_AINLINE void lj_buf_putb(SBuf *sb, int c)
{ {
char *p = lj_buf_more(sb, 1); char *w = lj_buf_more(sb, 1);
*p++ = (char)c; *w++ = (char)c;
setsbufP(sb, p); sb->w = w;
} }
/* High-level buffer put operations */ /* High-level buffer put operations */
@@ -97,7 +192,7 @@ LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp);
static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb) static LJ_AINLINE GCstr *lj_buf_str(lua_State *L, SBuf *sb)
{ {
return lj_str_new(L, sbufB(sb), sbuflen(sb)); return lj_str_new(L, sb->b, sbuflen(sb));
} }
#endif #endif
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** C data arithmetic. ** C data arithmetic.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#include "lj_obj.h" #include "lj_obj.h"
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
** C data arithmetic. ** C data arithmetic.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#ifndef _LJ_CARITH_H #ifndef _LJ_CARITH_H
+5 -5
View File
@@ -1,6 +1,6 @@
/* /*
** FFI C call handling. ** FFI C call handling.
** Copyright (C) 2005-2020 Mike Pall. See Copyright Notice in luajit.h ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
*/ */
#include "lj_obj.h" #include "lj_obj.h"
@@ -334,7 +334,7 @@
isfp = sz == 2*sizeof(float) ? 2 : 1; isfp = sz == 2*sizeof(float) ? 2 : 1;
#define CCALL_HANDLE_REGARG \ #define CCALL_HANDLE_REGARG \
if (LJ_TARGET_IOS && isva) { \ if (LJ_TARGET_OSX && isva) { \
/* IOS: All variadic arguments are on the stack. */ \ /* IOS: All variadic arguments are on the stack. */ \
} else if (isfp) { /* Try to pass argument in FPRs. */ \ } else if (isfp) { /* Try to pass argument in FPRs. */ \
int n2 = ctype_isvector(d->info) ? 1 : \ int n2 = ctype_isvector(d->info) ? 1 : \
@@ -345,10 +345,10 @@
goto done; \ goto done; \
} else { \ } else { \
nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \ nfpr = CCALL_NARG_FPR; /* Prevent reordering. */ \
if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \ if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \
} \ } \
} else { /* Try to pass argument in GPRs. */ \ } else { /* Try to pass argument in GPRs. */ \
if (!LJ_TARGET_IOS && (d->info & CTF_ALIGN) > CTALIGN_PTR) \ if (!LJ_TARGET_OSX && (d->info & CTF_ALIGN) > CTALIGN_PTR) \
ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \ ngpr = (ngpr + 1u) & ~1u; /* Align to regpair. */ \
if (ngpr + n <= maxgpr) { \ if (ngpr + n <= maxgpr) { \
dp = &cc->gpr[ngpr]; \ dp = &cc->gpr[ngpr]; \
@@ -356,7 +356,7 @@
goto done; \ goto done; \
} else { \ } else { \
ngpr = maxgpr; /* Prevent reordering. */ \ ngpr = maxgpr; /* Prevent reordering. */ \
if (LJ_TARGET_IOS && d->size < 8) goto err_nyi; \ if (LJ_TARGET_OSX && d->size < 8) goto err_nyi; \
} \ } \
} }

Some files were not shown because too many files have changed in this diff Show More