Hlavní navigace

LuaJIT – Just in Time překladač pro programovací jazyk Lua (12 – překlad operací s reálnými čísly)

15. 1. 2015
Doba čtení: 17 minut

Sdílet

V programovacím jazyku Lua jsou základním numerickým datovým typem čísla s plovoucí řádovou čárkou s dvojitou přesností (IEEE 754) známé v dalších jazycích pod názvem double. Pokud se s tímto datovým typem ve zdrojových kódech pracuje, musí LuaJIT při překladu vygenerovat příslušné strojové instrukce.

Obsah

1. LuaJIT – Just in Time překladač pro programovací jazyk Lua (12 – překlad operací s reálnými čísly)

   1.1 Tabulka se strojovými instrukcemi použitými při překladu do strojového kódu mikroprocesorů x86_64

   1.2 Tabulka se strojovými instrukcemi použitými při překladu do strojového kódu mikroprocesorů ARM

2. První demonstrační příklad test54.lua – výpočet (konvergující) geometrické řady

   2.1 Zdrojový kód

   2.2 Detekovaná stopa hot-loop

   2.3 Překlad stopy do sekvence meziinstrukcí

3. Překlad prvního demonstračního příkladu do strojového kódu procesorů x86_64

4. Překlad prvního demonstračního příkladu do strojového kódu procesorů ARM

5. Druhý demonstrační příklad test55.lua – složitější výpočty prováděné ve smyčce while

   5.1 Zdrojový kód

   5.2 Detekovaná stopa hot-loop

   5.3 Překlad stopy do sekvence meziinstrukcí

6. Překlad druhého demonstračního příkladu do strojového kódu procesorů x86_64

7. Překlad druhého demonstračního příkladu do strojového kódu procesoru ARM

8. Odkazy na zdrojové texty demonstračních příkladů i na JITované sekvence instrukcí

9. Literatura

10. Odkazy na Internetu

1. LuaJIT – Just in Time překladač pro programovací jazyk Lua (12 – překlad operací s reálnými čísly)

V demonstračním příkladu, jehož just-in-time překlad jsme si popsali v předchozí části tohoto seriálu, byla implementována programová smyčka typu while, v níž se provádělo prosté zvyšování počitadla smyčky o jedničku a současně i zvyšování další lokální proměnné (resp. přesněji řečeno proměnné lokální v aktuálně používaném modulu). Vzhledem k tomu, že počáteční hodnota obou proměnných byla nastavena na nulu a v každé iteraci došlo ke zvýšení jejich hodnoty o jedničku (celé číslo), mohl LuaJIT v tomto případě použít pouze celočíselné operace, což je ostatně patrné i při pohledu na vygenerovanou sekvenci meziinstrukcí:

---- TRACE 1 IR
0001 >  int SLOAD  #2    T
0002 >+ int ADDOV  0001  +1
0003 >  int SLOAD  #1    T
0004 >+ int ADDOV  0003  +1
0005 >  int LT     0004  +100
0006 ------ LOOP ------------
0007 >+ int ADDOV  0002  +1
0008 >+ int ADDOV  0004  +1
0009 >  int LT     0008  +100
0010    int PHI    0002  0007
0011    int PHI    0004  0008
---- TRACE 1 stop -> loop

Povšimněte si především prefixu int uvedeného před všemi instrukcemi. Tento prefix znamená, že LuaJIT může (ale nemusí!) při vygenerování nativního kódu použít celočíselné operace. Ostatně již minule jsme mohli vidět, že zatímco na 32bitové platformě ARM se skutečně využívala pouze celočíselná aritmeticko-logická jednotka i celočíselné pracovní registry, na platformě x86_64 vybavené mj. i instrukčními sadami SSE a SSE2 se již pracovalo s registry XMM. Dnes si ukážeme formu just-in-time překladu u krátkých demonstračních programů, kde se již používají operace s reálnými čísly i na platformě ARM.

1.1 Tabulka se strojovými instrukcemi použitými při překladu do strojového kódu mikroprocesorů x86_64

V následující tabulce jsou pro úplnost vypsány všechny strojové instrukce mikroprocesorů s architekturou x86_64, s nimiž se setkáme v navazujících kapitolách. Zajímavé je, že LuaJIT si u překladu mnoha programů vystačí skutečně jen s relativně malou sadou instrukcí, takže zbylých několik set (!) instrukcí ze základní sady i z několika rozšiřujících sad (8087, 80387, MMX, SSEx…) zůstává většinou nevyužito:

# Instrukce Typ Popis
1 add aritmetická operace součet dvou skalárních hodnot
2 addsd aritmetická operace součet prvků vektorů bez saturace, operace provedena jen s pravým prvkem vektorů
3 mulsd aritmetická operace součin prvků vektorů, operace provedena jen s pravým prvkem vektorů
4 divsd aritmetická operace podíl prvků vektorů, operace provedena jen s pravým prvkem vektorů
5 cmp porovnání porovnání dvou skalárních hodnot, nastavení příznaků v EFLAGS
6 ucomisd porovnání porovnání dvou hodnot typu dobule, nastavení příznaků v EFLAGS
       
7 jmp skok nepodmíněný skok
8 ja skok podmíněný skok vykonaný při splnění: CF = 0 and ZF = 0
9 jbe skok podmíněný skok vykonaný při splnění: CF = 1 or ZF = 1 (negace předchozího)
10 jg skok podmíněný skok vykonaný při splnění: ZF = 0 and SF = OF
11 jle skok podmíněný skok vykonaný při splnění: ZF = 1 or SF != OF (negace předchozího)
12 jnb skok podmíněný skok vykonaný při splnění: CF = 0
       
13 mov přenos dat přenos skalárních hodnot
14 movsd přenos dat přenos vektorů
15 movaps přenos dat přenos (vektoru) hodnot typu single
       
16 cvtsd2si konverze konverze hodnot z typu double na int

Tabulka je rozdělena do několika sekcí. V první sekci lze najít aritmetické instrukce prováděné s celými čísly i s vektory definovanými v SSE/SSE2. Instrukce končící postfixem „sd“ pracují s hodnotami typu double. Ve druhé sekci lze nalézt nepodmíněný skok i několik podmíněných skoků, v sekci následující pak instrukce pro přenos dat mezi pamětí, celočíselnými registry a registry XMM. Poslední instrukce slouží ke konverzi dat.

1.2 Tabulka se strojovými instrukcemi použitými při překladu do strojového kódu mikroprocesorů ARM

Podobnou tabulku si uveďme i pro instrukce využívané LuaJITem při překladu do strojového kódu 32bitových mikroprocesorů s architekturou ARM, přesněji řečeno těch mikroprocesorů, které mají ve svém jádře implementovaný VFPv2 (Vector Floating Point):

# Instrukce Typ Popis
1 add aritmetická operace r0:=r1+r2, ovšem bez nastavení příznaků
2 adds aritmetická operace r0:=r1+r2 a nastav příznaky N, V, Z, C
       
3 vadd.f64 aritmetická operace součet prvků vektorů uložených ve VFP registrech
4 vmul.f64 aritmetická operace součin prvků vektorů uložených ve VFP registrech
5 vdiv.f64 aritmetická operace podíl prvků vektorů uložených ve VFP registrech
       
6 cmp porovnání operand1-operand2 (compare a nastav příznaky N, V, Z, C)
7 cmn porovnání operand1+operand2 (compare negative a nastav příznaky N, V, Z, C)
       
8 orr logická/bitová operace r0:=r1+r2
       
9 bl skok skok do subrutiny
10 ble skok podmíněný skok provedený při N!=V
11 blge skok podmíněný skok provedený při N=V
12 blgt skok podmíněný skok provedený při Z=0 and N=V
13 blhs skok podmíněný skok provedený při C=1
14 blne skok podmíněný skok provedený při nerovnosti (Z=0)
15 blt skok podmíněný skok provedený při N!=V
16 blvs skok podmíněný skok provedený při přetečení (V=1)
       
17 ldr přenos dat načtení slova do registru
18 ldrd přenos dat načtení hodnoty do registru
19 mov přenos dat načtení druhého operandu do registru
20 vldr přenos dat načtení (jedné) hodnoty do vybraného VFP registru

Opět můžeme vidět, že tabulka je rozdělena do několika sekcí. Nejprve jsou uvedeny dvě celočíselné aritmetické instrukce, dále pak tři instrukce prováděné s hodnotami uloženými ve VFP registrech. Další dvojici instrukcí již známe z minula – jedná se o porovnání dvou operandů (registrů) a nastavení příslušných příznaků N (negative), V (overflow), Z (zero) a C (carry) využívaných mj. i v podmíněných skocích vypsaných v páté sekci. V instrukcích sloužících pro přenos dat můžeme mj. vidět i instrukci vldr pro přenos do VFP registru.

Zajímavý je postfix u instrukcí vadd, vmulvdiv. Ten určuje typ dat a současně i sadu registrů, s kterými daná instrukce pracuje:

Postfix Typ dat (IEEE 754) Registry (operandy)
f32 single precision Sd, Sn, Sm
f64 double precision Dd, Dn, Dm

2. První demonstrační příklad test54.lua – výpočet (konvergující) geometrické řady

V dnešním prvním demonstračním příkladu nazvaném test54.lua se provádí výpočet geometrické řady konvergující ke dvojce. Implementace je velmi jednoduchá, protože je použita počítaná programová smyčka typu for, v níž se v tisíci iteracích sčítají jednotlivé prvky řady, přičemž každý prvek má hodnotu 2-n. Vzhledem k tomu, že se ve výpočtu používá dělení 1/x, je zřejmé, že LuaJIT nemůže použít optimalizaci spočívající v přetypování proměnných na typ integer, ale veškeré výpočty musí být prováděny s hodnotami typu double (a to navíc ideálně takovým způsobem, aby geometrická řada na všech platformách skutečně konvergovala ke dvojce :-).

2.1 Zdrojový kód

Podívejme se nejdříve na zdrojový kód tohoto příkladu:

--
-- LuaJIT: demonstracni priklad cislo 54.
--
-- Test JITu - prekladu do nativniho kodu.
--
 
 
 
local i
local geom = 0
local x = 1
 
for i = 1,1000 do
    geom = geom + 1/x
    x = x * 2
end
 
print(geom)
 
 
 
--
-- Finito.
--

2.2 Detekovaná stopa hot-loop

Trasovací just-it-time překladač LuaJIT po několika desítkách iterací (konkrétně po padesáté šesté iteraci, jak jsme se již ostatně dozvěděli v předchozích částech tohoto seriálu) nalezne následující hot-loop reprezentovanou snadno pochopitelným bajtkódem:

---- TRACE 1 start test53.lua:13
0008  DIVNV    7   2   0  ; 1
0009  ADDVV    1   1   7
0010  MULVN    2   2   1  ; 2
0011  FORL     3 => 0008

První tři instrukce (s tříadresovým kódem) tvoří tělo počítané programové smyčky. U každé instrukce jsou uvedeny tři registry: jeden registr cílový a dva registry zdrojové. Výsledek operace DIVNV je přičten k registru číslo 1 ve druhé operaci ADDVN a následně je obsah registru číslo 2 zdvojnásoben (i když by zde teoreticky bylo možné použít pouhé přičtení).

2.3 Překlad stopy do sekvence meziinstrukcí

Bajtkód je následně přetransformován do následující sekvence meziinstrukcí, kde je ke každé operaci doplněn datový typ. Prefix num značí použití čísel reprezentovaných v systému plovoucí řádové čárky (tečky):

---- TRACE 1 IR
0001    int SLOAD  #4    CI
0002 >  num SLOAD  #3    T
0003    num DIV    +1    0002
0004 >  num SLOAD  #2    T
0005  + num ADD    0004  0003
0006  + num ADD    0002  0002
0007  + int ADD    0001  +1
0008 >  int LE     0007  +1000
0009 ------ LOOP ------------
0010    num DIV    +1    0006
0011  + num ADD    0010  0005
0012  + num ADD    0006  0006
0013  + int ADD    0007  +1
0014 >  int LE     0013  +1000
0015    int PHI    0007  0013
0016    num PHI    0006  0012
0017    num PHI    0005  0011

3. Překlad prvního demonstračního příkladu do strojového kódu procesorů x86_64

Nyní se podívejme, jakým způsobem provedl LuaJIT překlad výše uvedené programové smyčky do (nativního) strojového kódu mikroprocesorů s architekturou x86_64 vybavenými navíc doplňkovou instrukční sadou SSE a SSE2:

---- TRACE 1 mcode 118
0bceff89  mov       dword [0x41f9e4a0], 0x1
0bceff94  movsd     xmm0, [0x400d9090]
0bceff9d  cvtsd2si  ebp, [rdx+0x18]
0bceffa2  cmp       dword [rdx+0x14], 0xfffeffff
0bceffa9  jnb       0x0bce0010  ->0
0bceffaf  movsd     xmm6, [rdx+0x10]
0bceffb4  movaps    xmm7, xmm0
0bceffb7  divsd     xmm7, xmm6
0bceffbb  cmp       dword [rdx+0xc], 0xfffeffff
0bceffc2  jnb       0x0bce0010     ->0
0bceffc8  addsd     xmm7, [rdx+0x8]
0bceffcd  addsd     xmm6, xmm6
0bceffd1  add       ebp, +0x01
0bceffd4  cmp       ebp, 0x3e8
0bceffda  jg        0x0bce0014     ->1
->LOOP:
0bceffe0  movaps    xmm5, xmm0
0bceffe3  divsd     xmm5, xmm6
0bceffe7  addsd     xmm7, xmm5
0bceffeb  addsd     xmm6, xmm6
0bceffef  add       ebp, +0x01
0bcefff2  cmp       ebp, 0x3e8
0bcefff8  jle       0x0bceffe0        ->LOOP
0bcefffa  jmp       0x0bce001c        ->3
---- TRACE 1 stop -> loop

Samotná programová smyčka je přeložena zajímavým způsobem – můžeme zde vidět, že prakticky všechny konstanty použité při výpočtu jsou uloženy v registrech XMMx (což je samozřejmě dobře) a taktéž použití celočíselného registru EBP ve funkci počitadla (konstanta 0×3e8 odpovídá dekadické hodnotě 1000 a tím pádem i maximálnímu počtu iterací). Zatímco vlastní výpočet je do jisté míry optimalizován – viz náhrada násobení za pouhý součet provedený v instrukci addsd xmm6, xmm6, tak řízení programové smyčky je přeloženo značně šablonovitým způsobem (zpětné počítání by bylo rychlejší, což ale platí pro sekvenci DEC+JNZ a nikoli pro LOOP).

4. Překlad prvního demonstračního příkladu do strojového kódu procesorů ARM

Zajímavé bude porovnat předchozí kód s kódem vytvořeným pro procesory s architekturou ARM:

---- TRACE 1 mcode 104
00397f98  mov      r0, #-1342177280
00397f9c  orr      r0, r0, #114294784
00397fa0  orr      r0, r0, #97280
00397fa4  vldr     d0, [r0, #424]
00397fa8  ldr      r11, [r9, #24]
00397fac  ldr      lr, [r9, #20]
00397fb0  vldr     d1, [r9, #16]
00397fb4  cmn      lr, #15
00397fb8  blhs     0x00390018  ->0
00397fbc  vdiv.f64 d3, d0, d1
00397fc0  ldr      lr, [r9, #12]
00397fc4  vldr     d2, [r9, #8]
00397fc8  cmn      lr, #15
00397fcc  blhs     0x00390018  ->0
00397fd0  vadd.f64 d15, d2, d3
00397fd4  vadd.f64 d14, d1, d1
00397fd8  add      r11, r11, #1
00397fdc  cmp      r11, #1000
00397fe0  blgt     0x0039001c  ->1
->LOOP:
00397fe4  vdiv.f64 d13, d0, d14
00397fe8  vadd.f64 d15, d13, d15
00397fec  vadd.f64 d14, d14, d14
00397ff0  add      r11, r11, #1
00397ff4  cmp      r11, #1000
00397ff8  ble      0x00397fe4  ->LOOP
00397ffc  bl       0x00390024  ->3
---- TRACE 1 stop -> loop

Vlastní programová smyčka je implementována s využitím šesti instrukcí, tj. je zde o jednu instrukci méně než u konkurenčního x86_64, a to zejména díky pěkně navržené tříadresové instrukční sadě. Opět zde můžeme vidět optimalizaci v instrukci vadd.f64 d14, d14, d14, která nahrazuje pomalé násobení rychlejším součtem. Jako počitadlo smyčky je použit registr r11, jehož hodnota je postupně zvyšována o jedničku a testována proti konstantně 1000, což je opět dosti šablonovitý překlad, protože aritmetické instrukce s postfixem „s“ dokážou nastavovat příznakové bity automaticky (takže by zde bylo možné použít operaci pro odečítání).

5. Druhý demonstrační příklad test55.lua – složitější výpočty prováděné ve smyčce while

Ve druhém demonstračním příkladu nazvaném test55.lua je použita programová smyčka typu while, což mj. znamená, že základní struktura bude odpovídat demonstračnímu příkladu uvedenému minule. V těle smyčky se zvyšuje hodnota počitadla i a navíc se ještě provádí další dva výpočty – hodnota lokální proměnné x se ztrojnásobí a hodnota proměnné y násobí konstantou pět. LuaJIT zde nebude moci použít celočíselné operace, především kvůli tomu, že se bude pracovat (po 56 iteraci) s příliš velkými čísly.

5.1 Zdrojový kód

Opět si nejprve uveďme zdrojový kód tohoto příkladu:

--
-- LuaJIT: demonstracni priklad cislo 55.
--
-- Test JITu - prekladu do nativniho kodu.
--
 
 
 
local i = 0
local x = 1
local y = 1
 
while i < 100 do
    i = i + 1
    x = x * 3
    y = y * 5
end
 
print(i)
print(x)
print(y)
 
 
 
--
-- Finito.
--

5.2 Detekovaná stopa hot-loop

Programová smyčka – hot-loop – detekovaná LuaJITem je zde poněkud delší a kupodivu i sekvence instrukcí v nalezené trase je „rozsekaná“:

---- TRACE 1 start test53.lua:13
0008  ADDVN    0   0   0  ; 1
0009  MULVN    1   1   1  ; 3
0010  MULVN    2   2   2  ; 5
0011  JMP      3 => 0004
0004  KSHORT   3 100
0005  ISGE     0   3
0006  JMP      3 => 0012
0007  LOOP     3 => 0012

5.3 Překlad stopy do sekvence meziinstrukcí

Pro úplnost se podívejme na mezikód, tj. na sekvenci meziinstrukcí vygenerovaných z výše vypsaného bajtkódu:

---- TRACE 1 IR
0001 >  num SLOAD  #1    T
0002  + num ADD    0001  +1
0003 >  num SLOAD  #2    T
0004  + num MUL    0003  +3
0005 >  num SLOAD  #3    T
0006  + num MUL    0005  +5
0007 >  num LT     0002  +100
0008 ------ LOOP ------------
0009  + num ADD    0002  +1
0010  + num MUL    0004  +3
0011  + num MUL    0006  +5
0012 >  num LT     0009  +100
0013    num PHI    0002  0009
0014    num PHI    0004  0010
0015    num PHI    0006  0011

6. Překlad druhého demonstračního příkladu do strojového kódu procesorů x86_64

Překlad do nativního kódu mikroprocesorů x86_64 vypadá následovně:

---- TRACE 1 mcode 145
0bceff66  mov     dword [0x406bc4a0], 0x1
0bceff71  movsd   xmm3, [0x406c8bf0]
0bceff7a  movsd   xmm2, [0x406c8bf8]
0bceff83  movsd   xmm1, [0x406c8c00]
0bceff8c  movsd   xmm0, [0x406c8c08]
0bceff95  cmp     dword [rdx+0x4], 0xfffeffff
0bceff9c  jnb     0x0bce0010        ->0
0bceffa2  movsd   xmm5, [rdx]
0bceffa6  addsd   xmm5, xmm3
0bceffaa  cmp     dword [rdx+0xc], 0xfffeffff
0bceffb1  jnb     0x0bce0010        ->0
0bceffb7  movsd   xmm6, [rdx+0x8]
0bceffbc  mulsd   xmm6, xmm2
0bceffc0  cmp     dword [rdx+0x14], 0xfffeffff
0bceffc7  jnb     0x0bce0010        ->0
0bceffcd  movsd   xmm7, [rdx+0x10]
0bceffd2  mulsd   xmm7, xmm1
0bceffd6  ucomisd xmm0, xmm5
0bceffda  jbe     0x0bce0014        ->1
->LOOP:
0bceffe0  addsd   xmm5, xmm3
0bceffe4  mulsd   xmm6, xmm2
0bceffe8  mulsd   xmm7, xmm1
0bceffec  ucomisd xmm0, xmm5
0bcefff0  ja      0x0bceffe0 ->LOOP
0bcefff2  jmp     0x0bce001c        ->3
---- TRACE 1 stop -> loop

V těle smyčky nalezneme podle očekávání dvojici operací mulsd následovanou instrukcí ucomisd, která provede porovnání počitadla s konstantou uloženou v registru xmm0. To je docela zajímavé, protože v předchozím příkladu se podařilo počítanou smyčku for přeložit s využitím celočíselných operací – zde se skrývá jedna z předností této programové smyčky pro ty programátory, kteří se snaží o tvorbu co nejefektivnějšího kódu.

7. Překlad druhého demonstračního příkladu do strojového kódu procesoru ARM

Překlad do nativního kódu mikroprocesorů s architekturou ARM vypadá následovně:

---- TRACE 1 mcode 120
00397f88  mov      r0, #-1275068416
00397f8c  orr      r0, r0, #47710208
00397f90  orr      r0, r0, #23552
00397f94  vldr     d1, [r0, #424]
00397f98  vldr     d0, [r0, #432]
00397f9c  ldrd     r4, [r9]
00397fa0  cmn      r5, #14
00397fa4  blne     0x00390018  ->0
00397fa8  adds     r4, r4, #1
00397fac  blvs     0x00390018  ->0
00397fb0  ldr      lr, [r9, #12]
00397fb4  vldr     d3, [r9, #8]
00397fb8  cmn      lr, #15
00397fbc  blhs     0x00390018  ->0
00397fc0  vmul.f64 d14, d3, d1
00397fc4  ldr      lr, [r9, #20]
00397fc8  vldr     d2, [r9, #16]
00397fcc  cmn      lr, #15
00397fd0  blhs     0x00390018  ->0
00397fd4  vmul.f64 d15, d2, d0
00397fd8  cmp      r4, #100
00397fdc  blge     0x0039001c  ->1
->LOOP:
00397fe0  mov      r11, r4
00397fe4  adds     r4, r11, #1
00397fe8  blvs     0x00390020  ->2
00397fec  vmul.f64 d14, d14, d1
00397ff0  vmul.f64 d15, d15, d0
00397ff4  cmp      r4, #100
00397ff8  blt      0x00397fe0  ->LOOP
00397ffc  bl       0x00390024  ->3
---- TRACE 1 stop -> loop

Zde je kupodivu programová smyčka implementována v sedmi instrukcích, což je ve skutečnosti zbytečné – stačí se podívat na to, jakým způsobem se manipuluje s registry r4 a r11. Výpočet je realizován dvojicí instrukcí vmul.f64, řízení programové smyčky zajišťuje čtveřice adds+blvs+cmp+blt (blvs by se nemuselo provádět, jedná se o kontrolu přetečení).

Překlad do nativního kódu provedený například s využitím gcc by v tomto případě vypadal odlišně, a to i v případě, že by se při překladu nepoužily optimalizační metody typu rozbalení smyček apod.

8. Odkazy na zdrojové texty demonstračních příkladů i na JITované sekvence instrukcí

Oba dnes použité demonstrační příklady byly, jak je tomu ostatně v tomto seriálu již dlouhodobějším zvykem, uloženy do Git (přesněji řečeno do GitHub) repositáře umístěného na adrese https://github.com/tisnik/luajit-examples.

Následuje tabulka obsahující odkazy na poslední verze obou dnešních příkladů i na výstup vygenerovaný LuaJITem:

9. Literatura

  1. Bolz, Cuni, Fijalkowski, Rigo:
    „Tracing the Meta-Level: PyPy's Tracing JIT Compiler“
  2. Vasanth Bala, Evelyn Duesterwald, Sanjeev Banerjia:
    „Dynamo: A Transparent Dynamic Optimization System“
  3. Bolz, Cuni, Fijalkowski, Leuschel, Pedroni, Rigo: „Allocation removal by partial evaluation in a tracing JIT“
  4. Bolz:
    „Automatic JIT Compiler Generation with Runtime Partial Evaluation“
  5. Bolz, Kuhn, Lienhard, Matsakis, Nierstrasz, Renggli, Rigo and T. Verwaest:
    „Back to the Future in One Week – Implementing a Smalltalk VM in PyPy“
    pages 123–139. 2008.
  6. Bolz and Rigo:
    „How to not write a virtual machine“
    In Proceedings of the 3rd Workshop on Dynamic Languages and Applications (DYLA), 2007
  7. Bruni, Verwaest:
    „PyGirl: generating Whole-System VMs from High-Level prototypes using PyPy“
    In Tools, accepted for publication, 2009.
  8. Sullivan, Bruening, Baron, Garnett and Amarasinghe:
    „Dynamic native optimization of interpreters“
    In Proceedings of the 2003 Workshop on Interpreters,
    Virtual Machines and Emulators pages 50–57, San Diego, California, 2003. ACM.

10. Odkazy na Internetu

  1. Static single assignment form (SSA)
    http://en.wikipedia.org/wi­ki/Static_single_assignmen­t_form
  2. LuaJIT 2.0 SSA IRhttp://wiki.luajit.org/SSA-IR-2.0
  3. Dynamic Assembler
    http://luajit.org/dynasm.html
  4. The Unofficial DynASM Documentation: Introduction
    http://corsix.github.io/dynasm-doc/index.html
  5. Have tracing JIT compilers won?
    http://lambda-the-ultimate.org/node/3851
  6. Tracing just-in-time compilation
    http://en.wikipedia.org/wi­ki/Tracing_just-in-time_compilation
  7. How does LuaJIT's trace compiler work?
    http://www.freelists.org/pos­t/luajit/How-does-LuaJITs-trace-compiler-work,1
  8. How does LuaJIT's trace compiler work?
    http://stackoverflow.com/qu­estions/20266523/how-does-luajits-trace-compiler-work
  9. TraceMonkey
    https://wiki.mozilla.org/Ja­vaScript:TraceMonkey
  10. TraceMonkey
    http://brendaneich.com/2008/08/tra­cemonkey-javascript-lightspeed/
  11. Improving JavaScript performance with JägerMonkey
    http://hacks.mozilla.org/2010/03/im­proving-javascript-performance-with-jagermonkey/
  12. Wikipedia: Mezijazyk
    http://cs.wikipedia.org/wi­ki/Mezijazyk
  13. The LuaJIT Project
    http://luajit.org/index.html
  14. LuaJIT FAQ
    http://luajit.org/faq.html
  15. LuaJIT Performance Comparison
    http://luajit.org/performance.html
  16. LuaJIT 2.0 intellectual property disclosure and research opportunities
    http://article.gmane.org/gma­ne.comp.lang.lua.general/58908
  17. LuaJIT Wiki
    http://wiki.luajit.org/Home
  18. LuaJIT 2.0 Bytecode Instructions
    http://wiki.luajit.org/Bytecode-2.0
  19. Programming in Lua 9.1 – Coroutine Basics,
    http://www.lua.org/pil/9.1.html
  20. Programming in Lua (first edition)
    http://www.lua.org/pil/contents.html
  21. Programming in Lua: 6 – More about Functions
    http://www.lua.org/pil/6.html
  22. Lua Lanes
    http://kotisivu.dnainternet­.net/askok/bin/lanes/
  23. Programming in Lua: 6.1 – Closures
    http://www.lua.org/pil/6.1.html
  24. Programming in Lua: 9.1 – Coroutine Basics
    http://www.lua.org/pil/9.1.html
  25. Programming in Lua: Numeric for
    http://www.lua.org/pil/4.3.4.html
  26. Programming in Lua: break and return
    http://www.lua.org/pil/4.4.html
  27. Programming in Lua: Tables
    http://www.lua.org/pil/2.5.html
  28. Programming in Lua: Table Constructors
    http://www.lua.org/pil/3.6.html
  29. Programovací jazyk Lua
    http://palmknihy.cz/web/kni­ha/programovaci-jazyk-lua-12651.htm
  30. Lua: Tables Tutorial
    http://lua-users.org/wiki/TablesTutorial
  31. Lua: Control Structure Tutorial
    http://lua-users.org/wiki/ControlStruc­tureTutorial
  32. Lua Types Tutorial
    http://lua-users.org/wiki/LuaTypesTutorial
  33. Goto Statement in Lua
    http://lua-users.org/wiki/GotoStatement
  34. Lua 5.2 sources
    http://www.lua.org/source/5.2/
  35. Lua 5.2 sources – lopcodes.h
    http://www.lua.org/source/5­.2/lopcodes.h.html
  36. Lua 5.2 sources – lopcodes.c
    http://www.lua.org/source/5­.2/lopcodes.c.html
  37. Lambda the Ultimate: Coroutines in Lua,
    http://lambda-the-ultimate.org/node/438
  38. Coroutines Tutorial,
    http://lua-users.org/wiki/CoroutinesTutorial
  39. Lua Coroutines Versus Python Generators,
    http://lua-users.org/wiki/LuaCorouti­nesVersusPythonGenerators
  40. SSE (Streaming SIMD Extentions)
    http://www.songho.ca/misc/sse/sse­.html
  41. Timothy A. Chagnon: SSE and SSE2
    http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf
  42. Intel corporation: Extending the World's Most Popular Processor Architecture
    http://download.intel.com/techno­logy/architecture/new-instructions-paper.pdf
  43. SIMD architectures:
    http://arstechnica.com/ol­d/content/2000/03/simd.ar­s/
  44. Sixth Generation Processors
    http://www.pcguide.com/ref/cpu/fam/g6­.htm
  45. Great Microprocessors of the Past and Present
    http://www.cpushack.com/CPU/cpu1.html
  46. The VFP architecture
    http://infocenter.arm.com/hel­p/index.jsp?topic=/com.ar­m.doc.dui0056d/Bcfibfha.html
  47. ARM Floating Point Accelerator (ARM FPA)
    http://vswww.kaist.ac.kr/ver4­.0/index.php/research/past-research/arm-fpa.html
  48. The ARM Processor Architecture
    http://www.arm.com/produc­ts/processors/technologies/in­struction-set-architectures.php