Hlavní navigace

Pohled pod kapotu JVM – přístup k prvkům složených datových typů v JVM, Lua VM a Python VM (pokračování)

Pavel Tišnovský

V dnešní části seriálu o Javě i o virtuálním stroji tohoto jazyka společně dokončíme téma, kterému jsme se věnovali již v minulém díle. Popíšeme si, jakým způsobem je v bajtkódu Python VM realizován přístup k prvkům složených datových typů, konkrétně k prvkům seznamů a n-tic.

Doba čtení: 24 minut

Sdílet

11. Okomentovaný bajtkód demonstračního příkladu Test24.py

12. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů

13. Obsah následující části seriálu

14. Odkazy na Internetu

1. Pohled pod kapotu JVM – přístup k prvkům složených datových typů v JVM, Lua VM a Python VM (pokračování)

V předcházející části tohoto seriálu jsme si vysvětlili, jakým způsobem se ve virtuálním stroji programovacího jazyka Java přistupuje k prvkům polí, což je vlastně jediný složený datový typ podporovaný již na úrovni bajtkódu. Na několika demonstračních příkladech jsme si ukázali čtení prvků z jednorozměrných i dvourozměrných polí, jakožto i zápis (či přesněji řečeno modifikaci) prvků v polích. Podobné demonstrační příklady byly použity i v případě programovacího jazyka Lua a Lua VM, v němž se sice nepoužívají klasická pole, ale koncepčně obecnější tabulky a asociativní pole. Ještě jsme si však neukázali způsob práce se složenými datovými typy v Pythonu a Python VM, což bude (alespoň doufejme) napraveno v následujících kapitolách.

2. Přístup k prvkům seznamů v Python VM

Pro přístup k prvkům seznamů i pro modifikaci seznamů se v Python VM používají tři instrukce bajtkódu. Tyto instrukce pracují se dvěma nebo třemi operandy, které samozřejmě musí být uloženy na zásobníku operandů. Instrukce BINARY_SUBSCR slouží pro přečtení prvku ze seznamu, instrukce STORE_SUBSCR pro uložení nové hodnoty prvku do seznamu a konečně instrukce DELETE_SUBSCR pro odstranění prvku ze seznamu. Hodnota uložená na vrcholu zásobníku operandů slouží ve všech případech k určení indexu čteného/zapisovaného/mazaného prvku:

# Instrukce Význam
1 BINARY_SUBSCR provádí operaci TOS = 2OS[TOS]
2 STORE_SUBSCR provádí operaci 2OS[TOS] = 3OS
3 DELETE_SUBSCR provádí operaci del 2OS[TOS]

Význam zkratek TOS, 2OS3OS je vysvětlen v další tabulce:

# Zkratka/zápis Význam
1 TOS Top Of Stack – prvek uložený na vrcholu zásobníku operandů
2 2OS 2nd Of Stack – prvek uložený těsně pod TOS
3 3OS 3rd Of Stack – prvek uložený těsně pod 2OS
4 2OS[TOS] Prvek s indexem uloženým na TOS, který je součástí seznamu, jehož reference je v 2OS

3. Demonstrační příklad Test21.py: přístup k prvkům jednorozměrného seznamu

V prvním demonstračním příkladu nazvaném Test21.py je implementována čtveřice funkcí readItem(), writeItem(), modifyListItems()printList(). Ve funkci readItem() se nejprve přečte prvek uložený v seznamu na daném indexu a posléze se hodnota tohoto prvku použije jako návratová hodnota celé funkce. Ve funkci writeItem() dochází k zápisu nové hodnoty do zadaného prvku seznamu a konečně se ve funkci modifyListItems() zvýší hodnoty všech prvků uložených v seznamu o jedničku:

#
# Pristup k prvkum (jednorozmerneho) seznamu.
#
 
 
 
#
# Nejjednodussi operace - precteni hodnoty prvku ze seznamu.
#
def readItem(list_variable, index):
    return list_variable[index]
 
 
 
#
# Dalsi jednoducha operace - zapis hodnoty prvku do seznamu.
#
def writeItem(list_variable, index, value):
    list_variable[index] = value
 
 
 
#
# Zvyseni hodnoty vsech prvku seznamu.
#
def modifyListItems(list_variable):
    for i in range(0, len(list_variable)):
        list_variable[i] = list_variable[i] + 1
 
 
 
#
# Tisk vsech prvku seznamu.
#
def printList(list_variable):
    for i in range(0, len(list_variable)):
        print(readItem(list_variable, i))
 
 
 
#
# Test.
#
def main():
    list_variable = [1, 2, 3]
 
    print("Original list:")
    printList(list_variable)
    print
 
    writeItem(list_variable, 1, 42)
    print("2nd item have been changed:")
    printList(list_variable)
    print
 
    modifyListItems(list_variable)
    print("Modified list:")
    printList(list_variable)
    print
 
 
 
#
# Ukazka disasembleru.
#
def disassemble():
    from dis import dis
 
    print("\nreadItem:")
    dis(readItem)
 
    print("\nwriteItem:")
    dis(writeItem)
 
    print("\nmodifyListItems:")
    dis(modifyListItems)
 
main()
 
 
#disassemble()

Po spuštění demonstračního příkladu Test22.py se na standardní výstup vypíše výsledek volání funkcí z main():

Original list:
1
2
3
 
2nd item have been changed:
1
42
3
 
Modified list:
2
43
4
 

4. Okomentovaný bajtkód demonstračního příkladu Test21.py

Podívejme se nyní na strukturu bajtkódu vzniklého po překladu zdrojového kódu demonstračního příkladu Test21.py. V bajtkódu funkce readItem() se používá již ve druhé kapitole popsaná instrukce BINARY_SUBSCR, které se však na zásobník operandů musí připravit dvojice operandů – reference na seznam a index prvku:

readItem:
 11           0 LOAD_FAST      0            // načíst první parametr "list_variable" a uložit ho na zásobník
              3 LOAD_FAST      1            // načíst druhý parametr "index" a uložit ho na zásobník
              6 BINARY_SUBSCR               // načtení prvku ze seznamu a uložení na zásobník
              7 RETURN_VALUE                // vrácení načteného prvku

Podobným způsobem je strukturován i bajtkód funkce writeItem(), ovšem s tím rozdílem, že se pro instrukci STORE_SUBSCR musí na zásobníku operandů připravit tři operandy: reference na seznam, index zapisovaného prvku a samozřejmě i zapisovaná hodnota:

writeItem:
 19           0 LOAD_FAST      2            // načíst třetí parametr (nová hodnota prvku)
              3 LOAD_FAST      0            // načíst první parametr "list_variable a uložit ho na zásobník
              6 LOAD_FAST      1            // načíst druhý parametr "index" a uložit ho na zásobník
              9 STORE_SUBSCR                // uložení prvku do seznamu
             10 LOAD_CONST     0            // hodnota vracená funkcí (None)
             13 RETURN_VALUE                // vrácení hodnoty None

Bajtkód funkce modifyListItems() je podle očekávání nejsložitější a využívá se v něm jak instrukce BINARY_SUBSCR, tak i instrukce STORE_SUBSCR; obě tyto instrukce jsou volány v počítané programové smyčce:

modifyListItems:
 27           0 SETUP_LOOP     47 (to 50)   // příprava programové smyčky (adresa konce smyčky)
              3 LOAD_GLOBAL    0 (range)    // reference na funkci "range"
              6 LOAD_CONST     1 (0)        // první parametr funkce "range"
              9 LOAD_GLOBAL    1 (len)      // reference na funkci "len"
             12 LOAD_FAST      0            // načíst parametr "list_variable"
             15 CALL_FUNCTION  1            // zavolat funkci len(list_variable)
             18 CALL_FUNCTION  2            // zavolat funkci range(0, len(list_variable))
             21 GET_ITER                    // iterátor pro programovou smyčku
 
        --   22 FOR_ITER       24 (to 49)   // začátek těla programové smyčky
             25 STORE_FAST     1 (i)        // uložit hodnotu počitadla na zásobník
 28          28 LOAD_FAST      0 (list_variable)
             31 LOAD_FAST      1 (i)        // počitadlo smyčky = index do seznamu
             34 BINARY_SUBSCR               // načtení prvku ze seznamu a uložení na zásobník
             35 LOAD_CONST     2 (1)        // konstanta přičítaná k prvku
             38 BINARY_ADD
             39 LOAD_FAST      0 (list_variable)
             42 LOAD_FAST      1 (i)
             45 STORE_SUBSCR                // uložení prvku do seznamu
             46 JUMP_ABSOLUTE  22           // skok na začátek těla smyčky (další iterace)
 
        --   49 POP_BLOCK                   // úprava obsahu zásobníku po ukončení smyčky
        --   50 LOAD_CONST     0            // hodnota vracená funkcí (None)
             53 RETURN_VALUE                // vrácení hodnoty None

5. Demonstrační příklad Test22.py: přístup k prvkům seznamu obsahujícího podseznamy

V dnešním druhém demonstračním příkladu, který se jmenuje Test22.py, se taktéž provádí operace se seznamy, ovšem tyto seznamy obsahují jako své prvky další podseznamy. S takto vytvořenou složenou datovou strukturou je možné pracovat jako s běžným dvourozměrným polem, i když ve skutečnosti jsou možnosti „seznamu seznamů“ mnohem větší, než v případě rigidních polí. Opět se zaměříme na trojici funkcí nazvaných readItem(), writeItem()sum() (součet všech prvků seznamu seznamů):

#
# Pristup k prvkum seznamu obsahujiciho podseznamy.
#
 
 
 
#
# Nejjednodussi operace - precteni hodnoty prvku ze seznamu seznamu.
#
def readItem(list_of_lists, index1, index2):
    return list_of_lists[index1][index2]
 
 
 
#
# Dalsi jednoducha operace - zapis hodnoty prvku do seznamu seznamu.
#
def writeItem(list_of_lists, index1, index2, value):
    list_of_lists[index1][index2] = value
 
 
 
#
# Vypocet sumy vsech prvku.
#
def sum(list_of_lists):
    sum = 0
    for sublist in list_of_lists:
        for item in sublist:
            sum = sum + item
    return sum
 
 
 
#
# Tisk vsech prvku.
#
def printList(list_of_lists):
    for sublist in list_of_lists:
        for item in sublist:
            print(item),
        print
 
 
 
#
# Test.
#
def main():
    list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
 
    printList(list_of_lists)
    print("Sum = " + str(sum(list_of_lists)))
    print
 
    writeItem(list_of_lists, 1, 1, 0)
    printList(list_of_lists)
 
    print("Sum = " + str(sum(list_of_lists)))
 
 
 
#
# Ukazka disasembleru.
#
def disassemble():
    from dis import dis
 
    print("\nreadItem:")
    dis(readItem)
 
    print("\nwriteItem:")
    dis(writeItem)
 
    print("\nsum:")
    dis(sum)
 
main()
 
 
#disassemble()

Po spuštění tohoto demonstračního příkladu se na standardní výstup nejprve vypíše původní hodnota „dvourozměrného pole“:

1 2 3
4 5 6
7 8 9
Sum = 45

Po modifikaci prostředního prvku se vypíše nová hodnota pole i nově vypočtená suma:

1 2 3
4 0 6
7 8 9
Sum = 40

6. Okomentovaný bajtkód demonstračního příkladu Test22.py

Bajtkód přeložené funkce readItem() je zajímavý především z toho hlediska, že je z něho jasně patrné, že se se „seznamem seznamů“ skutečně pracuje jako s hierarchickou datovou strukturou. První instrukcí BINARY_SUBSCR je vybrán podseznam uložený na indexu „index1“ a posléze je z tohoto seznamu již přečten konkrétní prvek na indexu „index2“:

readItem:
 11           0 LOAD_FAST      0            // načíst první parametr "list_of_lists" a uložit ho na zásobník
              3 LOAD_FAST      1            // načíst druhý parametr "index1" a uložit ho na zásobník
              6 BINARY_SUBSCR               // načtení prvku z n-tice (což je pod-n-tice)
              7 LOAD_FAST      2            // načíst třetí parametr "index2" a uložit ho na zásobník
             10 BINARY_SUBSCR               // načtení prvku z pod-n-tice a uložení na zásobník
             11 RETURN_VALUE                // vrácení načteného prvku

V bajtkódu funkce writeItem() je situace obdobná – první instrukcí BINARY_SUBSCR se získá reference na příslušný podseznam, s nímž se již provádí operace zápisu s využitím instrukce STORE_SUBSCR:

writeItem:
 19           0 LOAD_FAST      3            // načíst čtvrtý parametr (nová hodnota prvku)
              3 LOAD_FAST      0            // načíst první parametr "list_of_lists" a uložit ho na zásobník
              6 LOAD_FAST      1            // načíst druhý parametr "index1" a uložit ho na zásobník
              9 BINARY_SUBSCR
             10 LOAD_FAST      2            // načíst třetí parametr "index2" a uložit ho na zásobník
             13 STORE_SUBSCR                // uložení nové hodnoty prvku do seznamu
             14 LOAD_CONST     0            // hodnota vracená funkcí (None)
             17 RETURN_VALUE                // vrácení hodnoty None

V bajtkódu funkce sum() je implementována dvojice do sebe vnořených programových smyček a můžeme zde vidět použití iterátorů namísto instrukce BINARY_SUBSCR (samotný iterátor postupně vrací jednotlivé podseznamy ve vnější smyčce, popř. již konkrétní prvky ve smyčce vnitřní):

sum:
 27           0 LOAD_CONST     1 (0)        // počáteční hodnota lokální proměnné "sum"
              3 STORE_FAST     1 (sum)      // inicializace lokální proměnné "sum"
 
 28           6 SETUP_LOOP     41 (to 50)   // příprava vnější programové smyčky (adresa konce smyčky)
              9 LOAD_FAST      0            // načíst parametr "list_of_lists"
             12 GET_ITER                    // iterátor pro vnější programovou smyčku
        --   13 FOR_ITER       33 (to 49)   // začátek těla vnější programové smyčky
             16 STORE_FAST     2 (sublist)  // uložit aktuální hodnotu řídicí proměnné
 
 29          19 SETUP_LOOP     24 (to 46)   // příprava vnitřní programové smyčky (adresa konce smyčky)
             22 LOAD_FAST      2 (sublist)  // načíst aktuální hodnotu řídicí proměnné
             25 GET_ITER                    // iterátor pro vnitřní programovou smyčku
        --   26 FOR_ITER       16 (to 45)   // začátek těla vnitřní programové smyčky
             29 STORE_FAST     3 (item)     // získali jsme hodnotu prvku seznamu!
 
 30          32 LOAD_FAST      1 (sum)      // výpočet prováděný ve vnitřní programové smyčce
             35 LOAD_FAST      3 (item)     // načíst prvek
             38 BINARY_ADD                  // sum = sum + item
             39 STORE_FAST     1 (sum)      // nová hodnota lokální proměnné "sum"
             42 JUMP_ABSOLUTE  26           // skok na začátek vnitřní programové smyčky
 
        --   45 POP_BLOCK                   // úprava obsahu zásobníku po ukončení smyčky
        --   46 JUMP_ABSOLUTE  13           // skok na začátek vnější programové smyčky
 
        --   49 POP_BLOCK                   // úprava obsahu zásobníku po ukončení smyčky
 31     --   50 LOAD_FAST      1 (sum)      // hodnota vracená funkcí (proměnná "sum")
             53 RETURN_VALUE                // vrátit hodnotu lokální proměnné "sum"

Trojice instrukcí:

LOAD_FAST seznam_či_n_tice
GET_ITER
FOR_ITER       instrukce za koncem smyčky

je pro Python VM typická, stejně jako ukončení této smyčky:

JUMP_ABSOLUTE  adresa instrukce FOR_ITER
POP_BLOCK

To jsme již ostatně viděli i v několika demonstračních příkladech popisovaných předminule.

7. Přístup k prvkům n-tic v Python VM

Kromě seznamů podporuje programovací jazyk Python i použití n-tic (tuples), které se od seznamu mj. liší i tím, že jsou neměnitelné (immutable). Koncept neměnitelných hodnot umožňuje provádění různých typů optimalizací a nejinak je tomu i v případě n-tic. Zajímavé přitom je, že pro získání prvku z n-tice se v bajtkódu používá stejná instrukce, jako pro získání prvku ze seznamu. To mj. znamená, že tato kapitola bude velmi krátká, protože nám bude stačit si (znovu) popsat jedinou instrukci BINARY_SUBSCR:

# Instrukce Význam
1 BINARY_SUBSCR provádí operaci TOS = 2OS[TOS]

8. Demonstrační příklad Test23.py: přístup k prvkům jednorozměrné n-tice

V dnešním třetím demonstračním příkladu Test23.py si práci s n-ticemi otestujeme na funkci readItem(), která se však nijak neliší od stejnojmenné funkce z příkladu Test21.py:

#
# Pristup k prvkum (jednorozmerne) n-tice.
#
 
 
 
#
# Nejjednodussi operace - precteni hodnoty prvku z n-tice.
#
def readItem(tuple_variable, index):
    return tuple_variable[index]
 
 
 
#
# Tisk vsech prvku n-tice.
#
def printTuple(tuple_variable):
    for i in range(0, len(tuple_variable)):
        print(readItem(tuple_variable, i))
 
 
 
#
# Test.
#
def main():
    tuple_variable = (1, 2, 3)
 
    print("Original tuple:")
    printTuple(tuple_variable)
 
 
 
#
# Ukazka disasembleru.
#
def disassemble():
    from dis import dis
 
    print("\nreadItem:")
    dis(readItem)
 
main()
 
 
#disassemble()

Na standardní výstup se po spuštění tohoto příkladu vypíšou následující čtyři řádky:

Original tuple:
1
2
3

9. Okomentovaný bajtkód demonstračního příkladu Test23.py

Čtenáře pravděpodobně nepřekvapí, že bajtkód funkce readItem() zůstal nezměněn. Ostatně jeden z důvodů, proč je v bajtkódech Lua VM a Python VM menší množství instrukcí, než v případě JVM, spočívá právě v dynamickém typování, a tím pádem i v možnosti použití jediné instrukce (zde konkrétně BINARY_SUBSCR) s několika datovými typy:

readItem:
 11           0 LOAD_FAST      0            // načíst první parametr "tuple_variable" a uložit ho na zásobník
              3 LOAD_FAST      1            // načíst druhý parametr "index" a uložit ho na zásobník
              6 BINARY_SUBSCR               // načtení prvku z n-tice a uložení na zásobník
              7 RETURN_VALUE                // vrácení načteného prvku

10. Demonstrační příklad Test24.py: přístup k prvkům n-tice obsahující další n-tice

Jen pro úplnost si ukažme zdrojový kód dnešního posledního demonstračního příkladu Test24.py, v němž se pracuje s prvky n-tic, které obsahují další n-tice, takže výsledkem je buď neměnitelné dvourozměrné pole či nepravidelné pole. n-tice jsou neměnitelné, proto zde není implementována ani funkce writeItem():

#
# Pristup k prvkum n-tice obsahujici pod n-tice.
#
 
 
 
#
# Nejjednodussi operace - precteni hodnoty prvku z n-tice.
#
def readItem(tuple_of_tuples, index1, index2):
    return tuple_of_tuples[index1][index2]
 
 
 
#
# Vypocet sumy vsech prvku.
#
def sum(tuple_of_tuples):
    sum = 0
    for subtuple in tuple_of_tuples:
        for item in subtuple:
            sum = sum + item
    return sum
 
 
 
#
# Tisk vsech prvku.
#
def printTuple(tuple_of_tuples):
    for subtuple in tuple_of_tuples:
        for item in subtuple:
            print(item),
        print
 
 
 
#
# Test.
#
def main():
    tuple_of_tuples = ((1, 2, 3), (4, 5, 6), (7, 8, 9))
 
    printTuple(tuple_of_tuples)
    print("Sum = " + str(sum(tuple_of_tuples)))
    print
 
#
# Ukazka disasembleru.
#
def disassemble():
    from dis import dis
 
    print("\nreadItem:")
    dis(readItem)
 
    print("\nsum:")
    dis(sum)
 
main()
 
 
disassemble()
1 2 3
4 5 6
7 8 9
Sum = 45

11. Okomentovaný bajtkód demonstračního příkladu Test24.py

Bajtkód funkce readItem() z příkladu Test24.py je shodný s bajtkódem téže funkce z příkladu Test22.py:

readItem:
 11           0 LOAD_FAST      0            // načíst první parametr "tuple_of_tuples" a uložit ho na zásobník
              3 LOAD_FAST      1            // načíst druhý parametr "index1" a uložit ho na zásobník
              6 BINARY_SUBSCR               // načtení prvku z n-tice (což je pod-n-tice)
              7 LOAD_FAST      2            // načíst třetí parametr "index2" a uložit ho na zásobník
             10 BINARY_SUBSCR               // načtení prvku z pod-n-tice a uložení na zásobník
             11 RETURN_VALUE                // vrácení načteného prvku

Podobně je tomu i u bajtkódu funkce sum(), o čemž se ostatně můžete sami jednoduše přesvědčit:

CIF-tip-bezpecnost

sum:
 19           0 LOAD_CONST     1 (0)        // počáteční hodnota lokální proměnné "sum"
              3 STORE_FAST     1 (sum)      // inicializace lokální proměnné "sum"
 
 20           6 SETUP_LOOP     41 (to 50)   // příprava vnější programové smyčky (adresa konce smyčky)
              9 LOAD_FAST      0            // načíst parametr "tuple_of_tuples"
             12 GET_ITER                    // iterátor pro vnější programovou smyčku
        --   13 FOR_ITER       33 (to 49)   // začátek těla vnější programové smyčky
             16 STORE_FAST     2 (subtuple) // uložit aktuální hodnotu řídicí proměnné
 
 21          19 SETUP_LOOP     24 (to 46)   // příprava vnitřní programové smyčky (adresa konce smyčky)
             22 LOAD_FAST      2 (subtuple) // načíst aktuální hodnotu řídicí proměnné
             25 GET_ITER                    // iterátor pro vnitřní programovou smyčku
        --   26 FOR_ITER       16 (to 45)   // začátek těla vnitřní programové smyčky
             29 STORE_FAST     3 (item)     // získali jsme hodnotu prvku n-tice!
 
 22          32 LOAD_FAST      1 (sum)      // výpočet prováděný ve vnitřní programové smyčce
             35 LOAD_FAST      3 (item)     // načíst prvek
             38 BINARY_ADD                  // sum = sum + item
             39 STORE_FAST     1 (sum)      // nová hodnota lokální proměnné "sum"
             42 JUMP_ABSOLUTE  26           // skok na začátek vnitřní programové smyčky
 
        --   45 POP_BLOCK                   // úprava obsahu zásobníku po ukončení smyčky
        --   46 JUMP_ABSOLUTE  13           // skok na začátek vnější programové smyčky
 
        --   49 POP_BLOCK                   // úprava obsahu zásobníku po ukončení smyčky
 23     --   50 LOAD_FAST      1 (sum)      // hodnota vracená funkcí (proměnná "sum")
             53 RETURN_VALUE                // vrátit hodnotu lokální proměnné "sum"

12. Repositář se zdrojovými kódy všech dnešních demonstračních příkladů

Všechny čtyři dnes popsané a využité demonstrační příklady (naprogramované v Pythonu, dnes nikoli v Javě ani Lue :-) byly uloženy 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:

13. Obsah následující části seriálu

V následující části tohoto seriálu si ukážeme, jak se v bajtkódech virtuálních strojů JVM, Lua VM a Python VM pracuje s asociativními poli, popř. se strukturami, které se tomuto datovému typu nejvíce přibližují. Uvidíme, že i v tomto případě se možnosti jednotlivých popisovaných JVM od sebe odlišují, a to především v úrovni abstrakce. Nejmenší množství operací s asociativními poli nabízí JVM, ovšem v Lua VM i Python VM je operace s tímto velmi užitečným datovým typem podporována velmi dobře.

14. Odkazy na Internetu

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