From: Mike Pall Date: Thu, 23 Jun 2022 07:10:43 +0000 (+0200) Subject: Merge branch 'master' into v2.1 X-Git-Tag: v2.1.ROLLING~61 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c2441c16ce3c4e312aaefecc6d40c4fe21de97c;p=thirdparty%2FLuaJIT.git Merge branch 'master' into v2.1 --- 4c2441c16ce3c4e312aaefecc6d40c4fe21de97c diff --cc doc/ext_buffer.html index 7b874f57,00000000..192110a7 mode 100644,000000..100644 --- a/doc/ext_buffer.html +++ b/doc/ext_buffer.html @@@ -1,697 -1,0 +1,697 @@@ + + + +String Buffer Library + + + + + + + + +
+Lua +
+ + +
+

+The string buffer library allows high-performance manipulation of +string-like data. +

+

+Unlike Lua strings, which are constants, string buffers are +mutable sequences of 8-bit (binary-transparent) characters. Data +can be stored, formatted and encoded into a string buffer and later +converted, extracted or decoded. +

+

+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. +

+

- The string buffer libary also includes a high-performance ++The string buffer library also includes a high-performance +serializer for Lua objects. +

+ +

Work in Progress

+

+This library is a work in progress. More +functionality will be added soon. +

+ +

Using the String Buffer Library

+

+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: +

+
 +local buffer = require("string.buffer")
 +
+

+The convention for the syntax shown on this page is that buffer +refers to the buffer library and buf refers to an individual +buffer object. +

+

+Please note the difference between a Lua function call, e.g. +buffer.new() (with a dot) and a Lua method call, e.g. +buf:reset() (with a colon). +

+ +

Buffer Objects

+

+A buffer object is a garbage-collected Lua object. After creation with +buffer.new(), 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. +

+

+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. +

+

+The buffer space that holds the characters is managed automatically +— it grows as needed and already consumed space is recycled. Use +buffer.new(size) and buf:free(), if you need more +control. +

+

+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 — use the +FFI library to directly map memory or files up to the virtual memory +limit of your OS. +

+ +

Buffer Method Overview

+ + +

Buffer Creation and Management

+ +

local buf = buffer.new([size [,options]])
+local buf = buffer.new([options])

+

+Creates a new buffer object. +

+

+The optional size 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. +

+

+The optional table options sets various +serialization options. +

+ +

buf = buf:reset()

+

+Reset (empty) the buffer. The allocated buffer space is not freed and +may be reused. +

+ +

buf = buf:free()

+

+The buffer space of the buffer object is freed. The object itself +remains intact, empty and may be reused. +

+

+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. +

+ +

Buffer Writers

+ +

buf = buf:put([str|num|obj] [,…])

+

+Appends a string str, a number num or any object +obj with a __tostring metamethod to the buffer. +Multiple arguments are appended in the given order. +

+

+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. +

+ +

buf = buf:putf(format, …)

+

+Appends the formatted arguments to the buffer. The format +string supports the same options as string.format(). +

+ +

buf = buf:putcdata(cdata, len)FFI

+

+Appends the given len number of bytes from the memory pointed +to by the FFI cdata object to the buffer. The object needs to +be convertible to a (constant) pointer. +

+ +

buf = buf:set(str)
+buf = buf:set(cdata, len)
FFI

+

+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 +str or the FFI cdata object in the buffer. Any buffer +space originally allocated is freed. This is not an append +operation, unlike the buf:put*() methods. +

+

+After calling this method, the buffer behaves as if +buf:free():put(str) or buf:free():put(cdata, len) +had been called. However, the data is only referenced and not copied, as +long as the buffer is only consumed. +

+

+In case the buffer is written to later on, the referenced data is copied +and the object reference is removed (copy-on-write semantics). +

+

+The stored reference is an anchor for the garbage collector and keeps the +originally passed string or FFI cdata object alive. +

+ +

ptr, len = buf:reserve(size)FFI
+buf = buf:commit(used)FFI

+

+The reserve method reserves at least size bytes of +write space in the buffer. It returns an uint8_t * FFI +cdata pointer ptr that points to this space. +

+

+The available length in bytes is returned in len. This is at +least size bytes, but may be more to facilitate efficient +buffer growth. You can either make use of the additional space or ignore +len and only use size bytes. +

+

+The commit method appends the used bytes of the +previously returned write space to the buffer data. +

+

+This pair of methods allows zero-copy use of C read-style APIs: +

+
 +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 < 0 then error("read error") end
 +  buf:commit(n)
 +until false
 +
+

+The reserved write space is not initialized. At least the +used bytes must be written to before calling the +commit method. There's no need to call the commit +method, if nothing is added to the buffer (e.g. on error). +

+ +

Buffer Readers

+ +

len = #buf

+

+Returns the current length of the buffer data in bytes. +

+ +

res = str|num|buf .. str|num|buf […]

+

+The Lua concatenation operator .. also accepts buffers, just +like strings or numbers. It always returns a string and not a buffer. +

+

+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 buf:put() and buf:get(). +

+

+Mixing this with unrelated objects that have a __concat +metamethod may not work, since these probably only expect strings. +

+ +

buf = buf:skip(len)

+

+Skips (consumes) len bytes from the buffer up to the current +length of the buffer data. +

+ +

str, … = buf:get([len|nil] [,…])

+

+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 len bytes are consumed. A nil argument +consumes the remaining buffer space (this only makes sense as the last +argument). Multiple arguments consume the buffer data in the given +order. +

+

+Note: a zero length or no remaining buffer data returns an empty string +and not nil. +

+ +

str = buf:tostring()
+str = tostring(buf)

+

+Creates a string from the buffer data, but doesn't consume it. The +buffer remains unchanged. +

+

+Buffer objects also define a __tostring metamethod. This means +buffers can be passed to the global tostring() function and +many other functions that accept this in place of strings. The important +internal uses in functions like io.write() are short-circuited +to avoid the creation of an intermediate string object. +

+ +

ptr, len = buf:ref()FFI

+

+Returns an uint8_t * FFI cdata pointer ptr that +points to the buffer data. The length of the buffer data in bytes is +returned in len. +

+

+The returned pointer can be directly passed to C functions that expect a +buffer and a length. You can also do bytewise reads +(local x = ptr[i]) or writes +(ptr[i] = 0x40) of the buffer data. +

+

+In conjunction with the skip method, this allows zero-copy use +of C write-style APIs: +

+
 +repeat
 +  local ptr, len = buf:ref()
 +  if len == 0 then break end
 +  local n = C.write(fd, ptr, len)
 +  if n < 0 then error("write error") end
 +  buf:skip(n)
 +until n >= len
 +
+

+Unlike Lua strings, buffer data is not implicitly +zero-terminated. It's not safe to pass ptr to C functions that +expect zero-terminated strings. If you're not using len, then +you're doing something wrong. +

+ +

Serialization of Lua Objects

+

+The following functions and methods allow high-speed serialization +(encoding) of a Lua object into a string and decoding it back to a Lua +object. This allows convenient storage and transport of structured +data. +

+

+The encoded data is in an internal binary +format. The data can be stored in files, binary-transparent +databases or transmitted to other LuaJIT instances across threads, +processes or networks. +

+

+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. +

+

+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). +

+

+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. +

+ +

Serialization Functions and Methods

+ +

str = buffer.encode(obj)
+buf = buf:encode(obj)

+

+Serializes (encodes) the Lua object obj. The stand-alone +function returns a string str. The buffer method appends the +encoding to the buffer. +

+

+obj can be any of the supported Lua types — it doesn't +need to be a Lua table. +

+

+This function may throw an error when attempting to serialize +unsupported object types, circular references or deeply nested tables. +

+ +

obj = buffer.decode(str)
+obj = buf:decode()

+

- The stand-alone function de-serializes (decodes) the string - str, the buffer method de-serializes one object from the ++The stand-alone function deserializes (decodes) the string ++str, the buffer method deserializes one object from the +buffer. Both return a Lua object obj. +

+

+The returned object may be any of the supported Lua types — +even nil. +

+

+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. +

+

- Attempting to de-serialize an FFI type will throw an error, if the FFI ++Attempting to deserialize an FFI type will throw an error, if the FFI +library is not built-in or has not been loaded, yet. +

+ +

Serialization Options

+

+The options table passed to buffer.new() may contain +the following members (all optional): +

+ +

+dict needs to be an array of strings and metatable needs +to be an array of tables. Both starting at index 1 and without holes (no - nil inbetween). The tables are anchored in the buffer object and ++nil in between). The tables are anchored in the buffer object and +internally modified into a two-way index (don't do this yourself, just pass +a plain array). The tables must not be modified after they have been passed +to buffer.new(). +

+

+The dict and metatable 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 — older encodings can +then still be read. You may also set some indexes to false to +explicitly drop backwards-compatibility. Old encodings that use these +indexes will throw an error when decoded. +

+

+Metatables that are not found in the metatable dictionary are +ignored when encoding. Decoding returns a table with a nil +metatable. +

+

+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 +buf:set() method frees the already allocated buffer space: +

+
 +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
 +
+ +

Streaming Serialization

+

+In some contexts, it's desirable to do piecewise serialization of large +datasets, also known as streaming. +

+

+This serialization format can be safely concatenated and supports streaming. +Multiple encodings can simply be appended to a buffer and later decoded +individually: +

+
 +local buf = buffer.new()
 +buf:encode(obj1)
 +buf:encode(obj2)
 +local copy1 = buf:decode()
 +local copy2 = buf:decode()
 +
+

+Here's how to iterate over a stream: +

+
 +while #buf ~= 0 do
 +  local obj = buf:decode()
 +  -- Do something with obj.
 +end
 +
+

+Since the serialization format doesn't prepend a length to its encoding, +network applications may need to transmit the length, too. +

+ +

Serialization Format Specification

+

+This serialization format is designed for internal use by LuaJIT +applications. Serialized data is upwards-compatible and portable across +all supported LuaJIT platforms. +

+

+It's an 8-bit binary format 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. +

+

+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. +

+

+Although documented here for reference, this format is explicitly +not intended to be a 'public standard' for structured data +interchange across computer languages (like JSON or MessagePack). Please +do not use it as such. +

+

+The specification is given below as a context-free grammar with a +top-level object as the starting point. Alternatives are +separated by the | symbol and * indicates repeats. +Grouping is implicit or indicated by {…}. Terminals are +either plain hex numbers, encoded as bytes, or have a .format +suffix. +

+
 +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
 +
+ +

Error handling

+

+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. +

+

- OTOH you may want to catch some errors individually. Buffer methods need ++OTOH, you may want to catch some errors individually. Buffer methods need +to receive the buffer object as the first argument. The Lua colon-syntax +obj:method() does that implicitly. But to wrap a method with +pcall(), the arguments need to be passed like this: +

+
 +local ok, err = pcall(buf.encode, buf, obj)
 +if not ok then
 +  -- Handle error in err.
 +end
 +
+ +

FFI caveats

+

+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: +

+

+First, please remember that FFI pointers are zero-indexed. The space +returned by buf:reserve() and buf:ref() starts at the +returned pointer and ends before len bytes after that. +

+

+I.e. the first valid index is ptr[0] and the last valid index +is ptr[len-1]. If the returned length is zero, there's no valid +index at all. The returned pointer may even be NULL. +

+

+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. +

+

+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). +

+

+FFI pointers or references do not count as GC anchors for an underlying +object. E.g. an array allocated with ffi.new() is +anchored by buf:set(array, len), but not by +buf:set(array+offset, len). 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. +

+

+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 buf:set(cdata, len) 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. +

+
+
+ + + diff --cc doc/ext_profiler.html index 6059b4ea,00000000..b645a204 mode 100644,000000..100644 --- a/doc/ext_profiler.html +++ b/doc/ext_profiler.html @@@ -1,361 -1,0 +1,361 @@@ + + + +Profiler + + + + + + + +
+Lua +
+ + +
+

+LuaJIT has an integrated statistical profiler with very low overhead. It +allows sampling the currently executing stack and other parameters in +regular intervals. +

+

+The integrated profiler can be accessed from three levels: +

+ + +

High-Level Profiler

+

+The bundled high-level profiler offers basic profiling functionality. It +generates simple textual summaries or source code annotations. It can be +accessed with the -jp command line option +or from Lua code by loading the underlying jit.p module. +

+

+To cut to the chase — run this to get a CPU usage profile by +function name: +

+
 +luajit -jp myapp.lua
 +
+

+It's not a stated goal of the bundled profiler to add every +possible option or to cater for special profiling needs. The low-level +profiler APIs are documented below. They may be used by third-party +authors to implement advanced functionality, e.g. IDE integration or +graphical profilers. +

+

+Note: Sampling works for both interpreted and JIT-compiled code. The +results for JIT-compiled code may sometimes be surprising. LuaJIT +heavily optimizes and inlines Lua code — there's no simple +one-to-one correspondence between source code lines and the sampled +machine code. +

+ +

-jp=[options[,output]]

+

+The -jp command line option starts the high-level profiler. +When the application run by the command line terminates, the profiler +stops and writes the results to stdout or to the specified +output file. +

+

+The options argument specifies how the profiling is to be +performed: +

+ +

+The default output for -jp is a list of the most CPU consuming +spots in the application. Increasing the stack dump depth with (say) +-jp=2 may help to point out the main callers or callees of +hotspots. But sample aggregation is still flat per unique stack dump. +

+

+To get a two-level view (split view) of callers/callees, use +-jp=s or -jp=-s. The percentages shown for the second +level are relative to the first level. +

+

+To see how much time is spent in each line relative to a function, use +-jp=fl. +

+

+To see how much time is spent in different VM states or +zones, use -jp=v or -jp=z. +

+

+Combinations of v/z with f/F/l produce two-level +views, e.g. -jp=vf or -jp=fv. This shows the time +spent in a VM state or zone vs. hotspots. This can be used to answer - questions like "Which time consuming functions are only interpreted?" or ++questions like "Which time-consuming functions are only interpreted?" or +"What's the garbage collector overhead for a specific function?". +

+

+Multiple options can be combined — but not all combinations make +sense, see above. E.g. -jp=3si4m1 samples three stack levels +deep in 4ms intervals and shows a split view of the CPU consuming +functions and their callers with a 1% threshold. +

+

+Source code annotations produced by -jp=a or -jp=A are +always flat and at the line level. Obviously, the source code files need +to be readable by the profiler script. +

+

+The high-level profiler can also be started and stopped from Lua code with: +

+
 +require("jit.p").start(options, output)
 +...
 +require("jit.p").stop()
 +
+ +

jit.zone — Zones

+

+Zones can be used to provide information about different parts of an +application to the high-level profiler. E.g. a game could make use of an +"AI" zone, a "PHYS" zone, etc. Zones are hierarchical, +organized as a stack. +

+

+The jit.zone module needs to be loaded explicitly: +

+
 +local zone = require("jit.zone")
 +
+ +

+To show the time spent in each zone use -jp=z. To show the time +spent relative to hotspots use e.g. -jp=zf or -jp=fz. +

+ +

Low-level Lua API

+

+The jit.profile module gives access to the low-level API of the +profiler from Lua code. This module needs to be loaded explicitly: +

 +local profile = require("jit.profile")
 +
+

+This module can be used to implement your own higher-level profiler. +A typical profiling run starts the profiler, captures stack dumps in +the profiler callback, adds them to a hash table to aggregate the number - of samples, stops the profiler and then analyzes all of the captured ++of samples, stops the profiler and then analyzes all captured +stack dumps. Other parameters can be sampled in the profiler callback, +too. But it's important not to spend too much time in the callback, +since this may skew the statistics. +

+ +

profile.start(mode, cb) +— Start profiler

+

+This function starts the profiler. The mode argument is a +string holding options: +

+ +

+The cb argument is a callback function which is called with +three arguments: (thread, samples, vmstate). The callback is +called on a separate coroutine, the thread argument is the +state that holds the stack to sample for profiling. Note: do +not modify the stack of that state or call functions on it. +

+

+samples gives the number of accumulated samples since the last +callback (usually 1). +

+

+vmstate holds the VM state at the time the profiling timer +triggered. This may or may not correspond to the state of the VM when +the profiling callback is called. The state is either 'N' +native (compiled) code, 'I' interpreted code, 'C' +C code, 'G' the garbage collector, or 'J' the JIT +compiler. +

+ +

profile.stop() +— Stop profiler

+

+This function stops the profiler. +

+ +

dump = profile.dumpstack([thread,] fmt, depth) +— Dump stack

+

+This function allows taking stack dumps in an efficient manner. It +returns a string with a stack dump for the thread (coroutine), +formatted according to the fmt argument: +

+ +

+The depth argument gives the number of frames to dump, starting +at the topmost frame of the thread. A negative number dumps the frames in +inverse order. +

+

+The first example prints a list of the current module names and line +numbers of up to 10 frames in separate lines. The second example prints +semicolon-separated function names for all frames (up to 100) in inverse +order: +

+
 +print(profile.dumpstack(thread, "l\n", 10))
 +print(profile.dumpstack(thread, "lZ;", -100))
 +
+ +

Low-level C API

+

+The profiler can be controlled directly from C code, e.g. for +use by IDEs. The declarations are in "luajit.h" (see +Lua/C API extensions). +

+ +

luaJIT_profile_start(L, mode, cb, data) +— Start profiler

+

+This function starts the profiler. See +above for a description of the mode argument. +

+

+The cb argument is a callback function with the following +declaration: +

+
 +typedef void (*luaJIT_profile_callback)(void *data, lua_State *L,
 +                                        int samples, int vmstate);
 +
+

+data is available for use by the callback. L is the +state that holds the stack to sample for profiling. Note: do +not modify this stack or call functions on this stack — +use a separate coroutine for this purpose. See +above for a description of samples and vmstate. +

+ +

luaJIT_profile_stop(L) +— Stop profiler

+

+This function stops the profiler. +

+ +

p = luaJIT_profile_dumpstack(L, fmt, depth, len) +— Dump stack

+

+This function allows taking stack dumps in an efficient manner. +See above for a description of fmt +and depth. +

+

+This function returns a const char * pointing to a +private string buffer of the profiler. The int *len +argument returns the length of the output string. The buffer is +overwritten on the next call and deallocated when the profiler stops. +You either need to consume the content immediately or copy it for later +use. +

+
+
+ + + diff --cc doc/extensions.html index 6802d964,3ed13804..040fc588 --- a/doc/extensions.html +++ b/doc/extensions.html @@@ -203,36 -191,6 +203,36 @@@ for dot releases (x.y.0 → x.y.1), minor releases (2.0 → 2.1) or between any beta release. Foreign bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.

+

+Note: LJ_GC64 mode requires a different frame layout, which implies +a different, incompatible bytecode format for all 64 bit ports. This may be +rectified in the future. +

+ +

table.new(narray, nhash) allocates a pre-sized table

+

+An extra library function table.new() can be made available via +require("table.new"). This creates a pre-sized table, just like +the C API equivalent lua_createtable(). This is useful for big +tables if the final table size is known and automatic table resizing is +too expensive. +

+ +

table.clear(tab) clears a table

+

+An extra library function table.clear() can be made available +via require("table.clear"). This clears all keys and values +from a table, but preserves the allocated array/hash sizes. This is +useful when a table, which is linked from multiple places, needs to be +cleared and/or when recycling a table for use by the same context. This +avoids managing backlinks, saves an allocation and the overhead of +incremental array/hash part growth. +

+

- Please note this function is meant for very specific situations. In most ++Please note, this function is meant for very specific situations. In most +cases it's better to replace the (usually single) link with a new table +and let the GC do its work. +

Enhanced PRNG for math.random()