Obsah
1. Pohled pod kapotu JVM – překlad do bajtkódů JVM, Lua VM a Python VM
3. Parrot Assembly Language a Parrot Intermediate Representation
4. Jak lze získat přeložený bajtkód pro různé VM?
5. Překlad aritmetických výrazů
6. Překlad výrazů s Booleovskými operátory
7. Zkrácené vs. úplné vyhodnocení logických výrazů v Javě
8. Překlad výrazů s relačními operátory
9. Překlad řídicí struktury typu if-then
10. Překlad řídicí struktury typu if-then-else
11. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů
1. Pohled pod kapotu JVM – překlad do bajtkódů JVM, Lua VM a Python VM
V předchozí části seriálu o programovacím jazyku Java i o virtuálním stroji Javy jsme si ve stručnosti popsali trojici virtuálních strojů (VM), které jsou v současnosti používány v souvislosti s programovacími jazyky Java, Python a Lua. V případě programovacího jazyka Java se jedná o Java Virtual Machine (JVM), což může být ovšem poněkud zavádějící název, neboť nad JVM je dnes postaveno mnohem více programovacích jazyků, nejenom Java (zmínit se můžeme například o Jythonu, Scale, Groovy, Clojure, JACL či JavaScriptu). Pro Python, přesněji řečeno pro CPython, existuje taktéž vlastní VM, podobně jako pro programovací jazyk Lua. Každý ze zmíněných virtuálních strojů zpracovává svůj vlastní bajtkód, přičemž vlastnosti bajtkódů JVM, Python VM a Lua VM se od sebe v některých aspektech dosti odlišují; především mírou abstrakce nad základními datovými typy a taktéž tím, zda jednotlivé instrukce bajtkódu pracují s registry či s operandy uloženými na zásobníku.
V dnešním článku se seznámíme se způsobem překladu některých základních a v každodenním vývoji využívaných programových konstrukcí do bajtkódu jednotlivých výše zmíněných virtuálních strojů. Zaměříme se především na překlad běžných aritmetických, logických a bitových výrazů i na překlad programové konstrukce if-then a samozřejmě i úplné rozhodovací konstrukce if-then-else. Ještě předtím se však musíme seznámit se čtvrtým v současnosti vyvíjeným VM. Jedná se o virtuální stroj nazvaný Parrot, který je zajímavý hned z několika hledisek, což ostatně uvidíme hned v následující kapitole, kde se zmíníme o některých základních konceptech, na nichž je tento virtuální stroj postaven a jaké jsou jeho největší odlišnosti například v porovnání s Java Virtual Machine.
2. Virtuální stroj Parrot
Posledním virtuálním strojem, s nímž se v tomto seriálu alespoň ve stručnosti seznámíme, je virtuální stroj pojmenovaný Parrot. Tento virtuální stroj byl navržen takovým způsobem, aby mohl podporovat moderní dynamicky typované programovací jazyky, přičemž primárním (nejenom však jediným) jazykem je/bude Perl 6 (předchozí verze Perlu naproti tomu namísto klasického bajtkódu používají stromovou reprezentaci AST – Abstract Syntax Tree). Některé operace/instrukce podporované Parrotem jsou na vyšší úrovni, než je tomu například v případě bajtkódu JVM; Parrot VM je v tomto ohledu srovnatelný s Python VM.
Virtuální stroj Parrot je založen na použití registrů, přičemž je zajímavé, že se již při překladu (jenž může probíhat i v runtime) určuje, kolik registrů bude daná metoda či funkce využívat, což znamená, že počet registrů není pevně určen. Volba registrů namísto zásobníku byla ovlivněna především předpokladem, že se bajtkód založený na operacích prováděných nad registry bude snadněji překládat do nativního kódu; ve skutečnosti je ovšem i zásobníkový kód relativně snadno překládaný, což je vidět na příkladu JVM.
3. Parrot Assembly Language a Parrot Intermediate Representation
Ze všech čtyř popisovaných virtuálních strojů je Parrot zdaleka nejotevřenější různým možnostem rozšiřování a/nebo zásahu do překladu, interpretace popř. JIT překladu. Parrot – na rozdíl od JVM atd. – dokonce podporuje i vlastní assembler, který existuje ve dvou variantách. Vysokoúrovňová varianta assembleru se nazývá Parrot Intermediate Representation neboli PIR a předpokládá se, že překladače různých programovacích jazyků mohou provádět překlad právě do PIR, což je jednodušší i transparentnější, než přímá generace binárního bajtkódu.
Nízkoúrovňová varianta assembleru se nazývá Parrot Assembly Language neboli PASM. Tento assembler se podobá assemblerům skutečných mikroprocesorů, ovšem obsahuje například i podporu pro práci s řetězci. Právě na příkladu PIR a PASM si v následující části tohoto seriálu ukážeme, jakým způsobem vlastně virtuální stroj Parrot pracuje a jak zpracovává přeložený bajtkód.
4. Jak lze získat přeložený bajtkód pro různé VM?
Před uvedením a popisem jednotlivých demonstračních příkladů si musíme vysvětlit, jakým způsobem je vlastně možné vypsat bajtkód vygenerovaný překladačem, ať již se jedná o překladač Javy, či o překladače jazyků Lua nebo Python (ano, i zde je překlad do bajtkódu prováděn, a to vždy před vykonáním nějakého skriptu či dokonce explicitně). V případě programovacího jazyka Java je možné dekompilovat již přeloženou třídu s využitím nástroje javap (součást standardní instalace JDK), který se spustí s parametrem -c. Bližší informace o tomto nástroji lze získat pomocí příkazu man javap popř. javap –help. Příklad použití – dekompilace třídy Test, jejíž bajtkód je uložen v souboru s názvem „Test.class“:
javap -c Test
U programovacího jazyka Lua je možné využít překladač nazvaný luac, kterému se předá volba -l. Tento nástroj se pokusí přeložit skript či modul, jehož jméno je předáno na příkazové řádce a vytvořit bajtkód uložený v souboru, jehož výchozí jméno je luac.out; přitom se ovšem na standardní výstup vypíše při použití volby -l i generovaný bajtkód v čitelné podobě. Více informací o tomto velmi užitečném nástroji nám opět poskytnou příkazy man luac popř. pouze luac (bez dalších parametrů). Příklad použití – výpis bajtkódu všech funkcí i přímo zadaných příkazů uložených ve skriptu se jménem „Test.lua“:
luac -l Test.lua
U programovacího jazyka Python lze pro výpis kompilovaného bajtkódu v pro programátora čitelné podobě použít modul nazvaný dis. V tomto modulu se nachází stejnojmenná funkce, které stačí pouze předat jméno funkce a na standardní výstup se vypíše její bajtkód. Opět se podívejme na jednoduchý příklad použití:
from dis import dis dis(testFunction)
5. Překlad aritmetických výrazů
Nyní se již pojďme věnovat poněkud praktičtějšímu tématu – způsobu překladu různých programových konstrukcí do bajtkódu JVM, Python VM a taktéž Lua VM. V této kapitole si ukážeme, jak se překládají základní aritmetické výrazy, a to zejména z toho důvodu, že právě na překladu aritmetických výrazů bude patrný největší rozdíl mezi virtuálními stroji založenými na zásobníku a operacích s operandy uloženými na tomto zásobníku na jedné straně a s virtuálními stroji založenými na sadě registrů na straně druhé.
Demonstrační příklad Test2.java:
První varianta testovacího příkladu je vytvořena v Javě a obsahuje jak jednoduché výrazy s jediným operátorem, tak i složitější výrazy s několika operátory s různou prioritou i závorkami:
/** * Trida s nekolika jednoduchymi statickymi metodami * pro otestovani zakladnich vlastnosti bajtkodu JVM: * prekladu aritmetickych vyrazu. */ public class Test2 { public static int vyraz1(int x, int y) { int result = x + y; return result; } public static int vyraz2(int x, int y) { int result = x - y; return result; } public static int vyraz3(int x, int y) { int result = x * y; return result; } public static int vyraz4(int x, int y) { int result = x / y; return result; } public static int vyraz5(int x, int y) { int result = x % y; return result; } public static int vyraz6(int x, int y, int z) { int result = x + y * z; return result; } public static int vyraz7(int x, int y, int z, int w) { int result = x + y * z + w; return result; } public static int vyraz8(int x, int y, int z, int w) { int result = 2 * (x + y) * (z + w) * ((x + z) / (y + w)); return result; } /** * Vse je nutne otestovat. */ public static void main(String[] args) { System.out.println(vyraz1(4, 3)); System.out.println(vyraz2(4, 3)); System.out.println(vyraz3(4, 3)); System.out.println(vyraz4(4, 3)); System.out.println(vyraz5(4, 3)); System.out.println(vyraz6(4, 3, 2)); System.out.println(vyraz7(4, 3, 2, 1)); System.out.println(vyraz8(4, 3, 2, 1)); } }
Demonstrační příklad Test2.lua:
Druhá varianta je vytvořena v Lua. Důležité je si uvědomit, že tento příklad ve skutečnosti není ekvivalentní předchozímu příkladu, a to proto, že se výpočty provádí s hodnotami s plovoucí řádovou čárkou:
-- -- Modul s nekolika jednoduchymi funkcemi -- pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua -- prekladu aritmetickych vyrazu. -- function vyraz1(x, y) local result = x + y return result end function vyraz2(x, y) local result = x - y return result end function vyraz3(x, y) local result = x * y return result end function vyraz4(x, y) local result = x / y return result end function vyraz5(x, y) local result = x % y return result end function vyraz6(x, y, z) local result = x + y * z return result end function vyraz7(x, y, z, w) local result = x + y * z + w return result end function vyraz8(x, y, z, w) local result = 2 * (x + y) * (z + w) * ((x + z) / (y + w)) return result end -- -- Vse je nutne otestovat. -- function main() print(vyraz1(4, 3)) print(vyraz2(4, 3)) print(vyraz3(4, 3)) print(vyraz4(4, 3)) print(vyraz5(4, 3)) print(vyraz6(4, 3, 2)) print(vyraz7(4, 3, 2, 1)) print(vyraz8(4, 3, 2, 1)) end main()
Demonstrační příklad Test2.py:
Třetí varianta je vytvořena v Pythonu:
# # Modul s nekolika jednoduchymi funkcemi # pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua # prekladu aritmetickych vyrazu. # def vyraz1(x, y): local result = x + y return result def vyraz2(x, y): local result = x - y return result def vyraz3(x, y): local result = x * y return result def vyraz4(x, y): local result = x / y return result def vyraz5(x, y): local result = x % y return result def vyraz6(x, y, z): local result = x + y * z return result def vyraz7(x, y, z, w): local result = x + y * z + w return result def vyraz8(x, y, z, w): local result = 2 * (x + y) * (z + w) * ((x + z) / (y + w)) return result # # Vse je nutne otestovat. # def main(): print(vyraz1(4, 3)) print(vyraz2(4, 3)) print(vyraz3(4, 3)) print(vyraz4(4, 3)) print(vyraz5(4, 3)) print(vyraz6(4, 3, 2)) print(vyraz7(4, 3, 2, 1)) print(vyraz8(4, 3, 2, 1)) def disassemble(): from dis import dis print("\nvyraz1:") dis(vyraz1) print("\nvyraz2:") dis(vyraz2) print("\nvyraz3:") dis(vyraz3) print("\nvyraz4:") dis(vyraz4) print("\nvyraz5:") dis(vyraz5) print("\nvyraz6:") dis(vyraz6) print("\nvyraz7:") dis(vyraz7) print("\nvyraz8:") dis(vyraz8) main() disassemble()
Nyní se podívejme, jak vypadají jednotlivé bajtkódy.
Přeložený bajtkód demonstračního příkladu Test2.java:
V Javě se setkáme s klasickým zásobníkovým kódem, na nějž se ukládají parametry metod a/nebo lokální proměnné či konstanty:
public static int vyraz1(int, int); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: iadd ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 5: ireturn ; výskok z metody s předáním návratové hodnoty public static int vyraz2(int, int); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: isub ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 5: ireturn ; výskok z metody s předáním návratové hodnoty public static int vyraz3(int, int); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: imul ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 5: ireturn ; výskok z metody s předáním návratové hodnoty public static int vyraz4(int, int); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: idiv ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 5: ireturn ; výskok z metody s předáním návratové hodnoty public static int vyraz5(int, int); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: irem ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 5: ireturn ; výskok z metody s předáním návratové hodnoty public static int vyraz6(int, int, int); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: iload_2 ; uložit třetí parametr metody na zásobník 3: imul ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 4: iadd ; provést druhou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 5: istore_3 ; uložit výsledek do lokální proměnné 6: iload_3 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 7: ireturn ; výskok z metody s předáním návratové hodnoty public static int vyraz7(int, int, int, int); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: iload_2 ; uložit třetí parametr metody na zásobník 3: imul ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 4: iadd ; provést druhou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 5: iload_3 ; uložit třetí parametr metody na zásobník 6: iadd ; provést třetí vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 7: istore 4 ; uložit výsledek do lokální proměnné 9: iload 4 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 11: ireturn ; výskok z metody s předáním návratové hodnoty public static int vyraz8(int, int, int, int); Code: 0: iconst_2 ; uložit konstantu na zásobník 1: iload_0 ; uložit první parametr metody na zásobník 2: iload_1 ; uložit druhý parametr metody na zásobník 3: iadd ; provést vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 4: imul ; provést druhou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 5: iload_2 ; uložit třetí parametr metody na zásobník 6: iload_3 ; uložit čtvrtý parametr metody na zásobník 7: iadd ; provést třetí vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 8: imul ; provést čtvrtou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 9: iload_0 ; uložit první parametr metody na zásobník 10: iload_2 ; uložit třetí parametr metody na zásobník 11: iadd ; provést pátou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 12: iload_1 ; uložit druhý parametr metody na zásobník 13: iload_3 ; uložit čtvrtý parametr metody na zásobník 14: iadd ; provést šestou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 15: idiv ; provést sedmou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 16: imul ; provést osmou vyžadovanou aritmetickou operaci a uložit výsledek zpět na zásobník 17: istore 4 ; uložit výsledek do lokální proměnné 19: iload 4 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 21: ireturn ; výskok z metody s předáním návratové hodnoty
Přeložený bajtkód demonstračního příkladu Test2.lua:
V Lue je použit kód využívající „registry“ virtuálního stroje a proto je počet instrukcí menší, než u kódu zásobníkového:
function <Test2.lua:7,10> (3 instructions at 0x9e07c88) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [8] ADD 2 0 1 ; provést aritmetickou operaci s parametrem 0 a 1 2 [9] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 3 [10] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test2.lua:12,15> (3 instructions at 0x9e07f20) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [13] SUB 2 0 1 ; provést aritmetickou operaci s parametrem 0 a 1 2 [14] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 3 [15] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test2.lua:17,20> (3 instructions at 0x9e080f0) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [18] MUL 2 0 1 ; provést aritmetickou operaci s parametrem 0 a 1 2 [19] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 3 [20] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test2.lua:22,25> (3 instructions at 0x9e07ec8) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [23] DIV 2 0 1 ; provést aritmetickou operaci s parametrem 0 a 1 2 [24] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 3 [25] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test2.lua:27,30> (3 instructions at 0x9e084f8) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [28] MOD 2 0 1 ; provést aritmetickou operaci s parametrem 0 a 1 2 [29] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 3 [30] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test2.lua:32,35> (4 instructions at 0x9e07e18) 3 params, 4 slots, 0 upvalues, 4 locals, 0 constants, 0 functions 1 [33] MUL 3 1 2 ; provést aritmetickou operaci s parametrem 1 a 2 2 [33] ADD 3 0 3 ; provést aritmetickou operaci s parametrem 0 a lokální proměnnou 3 3 [34] RETURN 3 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 3 4 [35] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test2.lua:37,40> (5 instructions at 0x9e08458) 4 params, 5 slots, 0 upvalues, 5 locals, 0 constants, 0 functions 1 [38] MUL 4 1 2 ; provést aritmetickou operaci s parametrem 1 a 2 2 [38] ADD 4 0 4 ; provést další aritmetickou operaci s parametrem 0 a lokální proměnnou 4 3 [38] ADD 4 4 3 ; provést další aritmetickou operaci s parametrem 3 a lokální proměnnou 4 4 [39] RETURN 4 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 4 5 [40] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test2.lua:42,45> (10 instructions at 0x9e08720) 4 params, 7 slots, 0 upvalues, 5 locals, 1 constant, 0 functions 1 [43] ADD 4 0 1 ; provést aritmetickou operaci s parametrem 0 a 1 2 [43] MUL 4 -1 4 ; 2 - ; zde se adresuje konstanta -2 !!! 3 [43] ADD 5 2 3 ; provést další aritmetickou operaci, výsledek do lok. proměnné 5 4 [43] MUL 4 4 5 5 [43] ADD 5 0 2 6 [43] ADD 6 1 3 7 [43] DIV 5 5 6 8 [43] MUL 4 4 5 9 [44] RETURN 4 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 4 10 [45] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce
Přeložený bajtkód demonstračního příkladu Test2.py:
V Pythonu je opět použit, jak zajisté po přečtení předchozí části tohoto seriálu očekáváte, zásobníkový kód:
vyraz1: 8 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_ADD 7 STORE_FAST 2 (result) 9 10 LOAD_FAST 2 (result) 13 RETURN_VALUE vyraz2: 13 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_SUBTRACT 7 STORE_FAST 2 (result) 14 10 LOAD_FAST 2 (result) 13 RETURN_VALUE vyraz3: 18 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_MULTIPLY 7 STORE_FAST 2 (result) 19 10 LOAD_FAST 2 (result) 13 RETURN_VALUE vyraz4: 23 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_DIVIDE 7 STORE_FAST 2 (result) 24 10 LOAD_FAST 2 (result) 13 RETURN_VALUE vyraz5: 28 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_MODULO 7 STORE_FAST 2 (result) 29 10 LOAD_FAST 2 (result) 13 RETURN_VALUE vyraz6: 33 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 LOAD_FAST 2 (z) 9 BINARY_MULTIPLY 10 BINARY_ADD 11 STORE_FAST 3 (result) 34 14 LOAD_FAST 3 (result) 17 RETURN_VALUE vyraz7: 38 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 LOAD_FAST 2 (z) 9 BINARY_MULTIPLY 10 BINARY_ADD 11 LOAD_FAST 3 (w) 14 BINARY_ADD 15 STORE_FAST 4 (result) 39 18 LOAD_FAST 4 (result) 21 RETURN_VALUE vyraz8: 43 0 LOAD_CONST 1 (2) 3 LOAD_FAST 0 (x) 6 LOAD_FAST 1 (y) 9 BINARY_ADD 10 BINARY_MULTIPLY 11 LOAD_FAST 2 (z) 14 LOAD_FAST 3 (w) 17 BINARY_ADD 18 BINARY_MULTIPLY 19 LOAD_FAST 0 (x) 22 LOAD_FAST 2 (z) 25 BINARY_ADD 26 LOAD_FAST 1 (y) 29 LOAD_FAST 3 (w) 32 BINARY_ADD 33 BINARY_DIVIDE 34 BINARY_MULTIPLY 35 STORE_FAST 4 (result) 44 38 LOAD_FAST 4 (result) 41 RETURN_VALUE
6. Překlad výrazů s Booleovskými operátory
Booleovské (logické) výrazy se většinou překládají s využitím podmíněného skoku. Před samotnou instrukcí skoku se vyhodnotí podmínka, v našem případě první část logického výrazu, a na základě této podmínky se zjistí hodnota druhé části logického výrazu (pokud se samozřejmě jedná o operace se dvěma operandy). Podívejme se nyní na způsob překladu výrazů obsahujících negaci, logický součet, logický součin, operaci nonekvivalence a různé kombinace těchto operací.
Demonstrační příklad Test3.java:
/** * Trida s nekolika jednoduchymi statickymi metodami * pro otestovani zakladnich vlastnosti bajtkodu JVM: * prekladu Booleovskych vyrazu. */ public class Test3 { public static boolean vyraz1(boolean x) { boolean result = !x; return result; } public static boolean vyraz2(boolean x, boolean y) { boolean result = x && y; return result; } public static boolean vyraz3(boolean x, boolean y) { boolean result = x || y; return result; } public static boolean vyraz4(boolean x, boolean y) { boolean result = x ^ y; return result; } public static boolean vyraz5(boolean x, boolean y, boolean z) { boolean result = x || y && z; return result; } public static boolean vyraz6(boolean x, boolean y, boolean z, boolean w) { boolean result = (x || y) && (z || w); return result; } /** * Vse je nutne otestovat. */ public static void main(String[] args) { System.out.println(vyraz1(true)); System.out.println(vyraz2(true, false)); System.out.println(vyraz3(true, false)); System.out.println(vyraz4(true, false)); System.out.println(vyraz5(true, false, true)); System.out.println(vyraz6(true, false, true, false)); } }
Demonstrační příklad Test3.lua:
-- -- Modul s nekolika jednoduchymi funkcemi -- pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua -- prekladu Booleovskych vyrazu. -- function vyraz1(x) local result = not x return result end function vyraz2(x, y) local result = x and y return result end function vyraz3(x, y) local result = x or y return result end function vyraz4(x, y) local result = x ~= y return result end function vyraz5(x, y, z) local result = x or y and z return result end function vyraz6(x, y, z, w) local result = (x or y) and (z or w) return result end -- -- Vse je nutne otestovat. -- function main() print(vyraz1(true)) print(vyraz2(true, false)) print(vyraz3(true, false)) print(vyraz4(true, false)) print(vyraz5(true, false, true)) print(vyraz6(true, false, true, false)) end main()
Demonstrační příklad Test3.py:
# # Modul s nekolika jednoduchymi funkcemi # pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua # prekladu Booleovskych vyrazu. # def vyraz1(x): result = not x return result def vyraz2(x, y): result = x and y return result def vyraz3(x, y): result = x or y return result def vyraz4(x, y): result = x ^ y return result def vyraz5(x, y, z): result = x or y and z return result def vyraz6(x, y, z, w): result = (x or y) and (z or w) return result # # Vse je nutne otestovat. # def main(): print(vyraz1(True)) print(vyraz2(True, False)) print(vyraz3(True, False)) print(vyraz4(True, False)) print(vyraz5(True, False, True)) print(vyraz6(True, False, True, False)) def disassemble(): from dis import dis print("\nvyraz1:") dis(vyraz1) print("\nvyraz2:") dis(vyraz2) print("\nvyraz3:") dis(vyraz3) print("\nvyraz4:") dis(vyraz4) print("\nvyraz5:") dis(vyraz5) print("\nvyraz6:") dis(vyraz6) main() disassemble()
Přeložený bajtkód demonstračního příkladu Test3.java:
V Javě se při zkráceném vyhodnocování logických výrazů objevují skoky:
public static boolean vyraz1(boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifne 8 ; podmíněný skok 4: iconst_1 ; konstanta true 5: goto 9 ; nepodmíněný skok 8: iconst_0 ; konstanta false 9: istore_1 ; uložit výsledek do lokální proměnné 10: iload_1 ; uložit druhý parametr metody na zásobník 11: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz2(boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifeq 12 ; podmíněný skok 4: iload_1 ; uložit druhý parametr metody na zásobník 5: ifeq 12 ; podmíněný skok 8: iconst_1 ; konstanta true 9: goto 13 ; nepodmíněný skok 12: iconst_0 ; konstanta false 13: istore_2 ; uložit výsledek do lokální proměnné 14: iload_2 15: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz3(boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifne 8 ; podmíněný skok 4: iload_1 ; uložit druhý parametr metody na zásobník 5: ifeq 12 ; podmíněný skok 8: iconst_1 ; konstanta true 9: goto 13 ; nepodmíněný skok 12: iconst_0 ; konstanta false 13: istore_2 ; uložit výsledek do lokální proměnné 14: iload_2 15: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz4(boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: ixor ; provést logickou operaci 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 5: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz5(boolean, boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifne 12 ; podmíněný skok 4: iload_1 ; uložit druhý parametr metody na zásobník 5: ifeq 16 ; podmíněný skok 8: iload_2 9: ifeq 16 ; podmíněný skok 12: iconst_1 ; konstanta true 13: goto 17 ; nepodmíněný skok 16: iconst_0 ; konstanta false 17: istore_3 ; uložit výsledek do lokální proměnné 18: iload_3 19: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz6(boolean, boolean, boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifne 8 ; podmíněný skok 4: iload_1 ; uložit druhý parametr metody na zásobník 5: ifeq 20 ; podmíněný skok 8: iload_2 9: ifne 16 ; podmíněný skok 12: iload_3 13: ifeq 20 ; podmíněný skok 16: iconst_1 ; konstanta true 17: goto 21 ; nepodmíněný skok 20: iconst_0 ; konstanta false 21: istore 4 ; uložit výsledek do lokální proměnné 23: iload 4 25: ireturn ; výskok z metody s předáním návratové hodnoty
Přeložený bajtkód demonstračního příkladu Test3.lua:
Podmíněné skoky nalezneme i v bajtkódu virtuálního stroje jazyka Lua:
function <Test3.lua:7,10> (3 instructions at 0x8ae6c88) 1 param, 2 slots, 0 upvalues, 2 locals, 0 constants, 0 functions 1 [8] NOT 1 0 ; provést logickou operaci 2 [9] RETURN 1 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 1 3 [10] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test3.lua:12,15> (5 instructions at 0x8ae6f08) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [13] TESTSET 2 0 0 2 [13] JMP 0 1 ; to 4 ; skok 3 [13] MOVE 2 1 4 [14] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 5 [15] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test3.lua:17,20> (5 instructions at 0x8ae7120) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [18] TESTSET 2 0 1 2 [18] JMP 0 1 ; to 4 ; skok 3 [18] MOVE 2 1 4 [19] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 5 [20] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test3.lua:22,25> (6 instructions at 0x8ae6eb0) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [23] EQ 0 0 1 2 [23] JMP 0 1 ; to 4 ; skok 3 [23] LOADBOOL 2 0 1 4 [23] LOADBOOL 2 1 0 5 [24] RETURN 2 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 2 6 [25] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test3.lua:27,30> (7 instructions at 0x8ae7590) 3 params, 4 slots, 0 upvalues, 4 locals, 0 constants, 0 functions 1 [28] TESTSET 3 0 1 2 [28] JMP 0 3 ; to 6 ; skok 3 [28] TESTSET 3 1 0 4 [28] JMP 0 1 ; to 6 ; skok 5 [28] MOVE 3 2 6 [29] RETURN 3 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 3 7 [30] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test3.lua:32,35> (9 instructions at 0x8ae74a0) 4 params, 5 slots, 0 upvalues, 5 locals, 0 constants, 0 functions 1 [33] TEST 0 1 2 [33] JMP 0 2 ; to 5 ; skok 3 [33] TESTSET 4 1 0 4 [33] JMP 0 3 ; to 8 ; skok 5 [33] TESTSET 4 2 1 6 [33] JMP 0 1 ; to 8 ; skok 7 [33] MOVE 4 3 8 [34] RETURN 4 2 ; návrat z funkce a vrácení hodnoty lokální proměnné 4 9 [35] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce
Přeložený bajtkód demonstračního příkladu Test3.py:
Pravděpodobně nebude velkým překvapením, že se s podmíněnými skoky setkáme i v bajtkódu virtuálního stroje jazyka Python (CPython):
vyraz1: 8 0 LOAD_FAST 0 (x) 3 UNARY_NOT 4 STORE_FAST 1 (result) 9 7 LOAD_FAST 1 (result) 10 RETURN_VALUE vyraz2: 12 0 LOAD_FAST 0 (x) 3 JUMP_IF_FALSE 4 (to 10) 6 POP_TOP 7 LOAD_FAST 1 (y) >> 10 STORE_FAST 2 (result) 13 13 LOAD_FAST 2 (result) 16 RETURN_VALUE vyraz3: 16 0 LOAD_FAST 0 (x) 3 JUMP_IF_TRUE 4 (to 10) 6 POP_TOP 7 LOAD_FAST 1 (y) >> 10 STORE_FAST 2 (result) 17 13 LOAD_FAST 2 (result) 16 RETURN_VALUE vyraz4: 20 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_XOR 7 STORE_FAST 2 (result) 21 10 LOAD_FAST 2 (result) 13 RETURN_VALUE vyraz5: 24 0 LOAD_FAST 0 (x) 3 JUMP_IF_TRUE 11 (to 17) 6 POP_TOP 7 LOAD_FAST 1 (y) 10 JUMP_IF_FALSE 4 (to 17) 13 POP_TOP 14 LOAD_FAST 2 (z) >> 17 STORE_FAST 3 (result) 25 20 LOAD_FAST 3 (result) 23 RETURN_VALUE vyraz6: 28 0 LOAD_FAST 0 (x) 3 JUMP_IF_TRUE 7 (to 13) 6 POP_TOP 7 LOAD_FAST 1 (y) 10 JUMP_IF_FALSE 11 (to 24) >> 13 POP_TOP 14 LOAD_FAST 2 (z) 17 JUMP_IF_TRUE 4 (to 24) 20 POP_TOP 21 LOAD_FAST 3 (w) >> 24 STORE_FAST 4 (result) 29 27 LOAD_FAST 4 (result) 30 RETURN_VALUE
7. Zkrácené vs. úplné vyhodnocení logických výrazů v Javě
Čtenáři, kteří jsou alespoň částečně obeznámeni s assemblerem, pravděpodobně budou předpokládat, že logické (Booleovské) výrazy se budou překládat podobným způsobem jako výrazy aritmetické; samozřejmě s tím rozdílem, že budou využívány jiné instrukce pro provedení logických operací. Ve skutečnosti však může být zpracování logických výrazů odlišné, a to zejména z toho důvodu, že (například v Javě) je možné se rozhodnout mezi zkráceným a nezkráceným vyhodnocením těchto výrazů – u dvou základních logických operací (logický součet a logický součin) je totiž možné již na základě hodnoty levého operandu v některých případech zjistit výsledek celého výrazu a tudíž není zapotřebí druhý operand vůbec vyhodnocovat, což například v případě Javy vede k vytvoření bajtkódu obsahujícího programový skok. Pokud však předchozí demonstrační příklad nepatrně upravíme takovým způsobem, aby se používalo nezkrácené vyhodnocení logického součtu a logického součinu, skoky v bajtkódu „magicky“ zmizí, o čemž se samozřejmě můžeme snadno přesvědčit:
Upravený demonstrační příklad Test3.java:
/** * Trida s nekolika jednoduchymi statickymi metodami * pro otestovani zakladnich vlastnosti bajtkodu JVM: * prekladu NEZKRACENE vyhodnocovanych Booleovskych vyrazu. */ public class Test3 { public static boolean vyraz1(boolean x) { boolean result = !x; return result; } public static boolean vyraz2(boolean x, boolean y) { boolean result = x & y; return result; } public static boolean vyraz3(boolean x, boolean y) { boolean result = x | y; return result; } public static boolean vyraz4(boolean x, boolean y) { boolean result = x ^ y; return result; } public static boolean vyraz5(boolean x, boolean y, boolean z) { boolean result = x | y & z; return result; } public static boolean vyraz6(boolean x, boolean y, boolean z, boolean w) { boolean result = (x | y) & (z | w); return result; } /** * Vse je nutne otestovat. */ public static void main(String[] args) { System.out.println(vyraz1(true)); System.out.println(vyraz2(true, false)); System.out.println(vyraz3(true, false)); System.out.println(vyraz4(true, false)); System.out.println(vyraz5(true, false, true)); System.out.println(vyraz6(true, false, true, false)); } }
Přeložený bajtkód upraveného demonstračního příkladu Test3.java:
Namísto programových skoků se nově používají instrukce iand a ior:
public static boolean vyraz2(boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: iand ; provést vyžadovanou logickou operaci a uložit výsledek zpět na zásobník 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 5: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz3(boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: ior ; provést vyžadovanou logickou operaci a uložit výsledek zpět na zásobník 3: istore_2 ; uložit výsledek do lokální proměnné 4: iload_2 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 5: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz5(boolean, boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: iload_2 ; uložit třetí parametr metody na zásobník 3: iand ; provést první vyžadovanou logickou operaci a uložit výsledek zpět na zásobník 4: ior ; provést druhou vyžadovanou logickou operaci a uložit výsledek zpět na zásobník 5: istore_3 ; uložit výsledek do lokální proměnné 6: iload_3 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 7: ireturn ; výskok z metody s předáním návratové hodnoty public static boolean vyraz6(boolean, boolean, boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: iload_1 ; uložit druhý parametr metody na zásobník 2: ior ; provést první vyžadovanou logickou operaci a uložit výsledek zpět na zásobník 3: iload_2 ; uložit třetí parametr metody na zásobník 4: iload_3 ; uložit čtvrtý parametr metody na zásobník 5: ior ; provést druhou vyžadovanou logickou operaci a uložit výsledek zpět na zásobník 6: iand ; provést třetí vyžadovanou logickou operaci a uložit výsledek zpět na zásobník 7: istore 4 ; uložit výsledek do lokální proměnné 9: iload 4 ; vložit hodnotu lokální proměnné (výsledek) na zásobník 11: ireturn ; výskok z metody s předáním návratové hodnoty
8. Překlad výrazů s relačními operátory
Výrazy s relačními operátory se překládají do značné míry stejným způsobem, jako logické výrazy, o čemž se ostatně přesvědčíme:
Demonstrační příklad Test4.java:
/** * Trida s nekolika jednoduchymi statickymi metodami * pro otestovani zakladnich vlastnosti bajtkodu JVM: * prekladu relacnich vyrazu. */ public class Test4 { public static boolean vyraz1(int x, int y) { boolean result = x < y; return result; } public static boolean vyraz2(int x, int y) { boolean result = x <= y; return result; } public static boolean vyraz3(int x, int y) { boolean result = x == y; return result; } public static boolean vyraz4(int x, int y) { boolean result = x != y; return result; } public static boolean vyraz5(int x, int y) { boolean result = x >= y; return result; } public static boolean vyraz6(int x, int y) { boolean result = x > y; return result; } /** * Vse je nutne otestovat. */ public static void main(String[] args) { System.out.println(vyraz1(1, 2)); System.out.println(vyraz2(1, 2)); System.out.println(vyraz3(1, 2)); System.out.println(vyraz4(1, 2)); System.out.println(vyraz5(1, 2)); System.out.println(vyraz6(1, 2)); } }
Demonstrační příklad Test4.lua:
-- -- Modul s nekolika jednoduchymi funkcemi -- pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua -- prekladu relacnich vyrazu. -- function vyraz1(x, y) local result = x < y return result end function vyraz2(x, y) local result = x <= y return result end function vyraz3(x, y) local result = x == y return result end function vyraz4(x, y) local result = x ~= y return result end function vyraz5(x, y, z) local result = x >= y return result end function vyraz6(x, y, z, w) local result = x > y return result end -- -- Vse je nutne otestovat. -- function main() print(vyraz1(1, 2)) print(vyraz2(1, 2)) print(vyraz3(1, 2)) print(vyraz4(1, 2)) print(vyraz5(1, 2)) print(vyraz6(1, 2)) end main()
Demonstrační příklad Test4.py:
# # Modul s nekolika jednoduchymi funkcemi # pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua # prekladu relacnich vyrazu. # def vyraz1(x, y): result = x <= y return result def vyraz2(x, y): result = x < y return result def vyraz3(x, y): result = x == y return result def vyraz4(x, y): result = x != y return result def vyraz5(x, y): result = x >= y return result def vyraz6(x, y): result = x > y return result # # Vse je nutne otestovat. # def main(): print(vyraz1(1, 2)) print(vyraz2(1, 2)) print(vyraz3(1, 2)) print(vyraz4(1, 2)) print(vyraz5(1, 2)) print(vyraz6(1, 2)) def disassemble(): from dis import dis print("\nvyraz1:") dis(vyraz1) print("\nvyraz2:") dis(vyraz2) print("\nvyraz3:") dis(vyraz3) print("\nvyraz4:") dis(vyraz4) print("\nvyraz5:") dis(vyraz5) print("\nvyraz6:") dis(vyraz6) main() disassemble()
Přeložený bajtkód demonstračního příkladu Test4.java:
Bajtkód JVM se v tomto případě opět neobejde bez skoků:
public static boolean vyraz1(int, int); Code: 0: iload_0 1: iload_1 2: if_icmpge 9 5: iconst_1 6: goto 10 9: iconst_0 10: istore_2 11: iload_2 12: ireturn public static boolean vyraz2(int, int); Code: 0: iload_0 1: iload_1 2: if_icmpgt 9 5: iconst_1 6: goto 10 9: iconst_0 10: istore_2 11: iload_2 12: ireturn public static boolean vyraz3(int, int); Code: 0: iload_0 1: iload_1 2: if_icmpne 9 5: iconst_1 6: goto 10 9: iconst_0 10: istore_2 11: iload_2 12: ireturn public static boolean vyraz4(int, int); Code: 0: iload_0 1: iload_1 2: if_icmpeq 9 5: iconst_1 6: goto 10 9: iconst_0 10: istore_2 11: iload_2 12: ireturn public static boolean vyraz5(int, int); Code: 0: iload_0 1: iload_1 2: if_icmplt 9 5: iconst_1 6: goto 10 9: iconst_0 10: istore_2 11: iload_2 12: ireturn public static boolean vyraz6(int, int); Code: 0: iload_0 1: iload_1 2: if_icmple 9 5: iconst_1 6: goto 10 9: iconst_0 10: istore_2 11: iload_2 12: ireturn
Přeložený bajtkód demonstračního příkladu Test4.lua:
V bajtkódu jazyka Lua je nutné používat skoky, na rozdíl od dále ukázaného bajtkódu Pythonu:
function <Test4.lua:7,10> (6 instructions at 0x995dc88) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [8] LT 1 0 1 2 [8] JMP 0 1 ; to 4 3 [8] LOADBOOL 2 0 1 4 [8] LOADBOOL 2 1 0 5 [9] RETURN 2 2 6 [10] RETURN 0 1 function <Test4.lua:12,15> (6 instructions at 0x995df48) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [13] LE 1 0 1 2 [13] JMP 0 1 ; to 4 3 [13] LOADBOOL 2 0 1 4 [13] LOADBOOL 2 1 0 5 [14] RETURN 2 2 6 [15] RETURN 0 1 function <Test4.lua:17,20> (6 instructions at 0x995e148) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [18] EQ 1 0 1 2 [18] JMP 0 1 ; to 4 3 [18] LOADBOOL 2 0 1 4 [18] LOADBOOL 2 1 0 5 [19] RETURN 2 2 6 [20] RETURN 0 1 function <Test4.lua:22,25> (6 instructions at 0x995def0) 2 params, 3 slots, 0 upvalues, 3 locals, 0 constants, 0 functions 1 [23] EQ 0 0 1 2 [23] JMP 0 1 ; to 4 3 [23] LOADBOOL 2 0 1 4 [23] LOADBOOL 2 1 0 5 [24] RETURN 2 2 6 [25] RETURN 0 1 function <Test4.lua:27,30> (6 instructions at 0x995de00) 3 params, 4 slots, 0 upvalues, 4 locals, 0 constants, 0 functions 1 [28] LE 1 1 0 2 [28] JMP 0 1 ; to 4 3 [28] LOADBOOL 3 0 1 4 [28] LOADBOOL 3 1 0 5 [29] RETURN 3 2 6 [30] RETURN 0 1 function <Test4.lua:32,35> (6 instructions at 0x995e508) 4 params, 5 slots, 0 upvalues, 5 locals, 0 constants, 0 functions 1 [33] LT 1 1 0 2 [33] JMP 0 1 ; to 4 3 [33] LOADBOOL 4 0 1 4 [33] LOADBOOL 4 1 0 5 [34] RETURN 4 2 6 [35] RETURN 0 1
Přeložený bajtkód demonstračního příkladu Test4.py:
Python VM používá přímočarý způsob práce s relačními operátory, což je názorně vidět z bajtkódu:
vyraz1: 8 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 COMPARE_OP 1 (<=) 9 STORE_FAST 2 (result) 9 12 LOAD_FAST 2 (result) 15 RETURN_VALUE vyraz2: 12 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 COMPARE_OP 0 (<) 9 STORE_FAST 2 (result) 13 12 LOAD_FAST 2 (result) 15 RETURN_VALUE vyraz3: 16 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 COMPARE_OP 2 (==) 9 STORE_FAST 2 (result) 17 12 LOAD_FAST 2 (result) 15 RETURN_VALUE vyraz4: 20 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 COMPARE_OP 3 (!=) 9 STORE_FAST 2 (result) 21 12 LOAD_FAST 2 (result) 15 RETURN_VALUE vyraz5: 24 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 COMPARE_OP 5 (>=) 9 STORE_FAST 2 (result) 25 12 LOAD_FAST 2 (result) 15 RETURN_VALUE vyraz6: 28 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 COMPARE_OP 4 (>) 9 STORE_FAST 2 (result) 29 12 LOAD_FAST 2 (result) 15 RETURN_VALUE
9. Překlad řídicí struktury typu if-then
Nyní se již konečně dostáváme k mnohem zajímavějšímu tématu – k podmíněným skokům, kterými jsou realizovány strukturované příkazy (rozeskoky) typu if-then a samozřejmě i úplné rozhodovací konstrukce typu if-then-else. V instrukčním kódu virtuálního stroje jazyka Java je k dispozici poměrně velké množství typů různých podmíněných skoků. V této kapitole si popíšeme skoky, které se provedou resp. neprovedou na základě testu hodnoty jediného operandu, který je uložen na vrcholu zásobníku operandů (TOS) a je ve zdrojovém kódu typu Boolean. Ve všech případech se přitom po překladu tento operand chápe jako operand typu int, který je po provedení testu ze zásobníku operandů odstraněn (samozřejmě nezávisle na tom, jak test ve skutečnosti dopadl). Instrukce podmíněného skoku nejdříve na základě operačního kódu instrukce zjistí, zda je operand nulový, nenulový, větší než nula, menší než nula, větší nebo roven nule popř. naopak menší nebo roven nule. Pokud je daná podmínka splněna, je proveden skok na šestnáctibitovou lokální adresu uloženou za operačním kódem instrukce; v opačném případě se pokračuje v provádění instrukce uložené ihned za podmíněným skokem.
Demonstrační příklad Test5.java:
/** * Trida s nekolika jednoduchymi statickymi metodami * pro otestovani zakladnich vlastnosti bajtkodu JVM: * prekladu programove struktury typu if-then */ public class Test5 { public static int prikaz1(boolean x) { if (x) { return 10; } return 20; } public static int prikaz2(boolean x, boolean y) { if (x) { if (y) { return 10; } } return 20; } /** * Vse je nutne otestovat. */ public static void main(String[] args) { System.out.println(prikaz1(true)); System.out.println(prikaz1(false)); System.out.println(prikaz2(true, true)); System.out.println(prikaz2(true, false)); System.out.println(prikaz2(false, true)); System.out.println(prikaz2(false, false)); } }
Demonstrační příklad Test5.lua:
Ekvivalentní příklad vytvořený v jazyce Lua by vypadal následovně:
-- -- Modul s nekolika jednoduchymi funkcemi -- pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua -- prekladu programove struktury typu if-then. -- function prikaz1(x) if x then return 10 end return 20 end function prikaz2(x, y) if x then if y then return 10 end end return 20 end -- -- Vse je nutne otestovat. -- function main() print(prikaz1(true)) print(prikaz1(false)) print(prikaz2(true, true)) print(prikaz2(true, false)) print(prikaz2(false, true)) print(prikaz2(false, false)) end main()
Demonstrační příklad Test5.py:
Program v Pythonu se v tomto případě do značné míry podobá příkladu v Lue:
# # Modul s nekolika jednoduchymi funkcemi # pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua # prekladu programove struktury typu if-then. # def prikaz1(x): if x: return 10 return 20 def prikaz2(x, y): if x: if y: return 10 return 20 # # Vse je nutne otestovat. # def main(): print(prikaz1(True)) print(prikaz1(False)) print(prikaz2(True, True)) print(prikaz2(True, False)) print(prikaz2(False, True)) print(prikaz2(False, False)) def disassemble(): from dis import dis print("\nprikaz1:") dis(prikaz1) print("\nprikaz2:") dis(prikaz2) main() disassemble()
Přeložený bajtkód demonstračního příkladu Test5.java:
Bajtkód JVM je v případě demonstračního příkladu Test5 velmi přímočarý a vlastně i jednodušší, než „pouhé“ vyhodnocení logického výrazu:
public static int prikaz1(boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifeq 7 ; podmíněný skok 4: bipush 10 ; návratová hodnota na zásobník 6: ireturn ; výskok z metody s předáním návratové hodnoty 7: bipush 20 ; návratová hodnota na zásobník 9: ireturn ; výskok z metody s předáním návratové hodnoty public static int prikaz2(boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifeq 11 ; podmíněný skok 4: iload_1 ; uložit druhý parametr metody na zásobník 5: ifeq 11 ; podmíněný skok 8: bipush 10 ; návratová hodnota na zásobník 10: ireturn ; výskok z metody s předáním návratové hodnoty 11: bipush 20 ; návratová hodnota na zásobník 13: ireturn ; výskok z metody s předáním návratové hodnoty
Přeložený bajtkód demonstračního příkladu Test5.lua:
Bajtkód Lua VM je překvapivě velmi podobný bajtkódu JVM:
function <Test5.lua:7,12> (7 instructions at 0x99b8c88) 1 param, 2 slots, 0 upvalues, 1 local, 2 constants, 0 functions 1 [8] TEST 0 0 ; test hodnoty prvního parametru funkce 2 [8] JMP 0 2 ; to 5 3 [9] LOADK 1 -1 ; 10 ; návratová hodnota 4 [9] RETURN 1 2 5 [11] LOADK 1 -2 ; 20 ; návratová hodnota 6 [11] RETURN 1 2 7 [12] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce function <Test5.lua:14,21> (9 instructions at 0x99b8f28) 2 params, 3 slots, 0 upvalues, 2 locals, 2 constants, 0 functions 1 [15] TEST 0 0 ; test hodnoty prvního parametru funkce 2 [15] JMP 0 4 ; to 7 3 [16] TEST 1 0 ; test hodnoty druhého parametru funkce 4 [16] JMP 0 2 ; to 7 5 [17] LOADK 2 -1 ; 10 ; návratová hodnota 6 [17] RETURN 2 2 7 [20] LOADK 2 -2 ; 20 ; návratová hodnota 8 [20] RETURN 2 2 9 [21] RETURN 0 1 ; automaticky vkládaná instrukce návratu z funkce
Přeložený bajtkód demonstračního příkladu Test5.py:
Podobně je s využitím instrukcí podmínky+skoku proveden překlad do bajtkódu virtuálního stroje jazyka Python:
prikaz1: 8 0 LOAD_FAST 0 (x) 3 JUMP_IF_FALSE 5 (to 11) 6 POP_TOP 9 7 LOAD_CONST 1 (10) 10 RETURN_VALUE >> 11 POP_TOP 10 12 LOAD_CONST 2 (20) 15 RETURN_VALUE prikaz2: 13 0 LOAD_FAST 0 (x) 3 JUMP_IF_FALSE 16 (to 22) 6 POP_TOP 14 7 LOAD_FAST 1 (y) 10 JUMP_IF_FALSE 5 (to 18) 13 POP_TOP 15 14 LOAD_CONST 1 (10) 17 RETURN_VALUE >> 18 POP_TOP 19 JUMP_FORWARD 1 (to 23) >> 22 POP_TOP 16 >> 23 LOAD_CONST 2 (20) 26 RETURN_VALUE
10. Překlad řídicí struktury typu if-then-else
Úplná programová konstrukce if-then-else vznikne z neúplné konstrukce typu if-then doplnění programové větve else, což je samozřejmě podporováno ve všech třech programovacích jazycích, jejichž bajtkódy se v dnešním článku zaobíráme.
Demonstrační příklad Test6.java:
/** * Trida s nekolika jednoduchymi statickymi metodami * pro otestovani zakladnich vlastnosti bajtkodu JVM: * prekladu programove struktury typu if-then-else */ public class Test6 { public static int prikaz1(boolean x) { if (x) { return 10; } else { return 20; } } public static int prikaz2(boolean x, boolean y) { if (x) { if (y) { return 10; } else { return 20; } } else { return 30; } } /** * Vse je nutne otestovat. */ public static void main(String[] args) { System.out.println(prikaz1(true)); System.out.println(prikaz2(true, true)); } }
Demonstrační příklad Test6.lua:
Ekvivalentní program v Lue je velmi podobný Javovské variantě:
-- -- Modul s nekolika jednoduchymi funkcemi -- pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua -- prekladu programove struktury typu if-then-else. -- function prikaz1(x) if x then return 10 else return 20 end end function prikaz2(x, y) if x then if y then return 10 else return 20 end else return 30 end end -- -- Vse je nutne otestovat. -- function main() print(prikaz1(true)) print(prikaz1(false)) print(prikaz2(true, true)) print(prikaz2(true, false)) print(prikaz2(false, true)) print(prikaz2(false, false)) end main()
Demonstrační příklad Test6.py:
To stejné platí pro podobný program naprogramovaný v Pythonu:
# # Modul s nekolika jednoduchymi funkcemi # pro otestovani zakladnich vlastnosti bajtkodu jazyka Lua # prekladu programove struktury typu if-then-else. # def prikaz1(x): if x: return 10 else: return 20 def prikaz2(x, y): if x: if y: return 10 else: return 20 else: return 30 # # Vse je nutne otestovat. # def main(): print(prikaz1(True)) print(prikaz1(False)) print(prikaz2(True, True)) print(prikaz2(True, False)) print(prikaz2(False, True)) print(prikaz2(False, False)) def disassemble(): from dis import dis print("\nprikaz1:") dis(prikaz1) print("\nprikaz2:") dis(prikaz2) main() disassemble()
Přeložený bajtkód demonstračního příkladu Test6.java:
Konstrukce if-then-else je v případě JVM přeložena do dvojice instrukcí podmíněný skok+nepodmíněný skok:
public static int prikaz1(boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifeq 7 ; podmíněný skok 4: bipush 10 ; návratová hodnota na zásobník 6: ireturn ; výskok z metody s předáním návratové hodnoty 7: bipush 20 ; návratová hodnota na zásobník 9: ireturn ; výskok z metody s předáním návratové hodnoty public static int prikaz2(boolean, boolean); Code: 0: iload_0 ; uložit první parametr metody na zásobník 1: ifeq 14 ; podmíněný skok 4: iload_1 ; uložit druhý parametr metody na zásobník 5: ifeq 11 ; podmíněný skok 8: bipush 10 ; návratová hodnota na zásobník 10: ireturn ; výskok z metody s předáním návratové hodnoty 11: bipush 20 ; návratová hodnota na zásobník 13: ireturn ; výskok z metody s předáním návratové hodnoty 14: bipush 30 ; návratová hodnota na zásobník 16: ireturn ; výskok z metody s předáním návratové hodnoty
Přeložený bajtkód demonstračního příkladu Test6.lua:
Podobně je tomu i v případě bajtkódu Lua VM:
function <Test6.lua:7,13> (8 instructions at 0x97ccc88) 1 param, 2 slots, 0 upvalues, 1 local, 2 constants, 0 functions 1 [8] TEST 0 0 2 [8] JMP 0 3 ; to 6 3 [9] LOADK 1 -1 ; 10 4 [9] RETURN 1 2 5 [9] JMP 0 2 ; to 8 6 [11] LOADK 1 -2 ; 20 7 [11] RETURN 1 2 8 [13] RETURN 0 1 function <Test6.lua:15,25> (13 instructions at 0x97ccff8) 2 params, 3 slots, 0 upvalues, 2 locals, 3 constants, 0 functions 1 [16] TEST 0 0 2 [16] JMP 0 8 ; to 11 3 [17] TEST 1 0 4 [17] JMP 0 3 ; to 8 5 [18] LOADK 2 -1 ; 10 6 [18] RETURN 2 2 7 [18] JMP 0 5 ; to 13 8 [20] LOADK 2 -2 ; 20 9 [20] RETURN 2 2 10 [21] JMP 0 2 ; to 13 11 [23] LOADK 2 -3 ; 30 12 [23] RETURN 2 2 13 [25] RETURN 0 1
Přeložený bajtkód demonstračního příkladu Test6.py:
Pro variantu stejné aplikace napsané v Pythonu vypadá bajtkód následovně (zde stojí za zmínku instrukce POP_TOP pro odstranění položky z vrcholu zásobníku operandů):
prikaz1: 8 0 LOAD_FAST 0 (x) 3 JUMP_IF_FALSE 5 (to 11) 6 POP_TOP 9 7 LOAD_CONST 1 (10) 10 RETURN_VALUE >> 11 POP_TOP 11 12 LOAD_CONST 2 (20) 15 RETURN_VALUE 16 LOAD_CONST 0 (None) 19 RETURN_VALUE prikaz2: 14 0 LOAD_FAST 0 (x) 3 JUMP_IF_FALSE 20 (to 26) 6 POP_TOP 15 7 LOAD_FAST 1 (y) 10 JUMP_IF_FALSE 5 (to 18) 13 POP_TOP 16 14 LOAD_CONST 1 (10) 17 RETURN_VALUE >> 18 POP_TOP 18 19 LOAD_CONST 2 (20) 22 RETURN_VALUE 23 JUMP_FORWARD 5 (to 31) >> 26 POP_TOP 20 27 LOAD_CONST 3 (30) 30 RETURN_VALUE >> 31 LOAD_CONST 0 (None) 34 RETURN_VALUE
11. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů
Všech pět dnes popsaných demonstračních příkladů (naprogramovaných v Javě, Lue i Pythonu) bylo uloženo do Mercurial repositáře umístěného na adrese http://icedtea.classpath.org/people/ptisnovs/jvm-tools/. Odkazy na prozatím poslední verze těchto příkladů naleznete v tabulce pod tímto odstavcem:
12. Odkazy na Internetu
- Parrot
http://www.parrot.org/ - Parrot languages
http://www.parrot.org/languages - Parrot Primer
http://docs.parrot.org/parrot/latest/html/docs/intro.pod.html - Parrot Opcodes
http://docs.parrot.org/parrot/latest/html/ops.html - Parrot VM
http://en.wikibooks.org/wiki/Parrot_Virtual_Machine - Parrot Assembly Language
http://www.perl6.org/archive/pdd/pdd06_pasm.html - Parrot Reference: Chapter 11 – Perl 6 and Parrot Essentials
http://oreilly.com/perl/excerpts/perl-6-and-parrot-essentials/parrot-reference.html - Python Bytecode: Fun With Dis
http://akaptur.github.io/blog/2013/08/14/python-bytecode-fun-with-dis/ - Python's Innards: Hello, ceval.c!
http://tech.blog.aknin.name/category/my-projects/pythons-innards/ - Byterun
https://github.com/nedbat/byterun - Python Byte Code Instructions
http://document.ihg.uni-duisburg.de/Documentation/Python/lib/node56.html - Python Byte Code Instructions
https://docs.python.org/3.2/library/dis.html#python-bytecode-instructions - Programovací jazyk Lua
http://palmknihy.cz/web/kniha/programovaci-jazyk-lua-12651.htm - Lua 5.2 sources
http://www.lua.org/source/5.2/ - Lua 5.2 sources – lopcodes.h
http://www.lua.org/source/5.2/lopcodes.h.html - Lua 5.2 sources – lopcodes.c
http://www.lua.org/source/5.2/lopcodes.c.html - dis – Python module
https://docs.python.org/2/library/dis.html - Comparison of Python virtual machines
http://polishlinux.org/apps/cli/comparison-of-python-virtual-machines/ - O-code
http://en.wikipedia.org/wiki/O-code_machine - BCPL
http://en.wikipedia.org/wiki/BCPL - The BCPL Cintcode System and Cintpos User Guide by Martin Richards
http://www.cl.cam.ac.uk/users/mr/bcplman.pdf - Bootstrapping the BCPL Compiler using INTCODE
http://www.gtoal.com/languages/bcpl/amiga/bcpl/booting.txt - p-code machine
http://en.wikipedia.org/wiki/P-code_machine - ucsd-psystem-vm 0.11 (a portable virtual machine for the UCSD p-System)
http://ucsd-psystem-vm.sourceforge.net/ - Introduction to Smalltalk bytecodes
http://marianopeck.wordpress.com/2011/05/21/introduction-to-smalltalk-bytecodes/ - Audio File Formats.
http://sox.sourceforge.net/AudioFormats-11.html - TestSounds.com: pure digital sounds to test your audio
http://www.testsounds.com/ - Test Tones (20hz – 20khz)
http://mdf1.tripod.com/test-tones.html - WAV (Wikipedia)
http://en.wikipedia.org/wiki/WAV - WAVE PCM soundfile format
https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - Audio Interchange File Format
http://en.wikipedia.org/wiki/Aiff - Musical Instrument Digital Interface,
http://en.wikipedia.org/wiki/Musical_Instrument_Digital_Interface - A MIDI Pedalboard Encode,
http://www.pykett.org.uk/a_midi_pedalboard_encoder.htm - MIDI Note Number, Frequency Table,
http://tonalsoft.com/pub/news/pitch-bend.aspx - Note names, MIDI numbers and frequencies,
http://www.phys.unsw.edu.au/jw/notes.html - The MIDI Specification,
http://www.gweep.net/~prefect/eng/reference/protocol/midispec.html - Essentials of the MIDI protocol,
http://ccrma.stanford.edu/~craig/articles/linuxmidi/misc/essenmidi.html - General MIDI,
http://en.wikipedia.org/wiki/General_MIDI - Obecné MIDI (General MIDI),
http://www-kiv.zcu.cz/~herout/html_sbo/midi/5.html - Custom Chips: Paula
http://www.amiga-hardware.com/showhardware.cgi?HARDID=1460 - Big Book of Amiga Hardware
http://www.amiga-resistance.info/bboahfaq/ - Amiga Hardware Database
http://amiga.resource.cx/ - ExoticA
http://www.exotica.org.uk/wiki/Main_Page - The absolute basics of Amiga audio
http://www.sufo.estates.co.uk/amiga/amimus.html - Wikipedia: Tracker
http://en.wikipedia.org/wiki/Tracker - Wikipedia: Trackers
http://en.wikipedia.org/wiki/Trackers - Ultimate Soundtracker
http://en.wikipedia.org/wiki/Ultimate_Soundtracker - Protracker
http://en.wikipedia.org/wiki/ProTracker - Impulse Tracker
http://en.wikipedia.org/wiki/Impulse_Tracker - Scream Tracker
http://en.wikipedia.org/wiki/ScreamTracker - MikMod for Java
http://jmikmod.berlios.de/ - List of audio trackers
http://en.wikipedia.org/wiki/List_of_audio_trackers - Wikipedia: Module File
http://en.wikipedia.org/wiki/Module_file - Wikipedia: Chiptune
http://en.wikipedia.org/wiki/Chiptune - SDL_mixer 2.0
http://www.libsdl.org/projects/SDL_mixer/ - SDLJava: package sdljava.ttf
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/package-summary.html#package_description - SDLJava: class sdljava.ttf.SDLTTF
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/SDLTTF.html - SDLJava: class sdljava.ttf.SDLTrueTypeFont
http://sdljava.sourceforge.net/docs/api/sdljava/ttf/SDLTrueTypeFont.html - SDL_ttf Documentation
http://www.libsdl.org/projects/SDL_ttf/docs/ - SDL_ttf 2.0 (není prozatím součástí SDLJava)
http://www.libsdl.org/projects/SDL_ttf/ - SDL_ttf doc
http://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_frame.html - SDL 1.2 Documentation: SDL_Surface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html - SDL 1.2 Documentation: SDL_PixelFormat
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html - SDL 1.2 Documentation: SDL_LockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html - SDL 1.2 Documentation: SDL_UnlockSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html - SDL 1.2 Documentation: SDL_LoadBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html - SDL 1.2 Documentation: SDL_SaveBMP
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html - SDL 1.2 Documentation: SDL_BlitSurface
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html - SDL 1.2 Documentation: SDL_VideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html - SDL 1.2 Documentation: SDL_GetVideoInfo
http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html - glDrawArrays
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArrays.xml - glDrawElements
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElements.xml - glDrawArraysInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawArraysInstanced.xml - glDrawElementsInstanced
http://www.opengl.org/sdk/docs/man4/xhtml/glDrawElementsInstanced.xml - Root.cz: Seriál Grafická knihovna OpenGL
http://www.root.cz/serialy/graficka-knihovna-opengl/ - Root.cz: Seriál Tvorba přenositelných grafických aplikací využívajících knihovnu GLUT
http://www.root.cz/serialy/tvorba-prenositelnych-grafickych-aplikaci-vyuzivajicich-knihovnu-glut/ - Best Practices for Working with Vertex Data
https://developer.apple.com/library/ios/documentation/3ddrawing/conceptual/opengles_programmingguide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html - Class BufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/image/BufferStrategy.html - Class Graphics
http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Graphics.html - Double Buffering and Page Flipping
http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html - BufferStrategy and BufferCapabilities
http://docs.oracle.com/javase/tutorial/extra/fullscreen/bufferstrategy.html - Java:Tutorials:Double Buffering
http://content.gpwiki.org/index.php/Java:Tutorials:Double_Buffering - Double buffer in standard Java AWT
http://www.codeproject.com/Articles/2136/Double-buffer-in-standard-Java-AWT - Java 2D: Hardware Accelerating – Part 1 – Volatile Images
http://www.javalobby.org/forums/thread.jspa?threadID=16840&tstart=0 - Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
http://www.javalobby.org/java/forums/t16867.html - How does paintComponent work?
http://stackoverflow.com/questions/15544549/how-does-paintcomponent-work - A Swing Architecture Overview
http://www.oracle.com/technetwork/java/architecture-142923.html - Class javax.swing.JComponent
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html - Class java.awt.Component
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html - Class java.awt.Component.BltBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.BltBufferStrategy.html - Class java.awt.Component.FlipBufferStrategy
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.FlipBufferStrategy.html - Metoda java.awt.Component.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/java/awt/Component.html#isDoubleBuffered() - Metoda javax.swing.JComponent.isDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#isDoubleBuffered() - Metoda javax.swing.JComponent.setDoubleBuffered()
http://docs.oracle.com/javase/6/docs/api/javax/swing/JComponent.html#setDoubleBuffered(boolean) - Javadoc – třída GraphicsDevice
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsDevice.html - Javadoc – třída GraphicsEnvironment
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsEnvironment.html - Javadoc – třída GraphicsConfiguration
http://docs.oracle.com/javase/7/docs/api/java/awt/GraphicsConfiguration.html - Javadoc – třída DisplayMode
http://docs.oracle.com/javase/7/docs/api/java/awt/DisplayMode.html - Lesson: Full-Screen Exclusive Mode API
http://docs.oracle.com/javase/tutorial/extra/fullscreen/ - Full-Screen Exclusive Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/exclusivemode.html - Display Mode
http://docs.oracle.com/javase/tutorial/extra/fullscreen/displaymode.html - Using the Full-Screen Exclusive Mode API in Java
http://www.developer.com/java/other/article.php/3609776/Using-the-Full-Screen-Exclusive-Mode-API-in-Java.htm - Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
http://www.mobilefish.com/tutorials/java/java_quickguide_jvm_instruction_set.html - The JVM Instruction Set
http://mpdeboer.home.xs4all.nl/scriptie/node14.html - MultiMedia eXtensions
http://softpixel.com/~cwright/programming/simd/mmx.phpi - SSE (Streaming SIMD Extentions)
http://www.songho.ca/misc/sse/sse.html - Timothy A. Chagnon: SSE and SSE2
http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf - Intel corporation: Extending the Worldr's Most Popular Processor Architecture
http://download.intel.com/technology/architecture/new-instructions-paper.pdf - SIMD architectures:
http://arstechnica.com/old/content/2000/03/simd.ars/ - GC safe-point (or safepoint) and safe-region
http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html - Safepoints in HotSpot JVM
http://blog.ragozin.info/2012/10/safepoints-in-hotspot-jvm.html - Java theory and practice: Synchronization optimizations in Mustang
http://www.ibm.com/developerworks/java/library/j-jtp10185/ - How to build hsdis
http://hg.openjdk.java.net/jdk7/hotspot/hotspot/file/tip/src/share/tools/hsdis/README - Java SE 6 Performance White Paper
http://www.oracle.com/technetwork/java/6-performance-137236.html - Lukas Stadler's Blog
http://classparser.blogspot.cz/2010/03/hsdis-i386dll.html - How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
http://dropzone.nfshost.com/hsdis.htm - PrintAssembly
https://wikis.oracle.com/display/HotSpotInternals/PrintAssembly - The Java Virtual Machine Specification: 3.14. Synchronization
http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.14 - The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4 - The Java Virtual Machine Specification: 17.4. Memory Model
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4 - The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.7 - Open Source ByteCode Libraries in Java
http://java-source.net/open-source/bytecode-libraries - ASM Home page
http://asm.ow2.org/ - Seznam nástrojů využívajících projekt ASM
http://asm.ow2.org/users.html - ObjectWeb ASM (Wikipedia)
http://en.wikipedia.org/wiki/ObjectWeb_ASM - Java Bytecode BCEL vs ASM
http://james.onegoodcookie.com/2005/10/26/java-bytecode-bcel-vs-asm/ - BCEL Home page
http://commons.apache.org/bcel/ - Byte Code Engineering Library (před verzí 5.0)
http://bcel.sourceforge.net/ - Byte Code Engineering Library (verze >= 5.0)
http://commons.apache.org/proper/commons-bcel/ - BCEL Manual
http://commons.apache.org/bcel/manual.html - Byte Code Engineering Library (Wikipedia)
http://en.wikipedia.org/wiki/BCEL - BCEL Tutorial
http://www.smfsupport.com/support/java/bcel-tutorial!/ - Bytecode Engineering
http://book.chinaunix.net/special/ebook/Core_Java2_Volume2AF/0131118269/ch13lev1sec6.html - Bytecode Outline plugin for Eclipse (screenshoty + info)
http://asm.ow2.org/eclipse/index.html - Javassist
http://www.jboss.org/javassist/ - Byteman
http://www.jboss.org/byteman - Java programming dynamics, Part 7: Bytecode engineering with BCEL
http://www.ibm.com/developerworks/java/library/j-dyn0414/ - The JavaTM Virtual Machine Specification, Second Edition
http://java.sun.com/docs/books/jvms/second_edition/html/VMSpecTOC.doc.html - The class File Format
http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html - javap – The Java Class File Disassembler
http://docs.oracle.com/javase/1.4.2/docs/tooldocs/windows/javap.html - javap-java-1.6.0-openjdk(1) – Linux man page
http://linux.die.net/man/1/javap-java-1.6.0-openjdk - Using javap
http://www.idevelopment.info/data/Programming/java/miscellaneous_java/Using_javap.html - Examine class files with the javap command
http://www.techrepublic.com/article/examine-class-files-with-the-javap-command/5815354 - aspectj (Eclipse)
http://www.eclipse.org/aspectj/ - Aspect-oriented programming (Wikipedia)
http://en.wikipedia.org/wiki/Aspect_oriented_programming - AspectJ (Wikipedia)
http://en.wikipedia.org/wiki/AspectJ - EMMA: a free Java code coverage tool
http://emma.sourceforge.net/ - Cobertura
http://cobertura.sourceforge.net/ - jclasslib bytecode viewer
http://www.ej-technologies.com/products/jclasslib/overview.html