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í)

1. 7. 2014
Doba čtení: 24 minut

Sdílet

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.

Obsah

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í)

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

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

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

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

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

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

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

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

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

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:

ict ve školství 24

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

Autor článku

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