Pohled pod kapotu JVM – závěrečné porovnání JVM, Lua VM a Python VM (2/2)

30. 9. 2014
Doba čtení: 49 minut

Sdílet

Porovnání základních vlastností tří virtuálních strojů – JVM, Lua VM a Python VM – bude dnes dokončeno. Zabývat se budeme voláním funkcí a metod a také implementacemi různých programových smyček. Nakonec přijdou všechny instrukce, které se mohou použít v bajtkódech JVM, Lua VM i Python VM.

Obsah

1. Pohled pod kapotu JVM – závěrečné porovnání JVM, Lua VM a Python VM (2/2)

2. Implementace programových smyček

3. Programová smyčka typu while

  3.1 Programová smyčka typu while v JVM

  3.2 Programová smyčka typu while v Lua VM

  3.3 Programová smyčka typu while v Python VM

4. Počítaná programová smyčka typu for

  4.1 Počítaná programová smyčka typu for v JVM

  4.2 Počítaná programová smyčka typu for v Lua VM

  4.3 Počítaná programová smyčka typu for v Python VM

5. Programová smyčka typu for-each

  5.1 programová smyčka typu for-each v JVM

  5.2 Programová smyčka typu for-each v Lua VM

  5.3 Programová smyčka typu for-each v Python VM

6. Volání funkcí a metod

  6.1 JVM

  6.2 Lua VM

  6.3 Python VM

7. Práce s výjimkami

  7.1 JVM

  7.2 Lua VM

  7.3 Python VM

8. Příloha A: Tabulka operačních kódů instrukcí Lua VM

9. Příloha B: Tabulka operačních kódů instrukcí Python VM

10. Příloha C: Tabulka operačních kódů instrukcí JVM

11. Odkazy na Internetu

1. Pohled pod kapotu JVM – závěrečné porovnání JVM, Lua VM a Python VM (2/2)

V dnešní části seriálu o JVM i o dalších dvou virtuálních strojích navážeme na část předchozí. Dnes totiž dokončíme závěrečné porovnání vlastností a možností trojice virtuálních strojů, tj. JVM, Lua VM i Python VM. Kromě obecného porovnání těchto tří virtuálních strojů se zaměříme i na vzájemné srovnání struktury bajtkódu, přesněji řečeno instrukční sady všech tří porovnávaných VM. Zabývat se budeme problematikou tvorby programových smyček různých typů, volání funkcí popř. volání metod a taktéž rozličnými způsoby přístupu k prvkům složených datových typů (což do značné míry souvisí s programovými smyčkami). Na závěr budou vypsány (poměrně rozsáhlé) tabulky se všemi instrukcemi, které se mohou použít v bajtkódech JVM, Lua VM i Python VM.

2. Implementace programových smyček

V předchozí části tohoto seriálu jsme si mj. popsali i instrukce používané ve všech třech typech virtuálních strojů k implementaci podmíněných a nepodmíněných skoků. Tyto instrukce jsou používány i pro implementaci některých typů programových smyček, především pro smyčku typu while. Typicky se tato programová smyčka přeloží takovým způsobem, že je na začátku použit podmíněný skok za konec těla smyčky provedený v případě nesplnění podmínky. Poslední instrukcí ve smyčce je nepodmíněný skok na její začátek. Podobný způsob je většinou aplikován i na počítané smyčky typu for. Poněkud odlišná je situace v případě programové smyčky typu for-each. Tyto smyčky jsou v aplikacích používány tak často (a navíc tak idiomatickým způsobem), že si v bajtkódech virtuálních strojů Pythonu a jazyka Lua „vysloužily“ vlastní specializované instrukce.

3. Programová smyčka typu while

Základním a ve skutečnosti i univerzálním typem smyčky je ve strukturovaném programování smyčka typu while. U tohoto typu smyčky se podmínka pro ukončení smyčky kontroluje vždy na začátku každé iterace, což mj. znamená, že se tělo smyčky nemusí provést ani jednou, a to v případě, kdy podmínka není splněna již před provedením první iterace, tj. před vstupem do smyčky. Z tohoto důvodu se konstrukce while používá například v situacích, kdy se mají zpracovávat vstupní data (čtená ze souboru, z databázové tabulky atd.), u nichž není zřejmé, kolik údajů se bude načítat a zda se vůbec nějaký údaj na vstupu bude nacházet. Zajímavé je, že ostatní typy smyček lze většinou přepsat právě na programovou smyčku typu while, i když – jak uvidíme na příkladu Pythonu – se nemusí vždy jednat o elegantní řešení. Pojďme si tedy na velmi jednoduchých příkladech ukázat způsob překladu této programové smyčky do bajtkódu JVM, Lua VM i Python VM. Nejprve si ukážeme překlad smyčky, v níž se pouze snižuje hodnota počitadla kontrolovaného v podmínce pro další iteraci.

3.1 Programová smyčka typu while v JVM

Metoda se smyčkou while:

public static int loop(int x) {
    // sestupne citani smerem k nule
    while (x > 0) {
        x--;
    }
    // bude se vracet hodnota 0
    return x;
}

Překlad do bajtkódu:

public static int loop(int);
  Code:
   0:   iload_0             ; načíst (jediný) parametr metody a uložit ho na zásobník
   1:   ifle    10          ; porovnání s nulou a podmíněný skok na instrukci na indexu 10
   4:   iinc    0, -1       ; snížení hodnoty počitadla (resp. přičtení hodnoty -1, což je to samé)
   7:   goto    0           ; nepodmíněný skok na začátek smyčky
   10:  iload_0             ; opět načíst (jediný) parametr metody a uložit ho na zásobník
   11:  ireturn             ; a vrátit jeho novou hodnotu, což by měla být vždy nula

3.2 Programová smyčka typu while v Lua VM

Funkce se smyčkou while:

function loop(x)
    while x > 0 do
        x = x - 1
    end
    return x
end

Překlad do bajtkódu:

function Test7.lua:7,12 (6 instructions at 0x9f54c88)
1 param, 2 slots, 0 upvalues, 1 local, 2 constants, 0 functions
        1       [8]     LT              0 -1 0  ; 0 -   ; porovnání x s nulou a podmíněné přeskočení další instrukce
        2       [8]     JMP             0 2     ; to 5  ; nepodmíněný skok na instrukci s indexem 5 (konec smyčky)
        3       [9]     SUB             0 0 -2  ; - 1   ; snížení hodnoty parametru x (index 0) o jedničku
        4       [9]     JMP             0 -4    ; to 1  ; nepodmíněný skok na instrukci s indexem 1 (skok na začátek smyčky)
        5       [11]    RETURN          0 2             ; návrat s použitím jediného parametru jako návratové hodnoty
        6       [12]    RETURN          0 1             ; automaticky generováno (zde zcela zbytečně)

3.3 Programová smyčka typu while v Python VM

Funkce se smyčkou while:

def loop(x):
    while x > 0:
        x = x - 1
    return x

Překlad do bajtkódu:

loop:
  8           0 SETUP_LOOP              28 (to 31)   ; příprava na provedení smyčky
              3 LOAD_FAST                0 (x)       ; načíst (jediný) parametr metody a uložit ho na zásobník
              6 LOAD_CONST               1 (0)       ; načíst konstantu 0 použitou pro porovnání
              9 COMPARE_OP               4 (>)       ; provést porovnání, výsledek je použit pro podmíněný skok
             12 JUMP_IF_FALSE           14 (to 29)   ; podmíněný skok při NEsplnění podmínky
             15 POP_TOP                              ; uklizení zásobníku

  9          16 LOAD_FAST                0 (x)       ; načíst (jediný) parametr metody a uložit ho na zásobník
             19 LOAD_CONST               2 (1)       ; načíst konstantu 1 použitou pro snížení počitadla
             22 BINARY_SUBTRACT                      ; snížení hodnoty počitadla o 1
             23 STORE_FAST               0 (x)       ; a uložit novou hodnotu
             26 JUMP_ABSOLUTE            3           ; skok na začátek smyčky
             29 POP_TOP                              ; (opět) uklizení zásobníku)
             30 POP_BLOCK

 10          31 LOAD_FAST                0 (x)       ; načíst (jediný) parametr metody a uložit ho na zásobník
             34 RETURN_VALUE                         ; návrat s použitím jediného parametru jako návratové hodnoty

4. Počítaná programová smyčka typu for

Dalším velmi často používaným typem programové smyčky je počítaná programová smyčka typu for, jejíž variantu nalezneme jak v programovacím jazyku Java (zde byla převzata přímo z jazyka C a C++), tak i v jazyku Lua. V Pythonu lze tuto smyčku nahradit pomocí for-each a funkcí range() popř. xrange()

4.1 Počítaná programová smyčka typu for v JVM

Metoda se smyčkou for:

static int testForLoop() {
    int result = 0;
    for (int i = 0; i <= 10; i++) {
        result++;
    }
    return result;
}

Překlad do bajtkódu:

static int testForLoop();
  Code:
   0:   iconst_0               // počáteční hodnota proměnné result
   1:   istore_0
   2:   iconst_0               // počáteční hodnota počitadla
   3:   istore_1
   4:   iload_1                // začátek smyčky
   5:   bipush  10             // hodnota horní meze
   7:   if_icmpgt       19     // při překročení horní meze skok ZA konec smyčky
   10:  iinc    0, 1           // zvýšit hodnotu proměnné result
   13:  iinc    1, 1           // zvýšit hodnotu počitadla
   16:  goto    4              // nepodmíněný skok na začátek smyčky
   19:  iload_0
   20:  ireturn                // vrátit hodnotu proměnné result

4.2 Počítaná programová smyčka typu for v Lua VM

Funkce se smyčkou for:

function testForLoop()
    local result = 0
    for i = 0, 10 do
        result = result + 1
    end
    return result;
end

Překlad do bajtkódu:

0 params, 5 slots, 0 upvalues, 5 locals, 3 constants, 0 functions
        1       [11]    LOADK           0 -1    ; 0    // počáteční hodnota proměnné result
        2       [12]    LOADK           1 -1    ; 0    // počáteční hodnota počitadla
        3       [12]    LOADK           2 -2    ; 10   // hodnota horní meze
        4       [12]    LOADK           3 -3    ; 1    // krok smyčky
        5       [12]    FORPREP         1 1     ; to 7 // příprava na smyčku snížení hodnoty počitadla o krok
                                                       // a skok na iterační příkaz
        6       [13]    ADD             0 0 -3  ; - 1  // zvýšit hodnotu proměnné result
        7       [12]    FORLOOP         1 -2    ; to 6 // provedení iterace - zvýšení hodnoty počitadla
                                                       // test a případný skok na instrukci číslo 6
        8       [15]    RETURN          0 2            // vrátit hodnotu proměnné result
        9       [16]    RETURN          0 1            // automaticky generovaný návrat z funkce

4.3 Počítaná programová smyčka typu for v Python VM

Funkce se smyčkou for:

def testForLoop():
    result = 0;
    for i in xrange(0,11):
        result = result + 1
    return result

Překlad do bajtkódu:

testForLoop:
  9           0 LOAD_CONST               1 (0)        // počáteční hodnota proměnné result
              3 STORE_FAST               0 (result)
 
 10           6 SETUP_LOOP              33 (to 42)    // konstrukce programové smyčky
              9 LOAD_GLOBAL              0 (xrange)   // příprava na volání xrange()
             12 LOAD_CONST               1 (0)        // dolní mez
             15 LOAD_CONST               2 (11)       // horní mez
             18 CALL_FUNCTION            2            // zavolání xrange()
             21 GET_ITER
             22 FOR_ITER                16 (to 41)    // vlastní smyčka
             25 STORE_FAST               1 (i)
 
 11          28 LOAD_FAST                0 (result)   // *
             31 LOAD_CONST               3 (1)        // * result = result + 1
             34 BINARY_ADD                            // *
             35 STORE_FAST               0 (result)   // *
             38 JUMP_ABSOLUTE           22            // další iterace (skok na začátek smyčky)
             41 POP_BLOCK                             // úklid po ukončení smyčky
 
 12          42 LOAD_FAST                0 (result)
             45 RETURN_VALUE                          // vrátit hodnotu proměnné result

5. Programová smyčka typu for-each

Poměrně velké množství operací (pravděpodobně většina operací) se složenými datovými typy se neprovádí s využitím počítané smyčky typu for, ale spíše s použitím smyčky typu for-each, která je v určité podobě implementována ve všech třech virtuálních strojích (JVM, Lua VM i Python VM).

5.1 Programová smyčka typu for-each v JVM

Metoda se smyčkou for-each:

static int sum(int[] array) {
    int sum = 0;
    for (int item : array) {
        sum += item;
    }
    return sum;
}

Překlad do bajtkódu:

static int sum(int[]);
  Code:
   0:   iconst_0                // počáteční hodnota lokální proměnné "sum"
   1:   istore_1                // inicializace lokální proměnné "sum"
   2:   aload_0                 // uložit první (jediný) parametr metody na zásobník
   3:   astore_2                // reference na zpracovávané pole je umístěna do druhé lokální proměnné
   4:   aload_2
   5:   arraylength             // vypočítat délku pole a uložit na TOS
   6:   istore_3                // uložit délku pole do třetí lokální proměnné
   7:   iconst_0                // počáteční hodnota počitadla
   8:   istore  4               // uložit do čtvrté lokální proměnné
 
   10:  iload   4               // začátek programové smyčky "for"
   12:  iload_3                 // porovnat hodnotu počitadla s délkou pole
   13:  if_icmpge       33      // test na ukončení programové smyčky
   16:  aload_2                 // načíst referenci na pole
   17:  iload   4               // hodnota počitadla je použita jako index
   19:  iaload                  // získat i-tý prvek z pole typu int[] (i=hodnota počitadla)
   20:  istore  5               // uložit hodnotu prvku do páté lokální proměnné
 
   22:  iload_1                 // lokální proměnná "sum" na TOS
   23:  iload   5
   25:  iadd                    // přičíst k proměnné "sum" hodnotu i-tého prvku pole
   26:  istore_1                // přenos hodnoty z TOS do lokální proměnné "sum"
 
   27:  iinc    4, 1            // zvýšit hodnotu počitadla o jedničku
   30:  goto    10              // skok na začátek programové smyčky
 
   33:  iload_1                 // načíst aktuální hodnotu lokální proměnné "sum"
   34:  ireturn                 // a vrátit ji jako výsledek metody

5.2 Programová smyčka typu for-each v Lua VM

Funkce se smyčkou for-each:

function sum(array)
    local sum = 0
    for i, item in ipairs(array) do
        sum = sum + item
    end
    return sum
end

Překlad do bajtkódu:

function <Test23.lua:23,29> (10 instructions at 0x9a39228)
1 param, 8 slots, 1 upvalue, 7 locals, 2 constants, 0 functions
        1       [24]    LOADK           1 -1    ; načtení konstanty 0 do lokální proměnné sum [registr číslo 1]
        2       [25]    GETTABUP        2 0 -2  ; příprava na volání funkce ipairs() [registr číslo 2]
        3       [25]    MOVE            3 0     ; tabulku/pole uložit do registru číslo 3
        4       [25]    CALL            2 2 4   ; zavolání funkce ipairs() [reference uložena v registru číslo 2]
        5       [25]    JMP             0 1     ; skok těsně před konec programové smyčky [instrukce číslo 7]
        6       [26]    ADD             1 1 6   ; přičtení obsahu registru číslo 6 k sumě [registr číslo 1]
        7       [25]    TFORCALL        2 2     ; volání funkce uložené v registru číslo 2 [ipairs()]
                                                ; s parametry R(3) [tabulka] a R(4)
                                                ; výsledek volání ulož do R(5) [index] a R(6) [hodnota]
        8       [25]    TFORLOOP        4 -3    ; pokud platí R(5) ~= nil, proveď relativní skok na instrukci číslo 6
        9       [28]    RETURN          1 2     ; ukončení funkce s návratovou hodnotou
        10      [29]    RETURN          0 1     ; standardní ukončení funkce

5.3 Programová smyčka typu for-each v Python VM

Funkce se smyčkou for-each:

def sum(tuple):
    sum = 0
    for item in tuple:
        sum = sum + item
    return sum

Překlad do bajtkódu:

sum:
 22           0 LOAD_CONST           0 // uložit na vrchol zásobníku operandů konstantu 0
              3 STORE_FAST           1 // tato hodnota se použije pro inicializaci lokální proměnné "sum"
 
 23           6 SETUP_LOOP          24 // příprava bloku pro programovou smyčku (až do adresy 33)
              9 LOAD_FAST            0 // načtení prvního parametru funkce (n-tice) a uložení na TOS
             12 GET_ITER               // získání iterátoru pro n-tici
 
                                       // začátek těla programové smyčky
        >>   13 FOR_ITER            16 // přečti další hodnotu generovanou iterátorem
                                       // pokud iterátor další hodnotu již nevrátí, skok na instrukci s indexem 32
             16 STORE_FAST           2 // přečtení hodnoty lokální proměnné "item"
 24          19 LOAD_FAST            1 // uložit na TOS hodnotu lokální proměnné "sum"
             22 LOAD_FAST            2 // uložit na TOS hodnotu lokální proměnné "item" (původní TOS se posune)
             25 BINARY_ADD             // součet sum+item
             26 STORE_FAST           1 // výsledek součtu se uloží zpět do lokální proměnné "sum"
             29 JUMP_ABSOLUTE       13 // skok na začátek programové smyčky (na instrukci FOR_ITER)
 
        >>   32 POP_BLOCK              // konec těla programové smyčky, zrušení bloku
 
 25     >>   33 LOAD_FAST            1 // uložit na vrchol zásobníku operandů hodnotu lokální proměnné "sum"
             36 RETURN_VALUE           // návrat z funkce

6. Volání funkcí a metod

Jednou z nejdůležitějších technologií implementovaných ve všech třech popisovaných virtuálních strojích Java VM, Lua VM i Python VM je volání funkcí popř. metod. Jedná se samozřejmě o velmi často prováděnou činnost, při níž je kromě vlastního zavolání vybrané funkce nebo metody nutné zajistit předání hodnot parametrů a taktéž zpracování návratové hodnoty (Java) či většího množství návratových hodnot (Lua). Jednotlivé VM se liší jak ve způsobu předávání parametrů do funkcí (zásobník vs. registry), tak i ve způsobu předání návratových hodnot (jedna, více). Samostatnou kapitolou jsou funkce s proměnným počtem parametrů, funkce s pojmenovanými parametry atd. (zde exceluje Python).

6.1 JVM

Volání metod v JVM:

static int staticMethod2() {
    return 42;
}
 
int nonStaticMethod2() {
    return 42;
}
 
void callStaticMethod2() {
    staticMethod2();
}
 
void callnonStaticMethod2() {
    nonStaticMethod2();
}

Překlad do bajtkódu:

  static int staticMethod2();
    Code:
       0: bipush        42     // ulozit na vrchol zasobniku operandu konstantu 42
       2: ireturn              // vyskok z metody s navratovou hodnotou ziskanou z TOS
 
  void callStaticMethod2();
    Code:
       0: invokestatic  #3;    // volani staticke metody: Method staticMethod2:()I
       3: pop                  // odstranit navratovou hodnotu ze zasobniku operandu
       4: return               // vyskok z metody bez pouziti navratove hodnoty
 
  int nonStaticMethod2();
    Code:
       0: bipush        42     // ulozit na vrchol zasobniku operandu konstantu 42
       2: ireturn              // vyskok z metody s navratovou hodnotou ziskanou z TOS
 
  void callnonStaticMethod2();
    Code:
       0: aload_0              // ulozit na vrchol zasobniku operandu hodnotu this
       1: invokevirtual #3;    // volani virtualni metody: Method nonStaticMethod2:()I
       4: pop                  // odstranit navratovou hodnotu ze zasobniku operandu
       5: return               // vyskok z metody bez pouziti navratove hodnoty
 

6.2 Lua VM

Volání funkcí v Lua VM:

function function2(x)
    return x
end
 
function callFunction2()
    function2()
    function2(nil)
    function2(42)
    function2(1, 2)
    function2("xyzzy")
end

Překlad do bajtkódu:

function2():
function <Test25.lua:20,22> (2 instructions at 0x8549de0)
1 param, 2 slots, 0 upvalues, 1 local, 0 constants, 0 functions
        1       [21]    RETURN          0 2    ; navratova hodnota - konstanta ulozena na indexu 2
        2       [22]    RETURN          0 1    ; navrat z funkce (automaticky vkladana instrukce)
constants (0) for 0x8549de0:
locals (1) for 0x8549de0:
        0       x       1       3              ; parametr funkce zde vystupuje jako lokalni promenna
upvalues (0) for 0x8549de0:
 
callFunction2():
function <Test25.lua:55,61> (16 instructions at 0x854a410)
0 params, 3 slots, 1 upvalue, 0 locals, 6 constants, 0 functions
        1       [56]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        2       [56]    CALL            0 1 1   ; zavolani funkce function2()
        3       [57]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        4       [57]    LOADNIL         1 0     ; parametr funkce se preda v registru R1
        5       [57]    CALL            0 2 1   ; zavolani funkce function2()
        6       [58]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        7       [58]    LOADK           1 -2    ; parametr funkce se preda v registru R1
        8       [58]    CALL            0 2 1   ; zavolani funkce function2()
        9       [59]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        10      [59]    LOADK           1 -4    ; prvni parametr funkce
        11      [59]    LOADK           2 -5    ; druhy parametr funkce
        12      [59]    CALL            0 3 1   ; zavolani funkce function2()
        13      [60]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        14      [60]    LOADK           1 -6    ; prvni parametr funkce se preda v registru R1
        15      [60]    CALL            0 2 1   ; zavolani funkce function2()
        16      [61]    RETURN          0 1     ; navrat z funkce (automaticky vkladana instrukce)
constants (6) for 0x854a410:
        1       "function2"
        2       42
        3       "function2"
        4       1
        5       2
        6       "xyzzy"
locals (0) for 0x854a410:
upvalues (1) for 0x854a410:
        0       _ENV    0       0

6.3 Python VM

Volání funkcí v Lua VM:

def function2(x):
    return x
 
def callFunction2():
    function2()
    function2(None)
    function2(42)
    function2(1, 2)
    function2("xyzzy")

Překlad do bajtkódu:

function2():
 21           0 LOAD_FAST                0 (x)         // uložit první (a jediný) parametr funkce na TOS
              3 RETURN_VALUE                           // vrátit tuto hodnotu
 
callFunction2():
 52           0 LOAD_GLOBAL              0 (function2) // načíst referenci volané funkce
              3 CALL_FUNCTION            0             // volat funkci (konstanta udává počet skutečně předávaných parametrů)
              6 POP_TOP                                // odstranit prvek (návratovou hodnotu) z TOS
 
 53           7 LOAD_GLOBAL              0 (function2) // načíst referenci volané funkce
             10 LOAD_CONST               0 (None)      // skutečný parametr funkce uložit na TOS
             13 CALL_FUNCTION            1             // volat funkci (konstanta udává počet skutečně předávaných parametrů)
             16 POP_TOP                                // odstranit prvek (návratovou hodnotu) z TOS
 
 54          17 LOAD_GLOBAL              0 (function2) // načíst referenci volané funkce
             20 LOAD_CONST               1 (42)        // skutečný parametr funkce uložit na TOS
             23 CALL_FUNCTION            1             // volat funkci (konstanta udává počet skutečně předávaných parametrů)
             26 POP_TOP                                // odstranit prvek (návratovou hodnotu) z TOS
 
 55          27 LOAD_GLOBAL              2 (function2) // načíst referenci volané funkce
             30 LOAD_CONST               2 (1)         // skutečný parametr funkce uložit na TOS
             33 LOAD_CONST               3 (2)         // skutečný parametr funkce uložit na TOS
             36 CALL_FUNCTION            2             // volat funkci (konstanta udává počet skutečně předávaných parametrů)
             39 POP_TOP                                // odstranit prvek (návratovou hodnotu) z TOS
 
 56          40 LOAD_GLOBAL              0 (function2) // načíst referenci volané funkce
             43 LOAD_CONST               4 ('xyzzy')   // skutečný parametr funkce uložit na TOS
             46 CALL_FUNCTION            1             // volat funkci (konstanta udává počet skutečně předávaných parametrů)
             49 POP_TOP                                // odstranit prvek (návratovou hodnotu) z TOS
             50 LOAD_CONST               0 (None)      // uložit konstantu None na zásobník operandů
             53 RETURN_VALUE                           // vrátit tuto konstantu (uloženou na TOS)

7. Práce s výjimkami

Velmi důležitou součástí většiny moderních programovacích jazyků jsou syntaktické konstrukce určené pro práci s výjimkami, přičemž každý popisovaný programovací jazyk a jeho virtuální stroj tuto problematiku řeší poněkud odlišným způsobe.

Začněme popisem práce s výjimkami v Javě. V tomto programovacím jazyku má vývojář k dispozici hned několik klíčových slov určených jak pro označení těch výjimek, které mohou vzniknout v nějaké metodě (klíčové slovo throws), tak i pro samotné programové vyhození výjimky zvoleného typu (klíčové slovo throw) i její zachycení (struktura tvořená dvojicí programových bloků try-catch popř. rozšířená i o blok finally).

Prakticky stejným způsobem jsou programové bloky try-catch-finally implementovány i v programovacím jazyku Python, až na jeden nepatrný (syntaktický) rozdíl – namísto klíčového slova catch se zde používá slovo except.

Zcela odlišná je však implementace podobného příkladu v programovacím jazyce Lua, a to z toho důvodu, že tento jazyk přímo neobsahuje podporu pro bloky try-catch-finally. Namísto toho je aplikován „funkcionální“ přístup, kdy je ta část programu, v níž může nastat nějaká výjimka, umístěna do samostatné funkce, která se pak zavolá v „sandboxu“ s využitím funkce pcall() (protected call). Výjimka se vyhazuje funkcí error() a pokud výjimka skutečně nastane, vrací funkce pcall() ve svém prvním výsledku hodnotu false (další návratová hodnota či návratové hodnoty již souvisí s volanou funkcí).

7.1 JVM

Program, v němž se vyhazují a zachycují výjimky:

public static void throwException() throws Exception {
    throw new Exception();
}
 
public static void main(String[] args) throws Exception {
    try {
        throwException();
        System.out.println("try block");
    }
    catch (Exception e) {
        System.out.println("catch block");
    }
    finally {
        System.out.println("finally block");
    }
}

Překlad do bajtkódu:

  public static void throwException() throws java.lang.Exception;
    Code:
       0: new           #2;                 // vytvoření instance třídy java.lang.Exception
       3: dup                               // kopie reference na nově vytvořený objekt
                                            // inicializace objektu
       4: invokespecial #3;                 // Method java/lang/Exception."<init>":()V
       7: athrow                            // objekt byl inicializován, vyhození výjimky
 
 
  public static void main(java.lang.String[]) throws java.lang.Exception;
    Code:
      *** blok try ***
       0: invokestatic  #4;                 // volání metody throwException:()V
                                            // příprava na volání metody System.out.println()
       3: getstatic     #5;                 // Field java/lang/System.out:Ljava/io/PrintStream;
       6: ldc           #6;                 // konstanta obsahující řetězec "try block"
       8: invokevirtual #7;                 // volání metody java.io.PrintStream.println:(java.lang.String)
 
      *** blok finally #1 ***
                                            // příprava na volání metody System.out.println()
      11: getstatic     #5;                 // Field java/lang/System.out:Ljava/io/PrintStream;
      14: ldc           #8;                 // konstanta obsahující řetězec "finally block"
      16: invokevirtual #7;                 // volání metody java.io.PrintStream.println:(java.lang.String)
      19: goto          53                  // skok ZA konec bloku finally
 
      *** blok catch ***
      22: astore_1
      23: getstatic     #5;                 // Field java/lang/System.out:Ljava/io/PrintStream;
      26: ldc           #9;                 // konstanta obsahující řetězec "catch block"
      28: invokevirtual #7;                 // volání metody java.io.PrintStream.println:(java.lang.String)
 
      *** blok finally #2 ***
      31: getstatic     #5;                 // Field java/lang/System.out:Ljava/io/PrintStream;
      34: ldc           #8;                 // konstanta obsahující řetězec "finally block"
      36: invokevirtual #7;                 // volání metody java.io.PrintStream.println:(java.lang.String)
      39: goto          53                  // skok ZA konec bloku finally
 
      *** blok finally #3 - zachycení + rethrow jiné výjimky ***
      42: astore_2                          // uložit obsah TOS do lokální proměnné
      43: getstatic     #5;                 // Field java/lang/System.out:Ljava/io/PrintStream;
      46: ldc           #8;                 // konstanta obsahující řetězec "finally block"
      48: invokevirtual #7;                 // volání metody java.io.PrintStream.println:(java.lang.String)
      51: aload_2                           // obnovit obsah TOS
      52: athrow                            // a ihned vyvolat výjimku, kterou jsme zachytili jen dočasně
 
      53: return                            // ukončení běhu metody main()
 
    Exception table:                        // tabulka obsahující seznam řádků a případných výjimek
       from    to  target type
           0    11    22   Class java/lang/Exception // blok try
           0    11    42   any                       // bloky try+finally #1
          22    31    42   any                       // blok catch
          42    43    42   any                       // instrukce zachycení jiné výjimky

7.2 Lua VM

Program, v němž se vyhazují a zachycují výjimky:

function throwNewException(message)
    error(message)
end
 
function main()
    print("Calling function 'throwNewException()'")
    local status, message = pcall(throwNewException, "Hello world!")
    print("Returned from function 'throwNewException()'")
    print("    Status  = ", status)
    print("    Message = ", message)
end

Překlad do bajtkódu:

throwNewException():
function <Test34.lua:13,15> (4 instructions, 16 bytes at 0x175af60)
1 param, 3 slots, 0 upvalues, 1 local, 1 constant, 0 functions
        1       [14]    GETGLOBAL       1 -1    ; získání reference na funkci error()
        2       [14]    MOVE            2 0     ; parametr předaný funkci error
        3       [14]    CALL            1 2 1   ; zavolání funkce error (registr R1) s předáním parametru v registru R2
 
        4       [15]    RETURN          0 1     ; návrat z funkce throwNewException
 
 
main():
function <Test34.lua:22,28> (19 instructions, 76 bytes at 0x175b240)
0 params, 5 slots, 0 upvalues, 2 locals, 8 constants, 0 functions
        1       [23]    GETGLOBAL       0 -1    ; získání reference na funkci print
        2       [23]    LOADK           1 -2    ; řetězec "Calling function 'throwNewException'"
        3       [23]    CALL            0 2 1   ; zavolání funkce print s předáním parametru v registru R1
 
        4       [24]    GETGLOBAL       0 -3    ; získání reference na funkci pcall
        5       [24]    GETGLOBAL       1 -4    ; získání reference na funkci throwNewException
        6       [24]    LOADK           2 -5    ; řetězec "Hello world!"
        7       [24]    CALL            0 3 3   ; zavolání funkce pcall s dvojicí parametrů (throwNewException, "Hello world!"
 
        8       [25]    GETGLOBAL       2 -1    ; získání reference na funkci print
        9       [25]    LOADK           3 -6    ; řetězec "Returned from function 'throwNewException()'"
        10      [25]    CALL            2 2 1   ; zavolání funkce print
 
        11      [26]    GETGLOBAL       2 -1    ; získání reference na funkci print
        12      [26]    LOADK           3 -7    ; řetězec "    Status  = "
        13      [26]    MOVE            4 0     ; první návratová hodnota funkce pcall
        14      [26]    CALL            2 3 1   ; zavolání funkce print se dvěma parametry (registry R3 a R4)
 
        15      [27]    GETGLOBAL       2 -1    ; získání reference na funkci print
        16      [27]    LOADK           3 -8    ; řetězec "    Message = "
        17      [27]    MOVE            4 1     ; druhá návratová hodnota funkce pcall
        18      [27]    CALL            2 3 1   ; zavolání funkce print se dvěma parametry (registry R3 a R4)
 
        19      [28]    RETURN          0 1     ; návrat z funkce main

7.3 Python VM

Program, v němž se vyhazují a zachycují výjimky:

def throwNewException(message):
    raise Exception(message)
 
def main():
    try:
        print("Calling function 'throwNewException()'")
        throwNewException("Hello world!")
        print("Returned from function 'throwNewException()'")
    except:
        print("Catch/except block")
    finally:
        print("Finally block")

Překlad do bajtkódu:

throwNewException():
 13           0 LOAD_GLOBAL              0 (Exception) ; příprava na vytvoření objektu představujícího výjimku
                                                       ; získání reference třídy, jejíž instance se bude vytvářet
              3 LOAD_FAST                0 (message)   ; příprava na vytvoření objektu představujícího výjimku
                                                       ; načtení parametru funkce
              6 CALL_FUNCTION            1             ; volání Exception(message) - vytvoření výjimky
 
              9 RAISE_VARARGS            1             ; vlastní vyhození výjimky
 
             12 LOAD_CONST               0 (None)      ; návratová hodnota funkce throwNewException
             15 RETURN_VALUE                           ; výskok z funkce throwNewException
 
 
main():
 21           0 SETUP_FINALLY           43 (to 46)     ; vytvoření bloku instrukcí, v nichž jsou implementovány bloky try-finally
              3 SETUP_EXCEPT            24 (to 30)     ; vytvoření bloku instrukcí, v nichž může dojít k výjimce
 
začátek bloku *try*
 
 22           9 LOAD_CONST               1             ; řetězec "Calling function 'throwNewException()'")
              9 PRINT_ITEM                             ; tisk řetězce na standardní výstup
             10 PRINT_NEWLINE                          ; odřádkování
 
 23          11 LOAD_GLOBAL              0 (throwNewException)
                                                       ; získání reference funkce, která se bude volat
             14 LOAD_CONST               2             ; řetězec 'Hello world!'
             17 CALL_FUNCTION            1             ; zavolání funkce throwNewException
             20 POP_TOP                                ; úklid návratové hodnoty (nevyužijeme ji)
 
 24          21 LOAD_CONST               3             ; řetězec "Returned from function 'throwNewException()'"
             24 PRINT_ITEM                             ; tisk řetězce na standardní výstup
             25 PRINT_NEWLINE                          ; odřádkování
 
             26 POP_BLOCK                              ; volání proběhlo v pořádku - zrušíme celý blok
                                                       ; vytvořený přes SETUP_EXCEPT
             27 JUMP_FORWARD            12 (to 42)     ; skok na konec funkce (přeskok dalšího bloku)
 
konec bloku *try*
 
začátek bloku *except*
 
 25          30 POP_TOP                                ; úklid na zásobníku operandů (vlastní výjimka)
             31 POP_TOP                                ; úklid na zásobníku operandů (parametr výjimky)
             32 POP_TOP                                ; úklid na zásobníku operandů (handler)
 
 26          33 LOAD_CONST               4             ; řetězec "Catch/except block"
             36 PRINT_ITEM                             ; tisk řetězce na standardní výstup
             37 PRINT_NEWLINE                          ; odřádkování
             38 JUMP_FORWARD             1 (to 42)     ; skok na konec funkce (přeskok dalšího bloku)
 
konec bloku *except*
 
             41 END_FINALLY                            ; ukončení prvního bloku finally
             42 POP_BLOCK                              ; náhrada návratové hodnoty funkce
             43 LOAD_CONST               0 (None)      ; náhrada návratové hodnoty funkce
 
začátek bloku *finally*
 
 28          46 LOAD_CONST               5             ; řetězec "('Finally block')"
             49 PRINT_ITEM                             ; tisk řetězce na standardní výstup
             50 PRINT_NEWLINE                          ; odřádkování
 
             51 END_FINALLY                            ; ukončení bloku finally
 
konec bloku *finally*
 
             52 LOAD_CONST               0 (None)      ; návratová hodnota funkce main
             55 RETURN_VALUE                           ; výskok z funkce main

8. Příloha A: Tabulka operačních kódů instrukcí Lua VM

V první příloze je vypsána tabulka operačních kódů všech instrukcí virtuálního stroje programovacího jazyka Lua. Tato tabulka je využívána překladačem luac. Povšimněte si, že celkový počet instrukcí je velmi nízký a tím pádem na uložení operačního kódu instrukce dostačuje pouze šest bitů (a délka instrukcí je šestnáct bitů), na rozdíl od známější JVM, kde je operační kód instrukce uložený v osmi bitech (a instrukce mají navíc proměnnou délku):

ict ve školství 24

Operační kód Instrukce Význam
0×00 MOVE přesun dat ze zdrojového registru do cílového registru
0×01 LOADK(A,Bx) načtení konstanty
0×02 LOADKX(A) načtení konstanty (alternativní forma instrukce)
0×03 LOADBOOL(A,B,C) načtení booleovské konstanty a podmíněný přeskok další instrukce
0×04 LOADNIL(A,B) nastavení zvolené sekvence prvků na nil
     
0×05 GETUPVAL(A,B) přístup k vázaným proměnným (čtení proměnné)
0×06 GETTABUP(A,B,C) přístup k vázaným proměnným
0×07 GETTABLE(A,B,C) přístup k prvkům tabulky (čtení)
0×08 SETTABUP(A,B,C) přístup k vázaným proměnným (zápis do proměnné)
0×09 SETUPVAL(A,B) přístup k vázaným proměnným
0×0a SETTABLE(A,B,C) přístup k prvkům tabulky (zápis)
0×0b NEWTABLE(A,B,C) vytvoření tabulky o zadané velikosti
0×0c SELF(A,B,C) získání hodnoty self/this
     
0×0d ADD aritmetická operace s trojicí registrů: součet
0×0e SUB aritmetická operace s trojicí registrů: rozdíl
0×0f MUL aritmetická operace s trojicí registrů: součin
0×10 DIV aritmetická operace s trojicí registrů: podíl
0×11 MOD aritmetická operace s trojicí registrů: podíl modulo
0×12 POW aritmetická operace s trojicí registrů: umocnění
0×13 UNM změna znaménka
0×14 NOT negace
     
0×15 LEN(A,B) výpočet délky/velikosti (tabulky…)
0×16 CONCAT konverze dat
     
0×17 JMP(A,sBx) nepodmíněný relativní skok v rámci jedné funkce
0×18 EQ(A,B,C) přeskok další instrukce za podmínky ((RK[B] == RK[C]) ~= A)
0×19 LT(A,B,C) přeskok další instrukce za podmínky ((RK[B] < RK[C]) ~= A)
0×1a LE(A,B,C) přeskok další instrukce za podmínky ((RK[B] <= RK[C]) ~= A)
0×1b TEST(A,C) přeskok další instrukce za podmínky not (R[A] < ⇒ C)
0×1c TESTSET(A,B,C) podmíněný přeskok další instrukce/přiřazení
     
0×1d CALL(A,B,C) volání funkce s předáním parametrů v registrech
0×1e TAILCALL(A,B,C) tail call
0×1f RETURN(A,B) návrat z funkce s předáním návratových hodnot v registrech
     
0×20 FORLOOP(A,sBx) další iterace počítané programové smyčky při splnění podmínky
0×21 FORPREP(A,sBx) příprava počítané programové smyčky for
0×22 TFORCALL(A,C) volání iterátoru, typicky ve smyčce typu for-each
0×23 TFORLOOP(A,sBx) další iterace smyčky typu for-each při splnění podmínky
     
0×24 SETLIST(A,B,C) konverze dat
0×25 CLOSURE vytvoření uzávěru
0×26 VARARG(A,B) načtení vararg do zvolené sady registrů
0×27 EXTRAARG(Ax) načtení konstanty, rozšíření instrukce LOADKX

9. Příloha B: Tabulka operačních kódů instrukcí Python VM

Virtuální stroj programovacího jazyka Python využívá v bajtkódu instrukce, jejichž operační kód má šířku osmi bitů (jeden bajt). To znamená, že je teoreticky možné využít 256 různých instrukcí. Ve skutečnosti jsou však některé operační kódy neobsazeny, což je ostatně patrné i při pohledu na tabulku se seznamem všech (v současnosti používaných) instrukcí Python VM:

Operační kód Instrukce Význam
0×00 STOP_CODE konec bajtkódu, není využito interpretrem
     
0×01 POP_TOP odstraní položku ze zásobníku operandů
0×02 ROT_TWO rotace (swap) dvou položek
0×03 ROT_THREE rotace (roll) tří položek
0×04 DUP_TOP duplikace položky na zásobníku operandů
0×05 ROT_FOUR rotace čtyř položek
     
0×06 neobsazeno (neobsazeno)
0×07 neobsazeno (neobsazeno)
0×08 neobsazeno (neobsazeno)
     
0×09 NOP žádná operace (výplň)
     
0×0a UNARY_POSITIVE unární operátor +
0×0b UNARY_NEGATIVE změna znaménka
0×0c UNARY_NOT negace
0×0d UNARY_CONVERT implementace konstrukce backtick (`)
     
0×0e neobsazeno (neobsazeno)
     
0×0f UNARY_INVERT bitová negace
     
0×10 neobsazeno (neobsazeno)
0×11 neobsazeno (neobsazeno)
0×12 neobsazeno (neobsazeno)
     
0×13 BINARY_POWER umocnění
0×14 BINARY_MULTIPLY součin
0×15 BINARY_DIVIDE podíl
0×16 BINARY_MODULO podíl modulo
0×17 BINARY_ADD součet
0×18 BINARY_SUBTRACT rozdíl
     
0×19 BINARY_SUBSCR přístup k prvkům složeného datového typu (řetězec, seznam, n-tice)
     
0×1a BINARY_FLOOR_DIVIDE podíl (//)
0×1b BINARY_TRUE_DIVIDE podíl
0×1c INPLACE_FLOOR_DIVIDE podíl (odlišný přístup k prvkům na zásobníku)
0×1d INPLACE_TRUE_DIVIDE podíl (odlišný přístup k prvkům na zásobníku)
     
0×1e SLICE+0 přístup k prvkům složeného datového typu (řetězec, seznam, n-tice)
0×1f SLICE+1 přístup k prvkům složeného datového typu (řetězec, seznam, n-tice)
0×20 SLICE+2 přístup k prvkům složeného datového typu (řetězec, seznam, n-tice)
0×21 SLICE+3 přístup k prvkům složeného datového typu (řetězec, seznam, n-tice)
     
0×22 neobsazeno (neobsazeno)
0×23 neobsazeno (neobsazeno)
0×24 neobsazeno (neobsazeno)
0×25 neobsazeno (neobsazeno)
0×26 neobsazeno (neobsazeno)
0×27 neobsazeno (neobsazeno)
     
0×28 STORE_SLICE+0 přístup k prvkům složeného datového typu (typicky seznamu)
0×29 STORE_SLICE+1 přístup k prvkům složeného datového typu (typicky seznamu)
0×2a STORE_SLICE+2 přístup k prvkům složeného datového typu (typicky seznamu)
0×2b STORE_SLICE+3 přístup k prvkům složeného datového typu (typicky seznamu)
     
0×2c neobsazeno (neobsazeno)
0×2d neobsazeno (neobsazeno)
0×2e neobsazeno (neobsazeno)
0×2f neobsazeno (neobsazeno)
0×30 neobsazeno (neobsazeno)
0×31 neobsazeno (neobsazeno)
     
0×32 DELETE_SLICE+0 přístup k prvkům složeného datového typu (typicky seznamu)
0×33 DELETE_SLICE+1 přístup k prvkům složeného datového typu (typicky seznamu)
0×34 DELETE_SLICE+2 přístup k prvkům složeného datového typu (typicky seznamu)
0×35 DELETE_SLICE+3 přístup k prvkům složeného datového typu (typicky seznamu)
     
0×36 STORE_MAP uloží do mapy další dvojici klíč:hodnota
     
0×37 INPLACE_ADD varianta instrukce BINARY_ADD (odlišný přístup k prvkům na zásobníku)
0×38 INPLACE_SUBTRACT varianta instrukce BINARY_SUBTRACT (odlišný přístup k prvkům na zásobníku)
0×39 INPLACE_MULTIPLY varianta instrukce BINARY_MULTIPLY (odlišný přístup k prvkům na zásobníku)
0×3a INPLACE_DIVIDE varianta instrukce BINARY_DIVIDE (odlišný přístup k prvkům na zásobníku)
0×3b INPLACE_MODULO varianta instrukce BINARY_MODULO (odlišný přístup k prvkům na zásobníku)
     
0×3c STORE_SUBSCR přístup k prvkům n-tice, seznamu či řetězce
0×3d DELETE_SUBSCR vymazání prvku složeného datového typu
     
0×3e BINARY_LSHIFT posun doleva
0×3f BINARY_RSHIFT posun doprava
0×40 BINARY_AND bitový/logický součin
0×41 BINARY_XOR bitová/logická nonekvivalence
0×42 BINARY_OR bitový/logický součet
     
0×43 INPLACE_POWER operace **
     
0×44 GET_ITER získání iterátoru pro prvek uložený na TOS
     
0×45 neobsazeno (neobsazeno)
     
0×46 PRINT_EXPR tisk výrazu
0×47 PRINT_ITEM tisk jedné hodnoty
0×48 PRINT_NEWLINE tisk konce řádku
0×49 PRINT_ITEM_TO tisk jedné hodnoty do souboru
0×4a PRINT_NEWLINE_TO tisk konce řádku do souboru
     
0×4b INPLACE_LSHIFT posun doleva
0×4c INPLACE_RSHIFT posun doprava
0×4d INPLACE_AND bitový/logický součin
0×4e INPLACE_XOR bitová/logická nonekvivalence
0×4f INPLACE_OR bitový/logický součet
     
0×50 BREAK_LOOP přerušení programové smyčky
     
0×51 WITH_CLEANUP vymazání zásobníku při ukončení bloku with
0×52 LOAD_LOCALS použito při definici tříd
0×53 RETURN_VALUE návrat z funkce a vrácení hodnoty z TOS
     
0×54 IMPORT_STAR nahraje všechny (nelokální) symboly do jmenného prostoru
     
0×55 EXEC_STMT volá exec
0×56 YIELD_VALUE použito v generátoru pro vrácení (další) hodnoty
0×57 POP_BLOCK odstraní blok ze zásobníku (konec smyčky atd.)
0×58 END_FINALLY ukončí klauzuli finally
     
0×59 BUILD_CLASS vytvoří novou třídu
0×5a STORE_NAME práce se jmény uloženými v co_names
0×5b DELETE_NAME práce se jmény uloženými v co_names
     
0×5c UNPACK_SEQUENCE rozdělení sekvence na jednotlivé prvky a jejich uložení na zásobník
0×5d FOR_ITER použito při implementaci programové smyčky
0×5e LIST_APPEND volá list.append()
0×5f STORE_ATTR práce se jmény uloženými v co_names
0×60 DELETE_ATTR práce se jmény uloženými v co_names
0×61 STORE_GLOBAL práce s globálními jmény
0×62 DELETE_GLOBAL práce s globálními jmény
     
0×63 DUP_TOPX instrukce DUP opakovaná 1× až 5×
     
0×64 LOAD_CONST práce s hodnotami uloženými v co_const
0×65 LOAD_NAME práce s hodnotami uloženými v co_names
     
0×66 BUILD_TUPLE vytvoření nové n-tice
0×67 BUILD_LIST vytvoření nového seznamu
0×68 BUILD_SET vytvoření nové množiny
0×69 BUILD_MAP vytvoření nové mapy
0×6a LOAD_ATTR přečtení atributu objektu
     
0×6b COMPARE_OP provedení zvolené Booleovské operace
     
0×6c IMPORT_NAME import modulu
0×6d IMPORT_FROM import modulu
     
0×6e JUMP_FORWARD skok na relativní index (je zadána delta oproti současné adrese)
0×6f JUMP_IF_FALSE_OR_POP opačné chování, než je tomu v předchozí instrukci
0×70 JUMP_IF_TRUE_OR_POP pokud TOS==true, provede se skok, v opačném případě se TOS odstraní
0×71 JUMP_ABSOLUTE skok na zadaný index (lokální adresu)
0×72 POP_JUMP_IF_FALSE podmíněný skok na základě obsahu TOS; obsah TOS je odstraněn
0×73 POP_JUMP_IF_TRUE podmíněný skok na základě obsahu TOS (opačná podmínka); obsah TOS je odstraněn
     
0×74 LOAD_GLOBAL uložení zvoleného globálního jména na TOS
     
0×75 neobsazeno (neobsazeno)
0×76 neobsazeno (neobsazeno)
     
0×77 CONTINUE_LOOP implementace příkazu continue
0×78 SETUP_LOOP příprava programové smyčky (vytvoření bloku atd.)
0×79 SETUP_EXCEPT vytvoření kopie bloku try na zásobníku
0×7a SETUP_FINALLY vytvoření kopie bloku try na zásobníku
     
0×7b neobsazeno (neobsazeno)
     
0×7c LOAD_FAST uložení reference lokální proměnné na zásobník
0×7d STORE_FAST uložení hodnoty do lokální proměnné z TOS
0×7e DELETE_FAST vymazání lokální proměnné
     
0×7f neobsazeno (neobsazeno)
0×80 neobsazeno (neobsazeno)
0×81 neobsazeno (neobsazeno)
     
0×82 RAISE_VARARGS vyhození výjimky
0×83 CALL_FUNCTION volání funkce
0×84 MAKE_FUNCTION uložení reference na novou funkci na TOS
0×85 BUILD_SLICE implementace funkce slice()
0×86 MAKE_CLOSURE vytvoření uzávěru
0×87 LOAD_CLOSURE uloží referenci na uzávěr
0×88 LOAD_DEREF práce s uzávěry a/nebo objekty
0×89 STORE_DEREF práce s uzávěry a/nebo objekty
     
0×8a neobsazeno (neobsazeno)
0×8b neobsazeno (neobsazeno)
     
0×8c CALL_FUNCTION_VAR zavolání funkce
0×8d CALL_FUNCTION_KW zavolání funkce
0×8e CALL_FUNCTION_VAR_KW zavolání funkce
     
0×8f SETUP_WITH začátek bloku with
     
0×90 neobsazeno (neobsazeno)
     
0×91 EXTENDED_ARG podpora pro argumenty funkcí, jichž je více než 65535
     
0×92 SET_ADD rozšíření bajtkódu: práce s množinou
0×93 MAP_ADD rozšíření bajtkódu: práce s mapou
     
0×94 neobsazeno (neobsazeno)
0×95 neobsazeno (neobsazeno)
0×96 neobsazeno (neobsazeno)
0×97 neobsazeno (neobsazeno)
0×98 neobsazeno (neobsazeno)
0×99 neobsazeno (neobsazeno)
0×9a neobsazeno (neobsazeno)
0×9b neobsazeno (neobsazeno)
0×9c neobsazeno (neobsazeno)
0×9d neobsazeno (neobsazeno)
0×9e neobsazeno (neobsazeno)
0×9f neobsazeno (neobsazeno)
0×a0 neobsazeno (neobsazeno)
0×a1 neobsazeno (neobsazeno)
0×a2 neobsazeno (neobsazeno)
0×a3 neobsazeno (neobsazeno)
0×a4 neobsazeno (neobsazeno)
0×a5 neobsazeno (neobsazeno)
0×a6 neobsazeno (neobsazeno)
0×a7 neobsazeno (neobsazeno)
0×a8 neobsazeno (neobsazeno)
0×a9 neobsazeno (neobsazeno)
0×aa neobsazeno (neobsazeno)
0×ab neobsazeno (neobsazeno)
0×ac neobsazeno (neobsazeno)
0×ad neobsazeno (neobsazeno)
0×ae neobsazeno (neobsazeno)
0×af neobsazeno (neobsazeno)
0×b0 neobsazeno (neobsazeno)
0×b1 neobsazeno (neobsazeno)
0×b2 neobsazeno (neobsazeno)
0×b3 neobsazeno (neobsazeno)
0×b4 neobsazeno (neobsazeno)
0×b5 neobsazeno (neobsazeno)
0×b6 neobsazeno (neobsazeno)
0×b7 neobsazeno (neobsazeno)
0×b8 neobsazeno (neobsazeno)
0×b9 neobsazeno (neobsazeno)
0×ba neobsazeno (neobsazeno)
0×bb neobsazeno (neobsazeno)
0×bc neobsazeno (neobsazeno)
0×bd neobsazeno (neobsazeno)
0×be neobsazeno (neobsazeno)
0×bf neobsazeno (neobsazeno)
0×c0 neobsazeno (neobsazeno)
0×c1 neobsazeno (neobsazeno)
0×c2 neobsazeno (neobsazeno)
0×c3 neobsazeno (neobsazeno)
0×c4 neobsazeno (neobsazeno)
0×c5 neobsazeno (neobsazeno)
0×c6 neobsazeno (neobsazeno)
0×c7 neobsazeno (neobsazeno)
0×c8 neobsazeno (neobsazeno)
0×c9 neobsazeno (neobsazeno)
0×ca neobsazeno (neobsazeno)
0×cb neobsazeno (neobsazeno)
0×cc neobsazeno (neobsazeno)
0×cd neobsazeno (neobsazeno)
0×ce neobsazeno (neobsazeno)
0×cf neobsazeno (neobsazeno)
0×d0 neobsazeno (neobsazeno)
0×d1 neobsazeno (neobsazeno)
0×d2 neobsazeno (neobsazeno)
0×d3 neobsazeno (neobsazeno)
0×d4 neobsazeno (neobsazeno)
0×d5 neobsazeno (neobsazeno)
0×d6 neobsazeno (neobsazeno)
0×d7 neobsazeno (neobsazeno)
0×d8 neobsazeno (neobsazeno)
0×d9 neobsazeno (neobsazeno)
0×da neobsazeno (neobsazeno)
0×db neobsazeno (neobsazeno)
0×dc neobsazeno (neobsazeno)
0×dd neobsazeno (neobsazeno)
0×de neobsazeno (neobsazeno)
0×df neobsazeno (neobsazeno)
0×e0 neobsazeno (neobsazeno)
0×e1 neobsazeno (neobsazeno)
0×e2 neobsazeno (neobsazeno)
0×e3 neobsazeno (neobsazeno)
0×e4 neobsazeno (neobsazeno)
0×e5 neobsazeno (neobsazeno)
0×e6 neobsazeno (neobsazeno)
0×e7 neobsazeno (neobsazeno)
0×e8 neobsazeno (neobsazeno)
0×e9 neobsazeno (neobsazeno)
0×ea neobsazeno (neobsazeno)
0×eb neobsazeno (neobsazeno)
0×ec neobsazeno (neobsazeno)
0×ed neobsazeno (neobsazeno)
0×ee neobsazeno (neobsazeno)
0×ef neobsazeno (neobsazeno)
0×f0 neobsazeno (neobsazeno)
0×f1 neobsazeno (neobsazeno)
0×f2 neobsazeno (neobsazeno)
0×f3 neobsazeno (neobsazeno)
0×f4 neobsazeno (neobsazeno)
0×f5 neobsazeno (neobsazeno)
0×f6 neobsazeno (neobsazeno)
0×f7 neobsazeno (neobsazeno)
0×f8 neobsazeno (neobsazeno)
0×f9 neobsazeno (neobsazeno)
0×fa neobsazeno (neobsazeno)
0×fb neobsazeno (neobsazeno)
0×fc neobsazeno (neobsazeno)
0×fd neobsazeno (neobsazeno)
0×fe neobsazeno (neobsazeno)
0×ff neobsazeno (neobsazeno)

10. Příloha C: Tabulka operačních kódů instrukcí JVM

Poslední (nejrozsáhlejší) tabulkou je tabulka s operačními kódy instrukcí používaná virtuálními stroji programovacího jazyka Java. Z možných 256 kombinací jsou některé kódy nevyužity – tyto kódy se nachází na konci tabulky. Některé instrukce, například jsr, navíc nejsou v moderních překladačích Javy používány:

Operační kód Instrukce Význam
0×00 nop neprovede se žádná činnost (délka této instrukce je jeden bajt)
     
0×01 aconst_null uložení reference „null“ na zásobník
0×02 iconst_m1 uložení konstanty –1 na zásobník
0×03 iconst0 uložení konstanty 0 na zásobník
0×04 iconst1 uložení konstanty 1 na zásobník
0×05 iconst2 uložení konstanty 2 na zásobník
0×06 iconst3 uložení konstanty 3 na zásobník
0×07 iconst4 uložení konstanty 4 na zásobník
0×08 iconst5 uložení konstanty 5 na zásobník
0×09 lconst0 uložení konstanty 0L na zásobník
0×0a lconst1 uložení konstanty 1L na zásobník
0×0b fconst0 uložení konstanty 0.0f na zásobník
0×0c fconst1 uložení konstanty 1.0f na zásobník
0×0d fconst2 uložení konstanty 2.0f na zásobník
0×0e dconst0 uložení konstanty 0.0 na zásobník
0×0f dconst1 uložení konstanty 1.0 na zásobník
     
0×10 bipush uložení bajtu na zásobník s konverzí na int
0×11 sipush uložení 16bitového slova hibyte-lowbyte na zásobník s konverzí na int
0×12 ldc načte konstantu z constant poolu (může se jednat i o referenci)
0×13 ldc_w načte konstantu z constant poolu (index je šestnáctibitový)
0×14 ldc2_w totéž co předchozí instrukce, ale pro typy long a double (ty mají v constant poolu vyhrazeny dvě položky)
     
0×15 iload načtení lokální proměnné typu int z pozice „index“ a její uložení na TOS
0×16 lload načtení lokální proměnné typu long z pozice „index“ a její uložení na TOS
0×17 fload načtení lokální proměnné typu float z pozice „index“ a její uložení na TOS
0×18 dload načtení lokální proměnné typu double z pozice „index“ a její uložení na TOS
0×19 aload načtení lokální proměnné typu reference na objekt z pozice „index“ a její uložení na TOS
0×1a iload0 načtení lokální proměnné typu int z pozice číslo 0 a její uložení na TOS
0×1b iload1 načtení lokální proměnné typu int z pozice číslo 1 a její uložení na TOS
0×1c iload2 načtení lokální proměnné typu int z pozice číslo 2 a její uložení na TOS
0×1d iload3 načtení lokální proměnné typu int z pozice číslo 3 a její uložení na TOS
0×1e lload0 načtení lokální proměnné typu long z pozice číslo 0 a její uložení na TOS
0×1f lload1 načtení lokální proměnné typu long z pozice číslo 1 a její uložení na TOS
0×20 lload2 načtení lokální proměnné typu long z pozice číslo 2 a její uložení na TOS
0×21 lload3 načtení lokální proměnné typu long z pozice číslo 3 a její uložení na TOS
0×22 fload0 načtení lokální proměnné typu float z pozice číslo 0 a její uložení na TOS
0×23 fload1 načtení lokální proměnné typu float z pozice číslo 1 a její uložení na TOS
0×24 fload2 načtení lokální proměnné typu float z pozice číslo 2 a její uložení na TOS
0×25 fload3 načtení lokální proměnné typu float z pozice číslo 3 a její uložení na TOS
0×26 dload0 načtení lokální proměnné typu double z pozice číslo 0 a její uložení na TOS
0×27 dload1 načtení lokální proměnné typu double z pozice číslo 1 a její uložení na TOS
0×28 dload2 načtení lokální proměnné typu double z pozice číslo 2 a její uložení na TOS
0×29 dload3 načtení lokální proměnné typu double z pozice číslo 3 a její uložení na TOS
0×2a aload0 načtení lokální proměnné typu reference na objekt z pozice číslo 0 a její uložení na TOS
0×2b aload1 načtení lokální proměnné typu reference na objekt z pozice číslo 1 a její uložení na TOS
0×2c aload2 načtení lokální proměnné typu reference na objekt z pozice číslo 2 a její uložení na TOS
0×2d aload3 načtení lokální proměnné typu reference na objekt z pozice číslo 3 a její uložení na TOS
     
0×2e iaload přečtení prvku z pole typu int[]
0×2f laload přečtení prvku z pole typu long[]
0×30 faload přečtení prvku z pole typu float[]
0×31 daload přečtení prvku z pole typu double[]
0×32 aaload přečtení prvku z pole typu reference[]
0×33 baload přečtení prvku z pole typu byte[] nebo boolean[]
0×34 caload přečtení prvku z pole typu char[]
0×35 saload přečtení prvku z pole typu short[]
     
0×36 istore přesun hodnoty z TOS do lokální proměnné umístěné na pozici „index“ (kontrola na typ int)
0×37 lstore přesun hodnoty z TOS do lokální proměnné umístěné na pozici „index“ (kontrola na typ long)
0×38 fstore přesun hodnoty z TOS do lokální proměnné umístěné na pozici „index“ (kontrola na typ float)
0×39 dstore přesun hodnoty z TOS do lokální proměnné umístěné na pozici „index“ (kontrola na typ double)
0×3a astore přesun hodnoty z TOS do lokální proměnné umístěné na pozici „index“ (kontrola, zda jde o objekt)
0×3b istore0 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 0 (kontrola na typ int)
0×3c istore1 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 1 (kontrola na typ int)
0×3d istore2 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 2 (kontrola na typ int)
0×3e istore3 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 3 (kontrola na typ int)
0×3f lstore0 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 0 (kontrola na typ long)
0×40 lstore1 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 1 (kontrola na typ long)
0×41 lstore2 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 2 (kontrola na typ long)
0×42 lstore3 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 3 (kontrola na typ long)
0×43 fstore0 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 0 (kontrola na typ float)
0×44 fstore1 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 1 (kontrola na typ float)
0×45 fstore2 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 2 (kontrola na typ float)
0×46 fstore3 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 3 (kontrola na typ float)
0×47 dstore0 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 0 (kontrola na typ double)
0×48 dstore1 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 1 (kontrola na typ double)
0×49 dstore2 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 2 (kontrola na typ double)
0×4a dstore3 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 3 (kontrola na typ double)
0×4b astore0 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 0 (kontrola na typ reference na objekt)
0×4c astore1 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 1 (kontrola na typ reference na objekt)
0×4d astore2 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 2 (kontrola na typ reference na objekt)
0×4e astore3 přesun hodnoty z TOS do lokální proměnné umístěné na pozici číslo 3 (kontrola na typ reference na objekt)
     
0×4f iastore zápis nové hodnoty prvku do pole typu int[]
0×50 lastore zápis nové hodnoty prvku do pole typu long[]
0×51 fastore zápis nové hodnoty prvku do pole typu float[]
0×52 dastore zápis nové hodnoty prvku do pole typu double[]
0×53 aastore zápis nové hodnoty prvku do pole typu reference[]
0×54 bastore zápis nové hodnoty prvku do pole typu byte[] nebo boolean[]
0×55 castore zápis nové hodnoty prvku do pole typu char[]
0×56 sastore zápis nové hodnoty prvku do pole typu short[]
     
0×57 pop odstraní jednu položku z TOS (platí pro int, float, referenci na objekt)
0×58 pop2 odstraní jednu (long, double) položku či dvě (int, float, reference) položky ze zásobníku
0×59 dup zduplikuje (zkopíruje) položku z TOS (platí pro int, float, referenci na objekt)
0×5a dup_x1 zduplikuje (zkopíruje) položku z TOS, ale vloží i o dvě pozice níž do zásobníku
0×5b dup_x2 zduplikuje (zkopíruje) položku z TOS a vloží i o dvě či tři pozice níž (v závislosti na bitové šířce)
0×5c dup2 duplikace jedné (long, double) či dvou (int, float, reference) položek
0×5d dup2_x1 kombinace vlastností instrukcí dup2 a dup_x1 (vložení prvku o dvě místa níže)
0×5e dup2_x2 kombinace vlastností instrukcí dup2 a dup_x2
0×5f swap prohodí dva prvky ležící na vrcholu zásobníku (platí pro int, float, referenci na objekt)
     
0×60 iadd součet (int)
0×61 ladd součet (long)
0×62 fadd součet (float)
0×63 dadd součet (double)
0×64 isub rozdíl (int)
0×65 lsub rozdíl (long)
0×66 fsub rozdíl (float)
0×67 dsub rozdíl (double)
0×68 imul součin (int)
0×69 lmul součin (long)
0×6a fmul součin (float)
0×6b dmul součin (double)
0×6c idiv podíl (int)
0×6d ldiv podíl (long)
0×6e fdiv podíl (float)
0×6f ddiv podíl (double)
0×70 irem zbytek po dělení (int)
0×71 lrem zbytek po dělení (long)
0×72 frem zbytek po dělení (float)
0×73 drem zbytek po dělení (double)
     
0×74 ineg změna znaménka (int)
0×75 lneg změna znaménka (long)
0×76 fneg změna znaménka (float)
0×77 dneg změna znaménka (double)
     
0×78 ishl aritmetický/bitový posun doleva (int)
0×79 lshl aritmetický/bitový posun doleva (long)
0×7a ishr aritmetický posun doprava (int)
0×7b lshr aritmetický posun doprava (long)
0×7c iushr bitový posun doprava (int)
0×7d lushr bitový posun doprava (long)
     
0×7e iand bitový součin (int)
0×7f land bitový součin (long)
0×80 ior bitový součet (int)
0×81 lor bitový součet (long)
0×82 ixor nonekvivalence (int)
0×83 lxor nonekvivalence (long)
     
0×84 iinc zvýšení hodnoty proměnné typu int
     
0×85 i2l konverzní operace: int na long
0×86 i2f konverzní operace: int na float
0×87 i2d konverzní operace: int na double
0×88 l2i konverzní operace: long na int
0×89 l2f konverzní operace: long na float
0×8a l2d konverzní operace: long na double
0×8b f2i konverzní operace: float na int
0×8c f2l konverzní operace: float na long
0×8d f2d konverzní operace: float na double
0×8e d2i konverzní operace: double na int
0×8f d2l konverzní operace: double na long
0×90 d2f konverzní operace: double na float
0×91 i2b konverzní operace: int na byte
0×92 i2c konverzní operace: int na char
0×93 i2s konverzní operace: int na short
     
0×94 lcmp 1 když operand 1 > operand 2
0 když operand 1 == operand 2
-1 když operand 1 < operand 2
0×95 fcmpl 1 když operand 1 > operand 2
0 když operand 1 == operand 2
-1 když operand 1 < operand 2
-1 když operand 1 je NaN
-1 když operand 2 je NaN
0×96 fcmpg 1 když operand 1 > operand 2
0 když operand 1 == operand 2
-1 když operand 1 < operand 2
1 když operand 1 je NaN
1 když operand 2 je NaN
0×97 dcmpl 1 když operand 1 > operand 2
0 když operand 1 == operand 2
-1 když operand 1 < operand 2
-1 když operand 1 je NaN
-1 když operand 2 je NaN
0×98 dcmpg 1 když operand 1 > operand 2
0 když operand 1 == operand 2
-1 když operand 1 < operand 2
1 když operand 1 je NaN
1 když operand 2 je NaN
     
0×99 ifeq skok na lokální adresu highbyte*256+lowbyte při splnění podmínky
0×9a ifne skok na lokální adresu highbyte*256+lowbyte při splnění podmínky
0×9b iflt skok na lokální adresu highbyte*256+lowbyte při splnění podmínky
0×9c ifge skok na lokální adresu highbyte*256+lowbyte při splnění podmínky
0×9d ifgt skok na lokální adresu highbyte*256+lowbyte při splnění podmínky
0×9e ifle skok na lokální adresu highbyte*256+lowbyte při splnění podmínky
     
0×9f if_icmpeq skok na lokální adresu při splnění podmínky value1==value2
0×a0 if_acmpne skok na lokální adresu při splnění podmínky value1≠value2
0×a1 if_icmplt skok na lokální adresu při splnění podmínky value1<value2
0×a2 if_icmpge skok na lokální adresu při splnění podmínky value1≥value2
0×a3 if_icmpgt skok na lokální adresu při splnění podmínky value1>value2
0×a4 if_icmple skok na lokální adresu při splnění podmínky value1≤value2
0×a5 if_acmpeq skok na lokální adresu při splnění podmínky reference1=reference2
0×a6 if_acmpne skok na lokální adresu při splnění podmínky reference1≠reference2
     
0×a7 goto přímý skok na adresu uloženou v dvojici operandů: highbyte*256+lowbyte
0×a8 jsr skok v rámci metody s uložením návratové adresy (nepoužívá se)
0×a9 ret návrat na adresu uloženou instrukcí jsr
     
0×aa tableswitch implementace rozeskoku switch, pokud hodnoty tvoří celistvou posloupnost
0×ab lookupswitch obecná implementace rozeskoku switch
     
0×ac ireturn získání návratové hodnoty typu int z TOS zásobníku operandů + návrat z metody
0×ad lreturn získání návratové hodnoty typu long z TOS zásobníku operandů + návrat z metody
0×ae freturn získání návratové hodnoty typu float z TOS zásobníku operandů + návrat z metody
0×af dreturn získání návratové hodnoty typu double z TOS zásobníku operandů + návrat z metody
0×b0 areturn získání návratové hodnoty typu reference na objekt z TOS zásobníku operandů + návrat z metody
0×b1 return pouze návrat z metody, žádná hodnota se nevrací
     
0×b2 getstatic získá z constant poolu záznam typu FieldReference a uloží hodnotu získaného atributu na zásobník operandů
0×b3 putstatic opak předchozí instrukce: přesun hodnoty ze zásobníku operandů do statického atributu
0×b4 getfield získá hodnotu atributu objektu, jehož reference je uložena na TOS a tuto hodnotu následně uloží na zásobník operandů
0×b5 putfield obsah TOS se přenese do atributu objektu, jehož reference je uložena na druhém místě zásobníku operandů
     
0×b6 invokevirtual zavolání nestatické metody s předáním hodnoty this a všech dalších parametrů
0×b7 invokespecial zavolání speciální metody, většinou konstruktoru
0×b8 invokestatic zavolání statické metody s předáním parametrů této metodě
0×b9 invokeinterface zavolání metody deklarované v rozhraní, samozřejmě s předáním parametrů
     
0×ba unused nepoužito
     
0×bb new vytvoření objektu
0×bc newarray vytvoří nové pole s prvky primitivního datového typu
0×bd anewarray vytvoří nové pole objektů
0×be arraylength vrací délku pole
     
0×bf athrow vyhození výjimky
0×c0 checkcast kontrola, zda je objekt zadaného typu
0×c1 instanceof test, zda je objekt zadaného typu
     
0×c2 monitorenter vstup do synchronizovaného bloku (získání monitoru)
0×c3 monitorexit výstup ze synchronizovaného bloky (uvolnění monitoru)
     
0×c4 wide modifikátor další instrukce
0×c5 multianewarray vytvoří vícedimenzionální pole o dimensions dimenzích
     
0×c6 ifnull skok na adresu highbyte*256+lowbyte při splnění podmínky: operand==null
0×c7 ifnonnull skok na adresu highbyte*256+lowbyte při splnění podmínky: operand≠null
0×c8 goto_w přímý skok na adresu uloženou ve čtveřici operandů: byte1*224+byte2*216+byte3*28+by­te4 („široká“ varianta instrukce goto)
0×c9 jsr_w alternativa instrukce jsr s „širokou“ adresou
     
0×ca breakpoint nastavení breakpointu (nepoužíváno v bajtkódu, určeno pro interní použití v JVM)
     
0×cb (neobsazeno) (v současné verzi JVM neobsazeno)
0×cc (neobsazeno) (v současné verzi JVM neobsazeno)
0×cd (neobsazeno) (v současné verzi JVM neobsazeno)
0×ce (neobsazeno) (v současné verzi JVM neobsazeno)
0×cf (neobsazeno) (v současné verzi JVM neobsazeno)
0×d0 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d1 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d2 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d3 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d4 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d5 invokedynamic (v dřívějších verzích neobsazeno)
0×d6 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d7 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d8 (neobsazeno) (v současné verzi JVM neobsazeno)
0×d9 (neobsazeno) (v současné verzi JVM neobsazeno)
0×da (neobsazeno) (v současné verzi JVM neobsazeno)
0×db (neobsazeno) (v současné verzi JVM neobsazeno)
0×dc (neobsazeno) (v současné verzi JVM neobsazeno)
0×dd (neobsazeno) (v současné verzi JVM neobsazeno)
0×de (neobsazeno) (v současné verzi JVM neobsazeno)
0×df (neobsazeno) (v současné verzi JVM neobsazeno)
0×e0 (neobsazeno) (v současné verzi JVM neobsazeno)
0×e1 (neobsazeno) (v současné verzi JVM neobsazeno)
0×e2 (neobsazeno) (v současné verzi JVM neobsazeno)
0×e3 (neobsazeno) (v současné verzi JVM neobsazeno)
0×e4 (neobsazeno) (v současné verzi JVM neobsazeno)
0×e5 ldc_quick rychlá varianta instrukce ldc (ve starší verzi JVM neobsazeno)
0×e6 ldc_w_quick rychlá varianta instrukce ldc_w (ve starší verzi JVM neobsazeno)
0×e7 ldc2_w_quick rychlá varianta instrukce ldc2_w (ve starší verzi JVM neobsazeno)
0×e8 getfield_quick rychlá varianta instrukce getfield (ve starší verzi JVM neobsazeno)
0×e9 putfield_quick rychlá varianta instrukce putfield (ve starší verzi JVM neobsazeno)
0×ea getfield2_quick rychlá varianta instrukce getfield2 (ve starší verzi JVM neobsazeno)
0×eb putfield2_quick rychlá varianta instrukce putfield2 (ve starší verzi JVM neobsazeno)
0×ec getstatic_quick rychlá varianta instrukce getstatic (ve starší verzi JVM neobsazeno)
0×ed putstatic_quick rychlá varianta instrukce putstatic (ve starší verzi JVM neobsazeno)
0×ee getstatic2_quick rychlá varianta instrukce getstatic2 (ve starší verzi JVM neobsazeno)
0×ef putstatic2_quick rychlá varianta instrukce putstatic2 (ve starší verzi JVM neobsazeno)
0×f0 invokevirtual_quick rychlá varianta instrukce invokevirtual (ve starší verzi JVM neobsazeno)
0×f1 invokenonvirtual_quick rychlá varianta instrukce invokenonvirtual (ve starší verzi JVM neobsazeno)
0×f2 invokesuper_quick rychlá varianta instrukce invokesuper (ve starší verzi JVM neobsazeno)
0×f3 invokestatic_quick rychlá varianta instrukce invokestatic (ve starší verzi JVM neobsazeno)
0×f4 invokeinterface_quick rychlá varianta instrukce invokeinterface (ve starší verzi JVM neobsazeno)
0×f5 invokevirtualobject_quick rychlá varianta instrukce invokevirtualobject(ve starší verzi JVM neobsazeno)
0×f6 invokeignored_quick rychlá varianta instrukce invokeignored (ve starší verzi JVM neobsazeno)
0×f7 new_quick rychlá varianta instrukce new (ve starší verzi JVM neobsazeno)
0×f8 anewarray_quick rychlá varianta instrukce anewarray (ve starší verzi JVM neobsazeno)
0×f9 multianewarray_quick rychlá varianta instrukce multianewarray (ve starší verzi JVM neobsazeno)
0×fa checkcast_quick rychlá varianta instrukce checkcast (ve starší verzi JVM neobsazeno)
0×fb instanceof_quick rychlá varianta instrukce instanceof (ve starší verzi JVM neobsazeno)
0×fc invokevirtual_quick_w rychlá varianta instrukce invokevirtual_w (ve starší verzi JVM neobsazeno)
0×fd getfield_quick_w rychlá varianta instrukce getfield_w (ve starší verzi JVM neobsazeno)
0×fe putfield_quick_w rychlá varianta instrukce putfield_w (ve starší verzi rezervováno pro použití JIT překladačem)
0×ff nonnull_quick rychlá varianta instrukce nonnull (ve starší verzi rezervováno pro použití JIT překladačem)

11. Odkazy na Internetu

  1. Python Byte Code Instructions
    https://docs.python.org/re­lease/2.5.2/lib/bytecodes­.html
  2. Python 2.x: funkce range()
    https://docs.python.org/2/li­brary/functions.html#range
  3. Python 2.x: typ iterátor
    https://docs.python.org/2/li­brary/stdtypes.html#itera­tor-types
  4. Python break, continue and pass Statements
    http://www.tutorialspoint­.com/python/python_loop_con­trol.htm
  5. Python Bytecode: Fun With Dis
    http://akaptur.github.io/blog/2013/08/14/pyt­hon-bytecode-fun-with-dis/
  6. Python's Innards: Hello, ceval.c!
    http://tech.blog.aknin.na­me/category/my-projects/pythons-innards/
  7. Byterun
    https://github.com/nedbat/byterun
  8. Python Byte Code Instructions
    http://document.ihg.uni-duisburg.de/Documentation/Pyt­hon/lib/node56.html
  9. Python Byte Code Instructions
    https://docs.python.org/3­.2/library/dis.html#python-bytecode-instructions
  10. dis – Python module
    https://docs.python.org/2/li­brary/dis.html
  11. Comparison of Python virtual machines
    http://polishlinux.org/ap­ps/cli/comparison-of-python-virtual-machines/
  12. Lambda the Ultimate: Coroutines in Lua,
    http://lambda-the-ultimate.org/node/438
  13. Coroutines Tutorial,
    http://lua-users.org/wiki/CoroutinesTutorial
  14. Lua Coroutines Versus Python Generators,
    http://lua-users.org/wiki/LuaCorouti­nesVersusPythonGenerators
  15. Programming in Lua 9.1 – Coroutine Basics,
    http://www.lua.org/pil/9.1.html
  16. Wikipedia CZ: Koprogram,
    http://cs.wikipedia.org/wi­ki/Koprogram
  17. Wikipedia EN: Coroutine,
    http://en.wikipedia.org/wi­ki/Coroutine
  18. Programming in Lua (first edition)
    http://www.lua.org/pil/contents.html
  19. Programming in Lua: 6 – More about Functions
    http://www.lua.org/pil/6.html
  20. Lua Lanes,
    http://kotisivu.dnainternet­.net/askok/bin/lanes/
  21. Programming in Lua: 6.1 – Closures
    http://www.lua.org/pil/6.1.html
  22. Programming in Lua: 9.1 – Coroutine Basics
    http://www.lua.org/pil/9.1.html
  23. Programming in Lua: Numeric for
    http://www.lua.org/pil/4.3.4.html
  24. Programming in Lua: break and return
    http://www.lua.org/pil/4.4.html
  25. Programming in Lua: Tables
    http://www.lua.org/pil/2.5.html
  26. Programming in Lua: Table Constructors
    http://www.lua.org/pil/3.6.html
  27. Programovací jazyk Lua
    http://palmknihy.cz/web/kni­ha/programovaci-jazyk-lua-12651.htm
  28. Lua: Tables Tutorial
    http://lua-users.org/wiki/TablesTutorial
  29. Lua: Control Structure Tutorial
    http://lua-users.org/wiki/ControlStruc­tureTutorial
  30. Lua Types Tutorial
    http://lua-users.org/wiki/LuaTypesTutorial
  31. Goto Statement in Lua
    http://lua-users.org/wiki/GotoStatement
  32. Lua 5.2 sources
    http://www.lua.org/source/5.2/
  33. Lua 5.2 sources – lopcodes.h
    http://www.lua.org/source/5­.2/lopcodes.h.html
  34. Lua 5.2 sources – lopcodes.c
    http://www.lua.org/source/5­.2/lopcodes.c.html
  35. For-each Loop in Java
    http://www.leepoint.net/notes-java/flow/loops/foreach.html
  36. For Loop (Wikipedia)
    http://en.wikipedia.org/wiki/For_loop
  37. Heinz Rutishauser
    http://en.wikipedia.org/wi­ki/Heinz_Rutishauser
  38. Parrot
    http://www.parrot.org/
  39. Parrot languages
    http://www.parrot.org/languages
  40. Parrot Primer
    http://docs.parrot.org/pa­rrot/latest/html/docs/intro­.pod.html
  41. Parrot Opcodes
    http://docs.parrot.org/pa­rrot/latest/html/ops.html
  42. Parrot VM
    http://en.wikibooks.org/wi­ki/Parrot_Virtual_Machine
  43. Parrot Assembly Language
    http://www.perl6.org/archi­ve/pdd/pdd06_pasm.html
  44. Parrot Reference: Chapter 11 – Perl 6 and Parrot Essentials
    http://oreilly.com/perl/excerpts/perl-6-and-parrot-essentials/parrot-reference.html
  45. O-code
    http://en.wikipedia.org/wiki/O-code_machine
  46. 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
  47. The JVM Instruction Set
    http://mpdeboer.home.xs4a­ll.nl/scriptie/node14.html
  48. GC safe-point (or safepoint) and safe-region
    http://xiao-feng.blogspot.cz/2008/01/gc-safe-point-and-safe-region.html
  49. Safepoints in HotSpot JVM
    http://blog.ragozin.info/2012/10/sa­fepoints-in-hotspot-jvm.html
  50. Java theory and practice: Synchronization optimizations in Mustang
    http://www.ibm.com/develo­perworks/java/library/j-jtp10185/
  51. How to build hsdis
    http://hg.openjdk.java.net/jdk7/hot­spot/hotspot/file/tip/src/sha­re/tools/hsdis/README
  52. Java SE 6 Performance White Paper
    http://www.oracle.com/technet­work/java/6-performance-137236.html
  53. Lukas Stadler's Blog
    http://classparser.blogspot­.cz/2010/03/hsdis-i386dll.html
  54. How to build hsdis-amd64.dll and hsdis-i386.dll on Windows
    http://dropzone.nfshost.com/hsdis.htm
  55. PrintAssembly
    https://wikis.oracle.com/dis­play/HotSpotInternals/Prin­tAssembly
  56. The Java Virtual Machine Specification: 3.14. Synchronization
    http://docs.oracle.com/ja­vase/specs/jvms/se7/html/jvms-3.html#jvms-3.14
  57. 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
  58. 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
  59. 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
  60. Open Source ByteCode Libraries in Java
    http://java-source.net/open-source/bytecode-libraries
  61. ASM Home page
    http://asm.ow2.org/
  62. Seznam nástrojů využívajících projekt ASM
    http://asm.ow2.org/users.html
  63. ObjectWeb ASM (Wikipedia)
    http://en.wikipedia.org/wi­ki/ObjectWeb_ASM
  64. Java Bytecode BCEL vs ASM
    http://james.onegoodcooki­e.com/2005/10/26/java-bytecode-bcel-vs-asm/
  65. BCEL Home page
    http://commons.apache.org/bcel/
  66. Byte Code Engineering Library (před verzí 5.0)
    http://bcel.sourceforge.net/
  67. Byte Code Engineering Library (verze >= 5.0)
    http://commons.apache.org/pro­per/commons-bcel/
  68. BCEL Manual
    http://commons.apache.org/bcel/ma­nual.html
  69. Byte Code Engineering Library (Wikipedia)
    http://en.wikipedia.org/wiki/BCEL
  70. BCEL Tutorial
    http://www.smfsupport.com/sup­port/java/bcel-tutorial!/
  71. Bytecode Engineering
    http://book.chinaunix.net/spe­cial/ebook/Core_Java2_Volu­me2AF/0131118269/ch13lev1sec6­.html
  72. Bytecode Outline plugin for Eclipse (screenshoty + info)
    http://asm.ow2.org/eclipse/index.html
  73. Javassist
    http://www.jboss.org/javassist/
  74. Byteman
    http://www.jboss.org/byteman
  75. Java programming dynamics, Part 7: Bytecode engineering with BCEL
    http://www.ibm.com/develo­perworks/java/library/j-dyn0414/
  76. The JavaTM Virtual Machine Specification, Second Edition
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/VMSpec­TOC.doc.html
  77. The class File Format
    http://java.sun.com/docs/bo­oks/jvms/second_edition/html/Clas­sFile.doc.html
  78. javap – The Java Class File Disassembler
    http://docs.oracle.com/ja­vase/1.4.2/docs/tooldocs/win­dows/javap.html
  79. javap-java-1.6.0-openjdk(1) – Linux man page
    http://linux.die.net/man/1/javap-java-1.6.0-openjdk
  80. Using javap
    http://www.idevelopment.in­fo/data/Programming/java/mis­cellaneous_java/Using_javap­.html
  81. Examine class files with the javap command
    http://www.techrepublic.com/ar­ticle/examine-class-files-with-the-javap-command/5815354
  82. aspectj (Eclipse)
    http://www.eclipse.org/aspectj/
  83. Aspect-oriented programming (Wikipedia)
    http://en.wikipedia.org/wi­ki/Aspect_oriented_program­ming
  84. AspectJ (Wikipedia)
    http://en.wikipedia.org/wiki/AspectJ
  85. EMMA: a free Java code coverage tool
    http://emma.sourceforge.net/
  86. Cobertura
    http://cobertura.sourceforge.net/
  87. jclasslib bytecode viewer
    http://www.ej-technologies.com/products/jclas­slib/overview.html

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.