Pohled pod kapotu JVM – překlad do bajtkódů JVM, Lua VM a Python VM

Pavel Tišnovský 27. 5. 2014

V dnešní části seriálu o programovacím jazyku Java i o virtuálním stroji Javy budeme pokračovat v porovnávání vlastností bajtkódů JVM, Python VM i Lua VM, a to na několika demonstračních příkladech. Kromě toho si však popíšeme i základní vlastnosti dalšího zajímavého virtuálního stroje nazvaného Parrot.

Obsah

1. Pohled pod kapotu JVM – překlad do bajtkódů JVM, Lua VM a Python VM

2. Virtuální stroj Parrot

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ů

12. Odkazy na Internetu

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 PIRPASM 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 iandior:

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:

widgety

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.or­g/people/ptisnovs/jvm-tools/. Odkazy na prozatím poslední verze těchto příkladů naleznete v tabulce pod tímto odstavcem:

# Zdrojový kód Umístění
1 Test2.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/84bb68ad370b/by­tecode/Java/Test2.java
2 Test2.lua http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/4306edda5d9d/by­tecode/Lua/Test2.lua
3 Test2.py http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/a1f3b6f40b85/by­tecode/Python/Test2.py
     
4 Test3.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/84bb68ad370b/by­tecode/Java/Test3.java
5 Test3.lua http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/4306edda5d9d/by­tecode/Lua/Test3.lua
6 Test3.py http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/a1f3b6f40b85/by­tecode/Python/Test3.py
     
7 Test4.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/84bb68ad370b/by­tecode/Java/Test4.java
8 Test4.lua http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/4306edda5d9d/by­tecode/Lua/Test4.lua
9 Test4.py http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/a1f3b6f40b85/by­tecode/Python/Test4.py
     
10 Test5.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/84bb68ad370b/by­tecode/Java/Test5.java
11 Test5.lua http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/4306edda5d9d/by­tecode/Lua/Test5.lua
12 Test5.py http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/a1f3b6f40b85/by­tecode/Python/Test5.py
     
13 Test6.java http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/84bb68ad370b/by­tecode/Java/Test6.java
14 Test6.lua http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/4306edda5d9d/by­tecode/Lua/Test6.lua
15 Test6.py http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/file/a1f3b6f40b85/by­tecode/Python/Test6.py

12. Odkazy na Internetu

  1. Parrot
    http://www.parrot.org/
  2. Parrot languages
    http://www.parrot.org/languages
  3. Parrot Primer
    http://docs.parrot.org/pa­rrot/latest/html/docs/intro­.pod.html
  4. Parrot Opcodes
    http://docs.parrot.org/pa­rrot/latest/html/ops.html
  5. Parrot VM
    http://en.wikibooks.org/wi­ki/Parrot_Virtual_Machine
  6. Parrot Assembly Language
    http://www.perl6.org/archi­ve/pdd/pdd06_pasm.html
  7. Parrot Reference: Chapter 11 – Perl 6 and Parrot Essentials
    http://oreilly.com/perl/excerpts/perl-6-and-parrot-essentials/parrot-reference.html
  8. Python Bytecode: Fun With Dis
    http://akaptur.github.io/blog/2013/08/14/pyt­hon-bytecode-fun-with-dis/
  9. Python's Innards: Hello, ceval.c!
    http://tech.blog.aknin.na­me/category/my-projects/pythons-innards/
  10. Byterun
    https://github.com/nedbat/byterun
  11. Python Byte Code Instructions
    http://document.ihg.uni-duisburg.de/Documentation/Pyt­hon/lib/node56.html
  12. Python Byte Code Instructions
    https://docs.python.org/3­.2/library/dis.html#python-bytecode-instructions
  13. Programovací jazyk Lua
    http://palmknihy.cz/web/kni­ha/programovaci-jazyk-lua-12651.htm
  14. Lua 5.2 sources
    http://www.lua.org/source/5.2/
  15. Lua 5.2 sources – lopcodes.h
    http://www.lua.org/source/5­.2/lopcodes.h.html
  16. Lua 5.2 sources – lopcodes.c
    http://www.lua.org/source/5­.2/lopcodes.c.html
  17. dis – Python module
    https://docs.python.org/2/li­brary/dis.html
  18. Comparison of Python virtual machines
    http://polishlinux.org/ap­ps/cli/comparison-of-python-virtual-machines/
  19. O-code
    http://en.wikipedia.org/wiki/O-code_machine
  20. BCPL
    http://en.wikipedia.org/wiki/BCPL
  21. The BCPL Cintcode System and Cintpos User Guide by Martin Richards
    http://www.cl.cam.ac.uk/u­sers/mr/bcplman.pdf
  22. Bootstrapping the BCPL Compiler using INTCODE
    http://www.gtoal.com/langu­ages/bcpl/amiga/bcpl/bootin­g.txt
  23. p-code machine
    http://en.wikipedia.org/wiki/P-code_machine
  24. ucsd-psystem-vm 0.11 (a portable virtual machine for the UCSD p-System)
    http://ucsd-psystem-vm.sourceforge.net/
  25. Introduction to Smalltalk bytecodes
    http://marianopeck.wordpres­s.com/2011/05/21/introduc­tion-to-smalltalk-bytecodes/
  26. Audio File Formats.
    http://sox.sourceforge.net/Au­dioFormats-11.html
  27. TestSounds.com: pure digital sounds to test your audio
    http://www.testsounds.com/
  28. Test Tones (20hz – 20khz)
    http://mdf1.tripod.com/test-tones.html
  29. WAV (Wikipedia)
    http://en.wikipedia.org/wiki/WAV
  30. WAVE PCM soundfile format
    https://ccrma.stanford.edu/cou­rses/422/projects/WaveFor­mat/
  31. Audio Interchange File Format
    http://en.wikipedia.org/wiki/Aiff
  32. Musical Instrument Digital Interface,
    http://en.wikipedia.org/wi­ki/Musical_Instrument_Digi­tal_Interface
  33. A MIDI Pedalboard Encode,
    http://www.pykett.org.uk/a_mi­di_pedalboard_encoder.htm
  34. MIDI Note Number, Frequency Table,
    http://tonalsoft.com/pub/news/pitch-bend.aspx
  35. Note names, MIDI numbers and frequencies,
    http://www.phys.unsw.edu.au­/jw/notes.html
  36. The MIDI Specification,
    http://www.gweep.net/~pre­fect/eng/reference/protocol/mi­dispec.html
  37. Essentials of the MIDI protocol,
    http://ccrma.stanford.edu/~cra­ig/articles/linuxmidi/mis­c/essenmidi.html
  38. General MIDI,
    http://en.wikipedia.org/wi­ki/General_MIDI
  39. Obecné MIDI (General MIDI),
    http://www-kiv.zcu.cz/~herout/html_sbo/mi­di/5.html
  40. Custom Chips: Paula
    http://www.amiga-hardware.com/showhardware­.cgi?HARDID=1460
  41. Big Book of Amiga Hardware
    http://www.amiga-resistance.info/bboahfaq/
  42. Amiga Hardware Database
    http://amiga.resource.cx/
  43. ExoticA
    http://www.exotica.org.uk/wi­ki/Main_Page
  44. The absolute basics of Amiga audio
    http://www.sufo.estates.co­.uk/amiga/amimus.html
  45. Wikipedia: Tracker
    http://en.wikipedia.org/wiki/Tracker
  46. Wikipedia: Trackers
    http://en.wikipedia.org/wiki/Trackers
  47. Ultimate Soundtracker
    http://en.wikipedia.org/wi­ki/Ultimate_Soundtracker
  48. Protracker
    http://en.wikipedia.org/wi­ki/ProTracker
  49. Impulse Tracker
    http://en.wikipedia.org/wi­ki/Impulse_Tracker
  50. Scream Tracker
    http://en.wikipedia.org/wi­ki/ScreamTracker
  51. MikMod for Java
    http://jmikmod.berlios.de/
  52. List of audio trackers
    http://en.wikipedia.org/wi­ki/List_of_audio_trackers
  53. Wikipedia: Module File
    http://en.wikipedia.org/wi­ki/Module_file
  54. Wikipedia: Chiptune
    http://en.wikipedia.org/wiki/Chiptune
  55. SDL_mixer 2.0
    http://www.libsdl.org/pro­jects/SDL_mixer/
  56. SDLJava: package sdljava.ttf
    http://sdljava.sourceforge­.net/docs/api/sdljava/ttf/pac­kage-summary.html#package_description
  57. SDLJava: class sdljava.ttf.SDLTTF
    http://sdljava.sourceforge­.net/docs/api/sdljava/ttf/SDLTTF­.html
  58. SDLJava: class sdljava.ttf.SDLTrueTypeFont
    http://sdljava.sourceforge­.net/docs/api/sdljava/ttf/SDLTru­eTypeFont.html
  59. SDL_ttf Documentation
    http://www.libsdl.org/pro­jects/SDL_ttf/docs/
  60. SDL_ttf 2.0 (není prozatím součástí SDLJava)
    http://www.libsdl.org/pro­jects/SDL_ttf/
  61. SDL_ttf doc
    http://www.libsdl.org/pro­jects/SDL_ttf/docs/SDL_ttf_fra­me.html
  62. SDL 1.2 Documentation: SDL_Surface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsurface.html
  63. SDL 1.2 Documentation: SDL_PixelFormat
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlpixelformat.html
  64. SDL 1.2 Documentation: SDL_LockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdllocksurface.html
  65. SDL 1.2 Documentation: SDL_UnlockSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlunlocksurface.html
  66. SDL 1.2 Documentation: SDL_LoadBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlloadbmp.html
  67. SDL 1.2 Documentation: SDL_SaveBMP
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlsavebmp.html
  68. SDL 1.2 Documentation: SDL_BlitSurface
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlblitsurface.html
  69. SDL 1.2 Documentation: SDL_VideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlvideoinfo.html
  70. SDL 1.2 Documentation: SDL_GetVideoInfo
    http://www.libsdl.org/release/SDL-1.2.15/docs/html/sdlgetvideoinfo.html
  71. glDrawArrays
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArrays­.xml
  72. glDrawElements
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­ts.xml
  73. glDrawArraysInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawArraysIn­stanced.xml
  74. glDrawElementsInstanced
    http://www.opengl.org/sdk/doc­s/man4/xhtml/glDrawElemen­tsInstanced.xml
  75. Root.cz: Seriál Grafická knihovna OpenGL
    http://www.root.cz/serialy/graficka-knihovna-opengl/
  76. 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/
  77. Best Practices for Working with Vertex Data
    https://developer.apple.com/li­brary/ios/documentation/3ddra­wing/conceptual/opengles_pro­grammingguide/Techniquesfor­WorkingwithVertexData/Techni­quesforWorkingwithVertexDa­ta.html
  78. Class BufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/i­mage/BufferStrategy.html
  79. Class Graphics
    http://docs.oracle.com/ja­vase/1.5.0/docs/api/java/aw­t/Graphics.html
  80. Double Buffering and Page Flipping
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/doublebuf.html
  81. BufferStrategy and BufferCapabilities
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/bufferstrategy.html
  82. Java:Tutorials:Double Buffering
    http://content.gpwiki.org/in­dex.php/Java:Tutorials:Dou­ble_Buffering
  83. Double buffer in standard Java AWT
    http://www.codeproject.com/Ar­ticles/2136/Double-buffer-in-standard-Java-AWT
  84. Java 2D: Hardware Accelerating – Part 1 – Volatile Images
    http://www.javalobby.org/fo­rums/thread.jspa?threadID=16840&tstar­t=0
  85. Java 2D: Hardware Accelerating – Part 2 – Buffer Strategies
    http://www.javalobby.org/ja­va/forums/t16867.html
  86. How does paintComponent work?
    http://stackoverflow.com/qu­estions/15544549/how-does-paintcomponent-work
  87. A Swing Architecture Overview
    http://www.oracle.com/technet­work/java/architecture-142923.html
  88. Class javax.swing.JComponent
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html
  89. Class java.awt.Component
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html
  90. Class java.awt.Component.BltBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.BltBufferStrategy.html
  91. Class java.awt.Component.FlipBufferStrategy
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.FlipBufferStrategy­.html
  92. Metoda java.awt.Component.isDoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/java/awt/Com­ponent.html#isDoubleBuffe­red()
  93. Metoda javax.swing.JComponent.is­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#isDouble­Buffered()
  94. Metoda javax.swing.JComponent.set­DoubleBuffered()
    http://docs.oracle.com/ja­vase/6/docs/api/javax/swin­g/JComponent.html#setDouble­Buffered(boolean)
  95. Javadoc – třída GraphicsDevice
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsDevice.html
  96. Javadoc – třída GraphicsEnvironment
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsEnvironment.html
  97. Javadoc – třída GraphicsConfiguration
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Grap­hicsConfiguration.html
  98. Javadoc – třída DisplayMode
    http://docs.oracle.com/ja­vase/7/docs/api/java/awt/Dis­playMode.html
  99. Lesson: Full-Screen Exclusive Mode API
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/
  100. Full-Screen Exclusive Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/exclusivemode.html
  101. Display Mode
    http://docs.oracle.com/ja­vase/tutorial/extra/fullscre­en/displaymode.html
  102. Using the Full-Screen Exclusive Mode API in Java
    http://www.developer.com/ja­va/other/article.php/3609776/U­sing-the-Full-Screen-Exclusive-Mode-API-in-Java.htm
  103. Java quick guide: JVM Instruction Set (tabulka všech instrukcí JVM)
    http://www.mobilefish.com/tu­torials/java/java_quickgu­ide_jvm_instruction_set.html
  104. The JVM Instruction Set
    http://mpdeboer.home.xs4a­ll.nl/scriptie/node14.html
  105. MultiMedia eXtensions
    http://softpixel.com/~cwrig­ht/programming/simd/mmx.phpi
  106. SSE (Streaming SIMD Extentions)
    http://www.songho.ca/misc/sse/sse­.html
  107. Timothy A. Chagnon: SSE and SSE2
    http://www.cs.drexel.edu/~tc365/mpi-wht/sse.pdf
  108. Intel corporation: Extending the Worldr's Most Popular Processor Architecture
    http://download.intel.com/techno­logy/architecture/new-instructions-paper.pdf
  109. SIMD architectures:
    http://arstechnica.com/ol­d/content/2000/03/simd.ar­s/
  110. GC safe-point (or safepoint) and safe-region
    http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html
  111. Safepoints in HotSpot JVM
    http://blog.ragozin.info/2012/10/sa­fepoints-in-hotspot-jvm.html
  112. Java theory and practice: Synchronization optimizations in Mustang
    http://www.ibm.com/develo­perworks/java/library/j-jtp10185/
  113. How to build hsdis
    http://hg.openjdk.java.net/jdk7/hot­spot/hotspot/file/tip/src/sha­re/tools/hsdis/README
  114. Java SE 6 Performance White Paper
    http://www.oracle.com/technet­work/java/6-performance-137236.html
  115. Lukas Stadler's Blog
    http://classparser.blogspot­.cz/2010/03/hsdis-i386dll.html
  116. How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
    http://dropzone.nfshost.com/hsdis.htm
  117. PrintAssembly
    https://wikis.oracle.com/dis­play/HotSpotInternals/Prin­tAssembly
  118. The Java Virtual Machine Specification: 3.14. Synchronization
    http://docs.oracle.com/ja­vase/specs/jvms/se7/html/jvms-3.html#jvms-3.14
  119. The Java Virtual Machine Specification: 8.3.1.4. volatile Fields
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-8.html#jls-8.3.1.4
  120. The Java Virtual Machine Specification: 17.4. Memory Model
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.4
  121. The Java Virtual Machine Specification: 17.7. Non-atomic Treatment of double and long
    http://docs.oracle.com/ja­vase/specs/jls/se7/html/jls-17.html#jls-17.7
  122. Open Source ByteCode Libraries in Java
    http://java-source.net/open-source/bytecode-libraries
  123. ASM Home page
    http://asm.ow2.org/
  124. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2.org/users.html
  125. ObjectWeb ASM (Wikipedia)
    http://en.wikipedia.org/wi­ki/ObjectWeb_ASM
  126. Java Bytecode BCEL vs ASM
    http://james.onegoodcooki­e.com/2005/10/26/java-bytecode-bcel-vs-asm/
  127. BCEL Home page
    http://commons.apache.org/bcel/
  128. Byte Code Engineering Library (před verzí 5.0)
    http://bcel.sourceforge.net/
  129. Byte Code Engineering Library (verze >= 5.0)
    http://commons.apache.org/pro­per/commons-bcel/
  130. BCEL Manual
    http://commons.apache.org/bcel/ma­nual.html
  131. Byte Code Engineering Library (Wikipedia)
    http://en.wikipedia.org/wiki/BCEL
  132. BCEL Tutorial
    http://www.smfsupport.com/sup­port/java/bcel-tutorial!/
  133. Bytecode Engineering
    http://book.chinaunix.net/spe­cial/ebook/Core_Java2_Volu­me2AF/0131118269/ch13lev1sec6­.html
  134. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2.org/eclipse/index.html
  135. Javassist
    http://www.jboss.org/javassist/
  136. Byteman
    http://www.jboss.org/byteman
  137. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ibm.com/develo­perworks/java/library/j-dyn0414/
  138. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  139. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  140. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  141. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  142. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  143. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  144. aspectj (Eclipse)
    http://www.eclipse.org/aspectj/
  145. Aspect-oriented programming (Wikipedia)
    http://en.wikipedia.org/wi­ki/Aspect_oriented_program­ming
  146. AspectJ (Wikipedia)
    http://en.wikipedia.org/wiki/AspectJ
  147. EMMA: a free Java code coverage tool
    http://emma.sourceforge.net/
  148. Cobertura
    http://cobertura.sourceforge.net/
  149. jclasslib bytecode viewer
    http://www.ej-technologies.com/products/jclas­slib/overview.html
Našli jste v článku chybu?
Podnikatel.cz: Udělali jsme velkou chybu, napsal Čupr

Udělali jsme velkou chybu, napsal Čupr

DigiZone.cz: Samsung EVO-S: novinka pro Skylink

Samsung EVO-S: novinka pro Skylink

Vitalia.cz: Muž, který miluje příliš. Ženám neimponuje

Muž, který miluje příliš. Ženám neimponuje

Lupa.cz: Jen technická kvalita může být málo

Jen technická kvalita může být málo

DigiZone.cz: Světový pohár v přímém přenosu na ČT

Světový pohár v přímém přenosu na ČT

Vitalia.cz: Voda z Vltavy před a po úpravě na pitnou

Voda z Vltavy před a po úpravě na pitnou

Lupa.cz: Cimrman má hry na YouTube i vlastní doodle

Cimrman má hry na YouTube i vlastní doodle

DigiZone.cz: Numan Two: rozhlasový přijímač s CD

Numan Two: rozhlasový přijímač s CD

Podnikatel.cz: Instalatér, malíř a elektrikář. "Vymřou"?

Instalatér, malíř a elektrikář. "Vymřou"?

120na80.cz: Zázrak ze smetiště: co léčí lopuch?

Zázrak ze smetiště: co léčí lopuch?

Lupa.cz: Blíží se konec Wi-Fi sítí bez hesla?

Blíží se konec Wi-Fi sítí bez hesla?

Lupa.cz: Další Češi si nechali vložit do těla čip

Další Češi si nechali vložit do těla čip

120na80.cz: Co je padesátkrát sladší než cukr?

Co je padesátkrát sladší než cukr?

Lupa.cz: Jak levné procesory změnily svět?

Jak levné procesory změnily svět?

DigiZone.cz: DVB-T2 ověřeno: seznam TV zveřejněn

DVB-T2 ověřeno: seznam TV zveřejněn

Vitalia.cz: Tahák, jak vyzrát nad zápachem z úst

Tahák, jak vyzrát nad zápachem z úst

Lupa.cz: Proč jsou firemní počítače pomalé?

Proč jsou firemní počítače pomalé?

Podnikatel.cz: Vánoce v září? Kaufland si legraci nedělá

Vánoce v září? Kaufland si legraci nedělá

Podnikatel.cz: Babišovi se nedá věřit, stěžovali si hospodští

Babišovi se nedá věřit, stěžovali si hospodští

Vitalia.cz: dTest odhalil ten nejlepší kečup

dTest odhalil ten nejlepší kečup