bytecode reference updates

gccjit-ravi534
Dibyendu Majumdar 7 years ago
parent 326ffc70dc
commit 7e00d56f6f

@ -1636,5 +1636,303 @@ Line [2] in function ``b`` sets upvalue a (upvalue number 0 in the upvalue table
OP_NEWTABLE instruction
=======================
Syntax
------
::
NEWTABLE A B C R(A) := {} (size = B,C)
Description
-----------
Creates a new empty table at register R(A). B and C are the encoded size information for the
array part and the hash part of the table, respectively. Appropriate values for B and C are set
in order to avoid rehashing when initially populating the table with array values or hash
key-value pairs.
Operand B and C are both encoded as a 'floating point byte' (so named in lobject.c)
which is ``eeeeexxx`` in binary, where x is the mantissa and e is the exponent.
The actual value is calculated as ``1xxx*2^(eeeee-1)`` if ``eeeee`` is greater than ``0``
(a range of ``8`` to ``15*2^30``). If ``eeeee`` is ``0``, the actual value is ``xxx``
(a range of ``0`` to ``7``.)
If an empty table is created, both sizes are zero. If a table is created with a number of
objects, the code generator counts the number of array elements and the number of hash elements.
Then, each size value is rounded up and encoded in B and C using the floating point byte format.
Examples
--------
Creating an empty table forces both array and hash sizes to be zero::
f=load('local q = {}')
Leads to::
main <(string):0,0> (2 instructions at 0000022C1877A220)
0+ params, 2 slots, 1 upvalue, 1 local, 0 constants, 0 functions
1 [1] NEWTABLE 0 0 0
2 [1] RETURN 0 1
constants (0) for 0000022C1877A220:
locals (1) for 0000022C1877A220:
0 q 2 3
upvalues (1) for 0000022C1877A220:
0 _ENV 1 0
More examples are provided in the description of ``OP_SETLIST`` instruction.
OP_SETLIST instruction
======================
Syntax
------
::
SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B
Description
-----------
Sets the values for a range of array elements in a table referenced by R(A). Field B is the
number of elements to set. Field C encodes the block number of the table to be initialized.
The values used to initialize the table are located in registers R(A+1), R(A+2), and so on.
The block size is denoted by FPF. FPF is 'fields per flush', defined as ``LFIELDS_PER_FLUSH``
in the source file lopcodes.h, with a value of 50. For example, for array locations 1 to 20,
C will be 1 and B will be 20.
If B is 0, the table is set with a variable number of array elements, from register R(A+1)
up to the top of the stack. This happens when the last element in the table constructor is
a function call or a vararg operator.
If C is 0, the next instruction is cast as an integer, and used as the C value. This happens
only when operand C is unable to encode the block number, i.e. when C > 511, equivalent to an
array index greater than 25550.
Examples
--------
Well start with a simple example::
f=load('local q = {1,2,3,4,5,}')
This generates::
main <(string):0,0> (8 instructions at 0000022C18756E50)
0+ params, 6 slots, 1 upvalue, 1 local, 5 constants, 0 functions
1 [1] NEWTABLE 0 5 0
2 [1] LOADK 1 -1 ; 1
3 [1] LOADK 2 -2 ; 2
4 [1] LOADK 3 -3 ; 3
5 [1] LOADK 4 -4 ; 4
6 [1] LOADK 5 -5 ; 5
7 [1] SETLIST 0 5 1 ; 1
8 [1] RETURN 0 1
constants (5) for 0000022C18756E50:
1 1
2 2
3 3
4 4
5 5
locals (1) for 0000022C18756E50:
0 q 8 9
upvalues (1) for 0000022C18756E50:
0 _ENV 1 0
A table with the reference in register 0 is created in line [1] by NEWTABLE. Since we are
creating a table with no hash elements, the array part of the table has a size of 5,
while the hash part has a size of 0.
Constants are then loaded into temporary registers 1 to 5 (lines [2] to [6]) before the SETLIST
instruction in line [7] assigns each value to consecutive table elements. The start of the
block is encoded as 1 in operand C. The starting index is calculated as (1-1)*50+1 or 1.
Since B is 5, the range of the array elements to be set becomes 1 to 5, while the objects used
to set the array elements will be R(1) through R(5).
Next is a larger table with 55 array elements. This will require two blocks to initialize.
Some lines have been removed and ellipsis (...) added to save space::
> f=load('local q = {1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0, \
>> 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0, \
>> 1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,}')
The generated code is::
main <(string):0,0> (59 instructions at 0000022C187833C0)
0+ params, 51 slots, 1 upvalue, 1 local, 10 constants, 0 functions
1 [1] NEWTABLE 0 30 0
2 [1] LOADK 1 -1 ; 1
3 [1] LOADK 2 -2 ; 2
4 [1] LOADK 3 -3 ; 3
...
51 [3] LOADK 50 -10 ; 0
52 [3] SETLIST 0 50 1 ; 1
53 [3] LOADK 1 -1 ; 1
54 [3] LOADK 2 -2 ; 2
55 [3] LOADK 3 -3 ; 3
56 [3] LOADK 4 -4 ; 4
57 [3] LOADK 5 -5 ; 5
58 [3] SETLIST 0 5 2 ; 2
59 [3] RETURN 0 1
constants (10) for 0000022C187833C0:
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 0
locals (1) for 0000022C187833C0:
0 q 59 60
upvalues (1) for 0000022C187833C0:
0 _ENV 1 0
Since FPF is 50, the array will be initialized in two blocks. The first block is
for index 1 to 50, while the second block is for index 51 to 55. Each array block to be
initialized requires one ``SETLIST`` instruction. On line [1], ``NEWTABLE`` has a field
B value of 30, or 00011110 in binary. From the description of ``NEWTABLE``, ``xxx`` is ``1102``,
while ``eeeee`` is ``112``. Thus, the size of the array portion of the table is ``(1110)*2^(11-1)``
or ``(14*2^2)`` or ``56``.
Lines [2] to [51] sets the values used to initialize the first block. On line [52],
``SETLIST`` has a B value of 50 and a C value of 1. So the block is from 1 to 50.
Source registers are from R(1) to R(50).
Lines [53] to [57] sets the values used to initialize the second block. On line [58],
``SETLIST`` has a B value of 5 and a C value of 2. So the block is from 51 to 55.
The start of the block is calculated as ``(2-1)*50+1`` or ``51``. Source registers are
from R(1) to R(5).
Here is a table with hashed elements::
> f=load('local q = {a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,}')
This results in::
main <(string):0,0> (10 instructions at 0000022C18783D20)
0+ params, 2 slots, 1 upvalue, 1 local, 16 constants, 0 functions
1 [1] NEWTABLE 0 0 8
2 [1] SETTABLE 0 -1 -2 ; "a" 1
3 [1] SETTABLE 0 -3 -4 ; "b" 2
4 [1] SETTABLE 0 -5 -6 ; "c" 3
5 [1] SETTABLE 0 -7 -8 ; "d" 4
6 [1] SETTABLE 0 -9 -10 ; "e" 5
7 [1] SETTABLE 0 -11 -12 ; "f" 6
8 [1] SETTABLE 0 -13 -14 ; "g" 7
9 [1] SETTABLE 0 -15 -16 ; "h" 8
10 [1] RETURN 0 1
constants (16) for 0000022C18783D20:
1 "a"
2 1
3 "b"
4 2
5 "c"
6 3
7 "d"
8 4
9 "e"
10 5
11 "f"
12 6
13 "g"
14 7
15 "h"
16 8
locals (1) for 0000022C18783D20:
0 q 10 11
upvalues (1) for 0000022C18783D20:
0 _ENV 1 0
In line [1], ``NEWTABLE`` is executed with an array part size of 0 and a hash part size of 8.
On lines [2] to line [9], key-value pairs are set using ``SETTABLE``. The ``SETLIST`` instruction
is only for initializing array elements. Using ``SETTABLE`` to initialize the key-value pairs of
a table in the above example is quite efficient as it can reference the constant pool directly.
If there are both array elements and hash elements in a table constructor, both ``SETTABLE``
and ``SETLIST`` will be used to initialize the table after the initial ``NEWTABLE``. In addition,
if the last element of the table constructor is a function call or a vararg operator, then the
B operand of ``SETLIST`` will be 0, to allow objects from R(A+1) up to the top of the stack
to be initialized as array elements of the table.
::
> f=load('return {1,2,3,a=1,b=2,c=3,foo()}')
Leads to::
main <(string):0,0> (12 instructions at 0000022C18788430)
0+ params, 5 slots, 1 upvalue, 0 locals, 7 constants, 0 functions
1 [1] NEWTABLE 0 3 3
2 [1] LOADK 1 -1 ; 1
3 [1] LOADK 2 -2 ; 2
4 [1] LOADK 3 -3 ; 3
5 [1] SETTABLE 0 -4 -1 ; "a" 1
6 [1] SETTABLE 0 -5 -2 ; "b" 2
7 [1] SETTABLE 0 -6 -3 ; "c" 3
8 [1] GETTABUP 4 0 -7 ; _ENV "foo"
9 [1] CALL 4 1 0
10 [1] SETLIST 0 0 1 ; 1
11 [1] RETURN 0 2
12 [1] RETURN 0 1
constants (7) for 0000022C18788430:
1 1
2 2
3 3
4 "a"
5 "b"
6 "c"
7 "foo"
locals (0) for 0000022C18788430:
upvalues (1) for 0000022C18788430:
0 _ENV 1 0
In the above example, the table is first created in line [1] with its reference
in register 0, and it has both array and hash elements to be set. The size of the
array part is 3 while the size of the hash part is also 3.
Lines [2][4] loads the values for the first 3 array elements. Lines [5][7] set
the 3 key-value pairs for the hash part of the table. In lines [8] and [9],
the call to function ``foo`` is made, and then in line [10], the ``SETLIST`` instruction sets
the first 3 array elements (in registers 1 to 3) plus whatever additional results
returned by the ``foo`` function call (from register 4 onwards). This is accomplished by
setting operand B in ``SETLIST`` to 0. For the first block, operand C is 1 as usual.
If no results are returned by the function, the top of stack is at register 3
and only the 3 constant array elements in the table are set.
Finally::
> f=load('local a; return {a(), a(), a()}')
This gives::
main <(string):0,0> (11 instructions at 0000022C18787AD0)
0+ params, 5 slots, 1 upvalue, 1 local, 0 constants, 0 functions
1 [1] LOADNIL 0 0
2 [1] NEWTABLE 1 2 0
3 [1] MOVE 2 0
4 [1] CALL 2 1 2
5 [1] MOVE 3 0
6 [1] CALL 3 1 2
7 [1] MOVE 4 0
8 [1] CALL 4 1 0
9 [1] SETLIST 1 0 1 ; 1
10 [1] RETURN 1 2
11 [1] RETURN 0 1
constants (0) for 0000022C18787AD0:
locals (1) for 0000022C18787AD0:
0 a 2 12
upvalues (1) for 0000022C18787AD0:
0 _ENV 1 0
Note that only the last function call in a table constructor retains all results.
Other function calls in the table constructor keep only one result. This is shown in the
above example. For vararg operators in table constructors, please see the discussion for the
``VARARG`` instruction for an example.

Loading…
Cancel
Save