Hlavní navigace

Pohled pod kapotu JVM – práce s parametry funkcí a složené datové typy v JVM, Lua VM a Python VM

17. 6. 2014
Doba čtení: 44 minut

Sdílet

Dnešní část seriálu o programovacím jazyku Java i o virtuálním stroji Javy je opět věnována popisu společných vlastností, ale i rozdílů mezi bajtkódy JVM, Lua VM a Pythonu. Dnes se konkrétně budeme zabývat způsobem předávání a vyzvedávání parametrů funkcí/metod a taktéž prací se složenými datovými typy.

Obsah

1. Pohled pod kapotu JVM – práce s parametry funkcí a složené datové typy v JVM, Lua VM a Python VM

2. Předávání parametrů metodám v JVM

3. Demonstrační příklad Test17.java: předávání parametrů typu int

4. Demonstrační příklad Test18.java: předávání parametrů typu float

5. Předávání parametrů funkcím v Lua VM: demonstrační příklad Test17.lua

6. Předávání parametrů funkcím v Python VM: demonstrační příklad Test17.py

7. Složené datové typy v JVM, Lua VM a Python VM

8. Demonstrační příklad Test19.java: konstrukce jednorozměrných polí

9. Demonstrační příklad Test20.java: konstrukce vícerozměrných polí

10. Demonstrační příklad Test19.lua: vytvoření tabulky

11. Demonstrační příklad Test20.lua: vytvoření asociativního pole

12. Demonstrační příklad Test19.py: vytvoření seznamu

13. Demonstrační příklad Test20.py: vytvoření n-tice

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

15. Odkazy na Internetu

1. Pohled pod kapotu JVM – práce s parametry funkcí a složené datové typy v JVM, Lua VM a Python VM

V posledních několika částech seriálu o programovacím jazyce Java i o vlastnostech virtuálního stroje tohoto jazyka jsme si na mnoha demonstračních příkladech ukázali, jakým způsobem se do instrukcí bajtkódu JVM, Python VM i Lua VM překládají některé základní programové konstrukce, konkrétně aritmetické i logické výrazy, rozhodovací (větvící) konstrukce typu if-thenif-then-else, programové smyčky typu while (s podmínkou vyhodnocovanou na začátku každé iterace) i do-while/repeat-until (s podmínkou vyhodnocovanou na konci každé iterace) a konečně počítané programové smyčky typu for. Prozatím jsme si však podrobněji nevysvětlili další důležitou součást virtuálních strojů – postup použitý při předávání parametrů funkcím nebo metodám a následné zpracování těchto parametrů. Touto problematikou se budeme zabývat v první polovině dnešního článku (kapitoly 2 až 6).

Druhá polovina dnešního článku (konkrétně kapitola 7 a samozřejmě taktéž navazující kapitoly) bude věnována sice dosti odlišnému, ovšem taktéž důležitému tématu. Budeme se v ní totiž zabývat způsobem práce se složenými datovými typy a podporou těchto typů v jednotlivých bajtkódech. V případě JVM je podporován datový typ pole, zatímco Python VM naproti tomu podporuje seznamyn-tice a Lua VM tabulky jakožto zobecnění původních polí. Toto téma tedy bude dosti zajímavé, protože se zde opět ukážou významné rozdíly mezi jednotlivými virtuálními stroji. Tyto rozdíly samozřejmě poměrně úzce souvisí i se sémantikou programovacích jazyků, které tyto virtuální stroje primárně využívají.

2. Předávání parametrů metodám v JVM

Nejprve si popíšeme způsob předávání parametrů volaným metodám. Začneme popisem JVM. Zde je při volání metod použit zásobník operandů, na nějž se ve volající metodě uloží všechny potřebné parametry. V metodě volané se k těmto parametrům přistupuje jako k lokálním proměnným, což konkrétně znamená, že prvních n lokálních proměnných odpovídá n parametrům metody (u nestatických metod je prvním parametrem samozřejmě this). Záleží jen na konkrétní implementaci virtuálního stroje Javy, jakým způsobem dojde při volání metody ke konverzi mezi zásobníkem operandů volající metody a lokálními parametry metody volané.

Z hlediska bajtkódu se pro další práci s lokálními proměnnými používají instrukce sloužící pro přesuny dat mezi lokálními proměnnými a případnými parametry metody na jedné straně a zásobníkem operandů na straně druhé. Je pravděpodobně zřejmé, že způsob adresace dat bude odlišný na straně lokálních proměnných i na straně zásobníku operandů. V případě lokálních proměnných+parametrů je totiž každý prvek určen svým indexem, který je nedílnou součástí instrukce (způsob práce s lokálními parametry tedy připomíná práci s polem, jehož prvky lze snadno indexovat). U zásobníku operandů se vždy pracuje s prvkem umístěným na vrcholu zásobníku (TOS=Top Of Stack); ostatní prvky umístěné pod TOS jsou nedostupné.

Všechny instrukce tohoto typu se jmenují *load# popř. *store#, přičemž za hvězdičku se doplňuje první písmeno datového typu a za křížek se v některých případech udává index do oblasti lokálních proměnných – to ovšem jen v případě těch instrukcí, u nichž je index součástí instrukčního slova. V opačném případě je index uložen ve formě jednoho bajtu ihned za instrukčním kódem. Pokud je nutné adresovat prvek s indexem větším než 255 (typicky u začátečnických programů v velkým množstvím lokálních proměnných v jediné metodě :-)), lze před instrukci typu load/store vložit prefix wide – poté lze použít šestnáctibitový index namísto indexu osmibitového. Nyní nás budou zajímat pouze instrukce pro načtení hodnoty parametru/lokální proměnné a její uložení na zásobník operandů:

# Instrukce Opkód Data1 Typ dat Popis
01 iload 15 index int načtení lokální proměnné typu int z pozice „index“ a její uložení na TOS
02 lload 16 index long načtení lokální proměnné typu long z pozice „index“ a její uložení na TOS
03 fload 17 index float načtení lokální proměnné typu float z pozice „index“ a její uložení na TOS
04 dload 18 index double načtení lokální proměnné typu double z pozice „index“ a její uložení na TOS
05 aload 19 index reference načtení lokální proměnné typu reference na objekt z pozice „index“ a její uložení na TOS
06 iload0 1A   int načtení lokální proměnné typu int z pozice číslo 0 a její uložení na TOS
07 iload1 1B   int načtení lokální proměnné typu int z pozice číslo 1 a její uložení na TOS
08 iload2 1C   int načtení lokální proměnné typu int z pozice číslo 2 a její uložení na TOS
09 iload3 1D   int načtení lokální proměnné typu int z pozice číslo 3 a její uložení na TOS
10 lload0 1E   long načtení lokální proměnné typu long z pozice číslo 0 a její uložení na TOS
11 lload1 1F   long načtení lokální proměnné typu long z pozice číslo 1 a její uložení na TOS
12 lload2 20   long načtení lokální proměnné typu long z pozice číslo 2 a její uložení na TOS
13 lload3 21   long načtení lokální proměnné typu long z pozice číslo 3 a její uložení na TOS
14 fload0 22   float načtení lokální proměnné typu float z pozice číslo 0 a její uložení na TOS
15 fload1 23   float načtení lokální proměnné typu float z pozice číslo 1 a její uložení na TOS
16 fload2 24   float načtení lokální proměnné typu float z pozice číslo 2 a její uložení na TOS
17 fload3 25   float načtení lokální proměnné typu float z pozice číslo 3 a její uložení na TOS
18 dload0 26   double načtení lokální proměnné typu double z pozice číslo 0 a její uložení na TOS
19 dload1 27   double načtení lokální proměnné typu double z pozice číslo 1 a její uložení na TOS
20 dload2 28   double načtení lokální proměnné typu double z pozice číslo 2 a její uložení na TOS
21 dload3 29   double načtení lokální proměnné typu double z pozice číslo 3 a její uložení na TOS
22 aload0 2A   reference načtení lokální proměnné typu reference na objekt z pozice číslo 0 a její uložení na TOS
23 aload1 2B   reference načtení lokální proměnné typu reference na objekt z pozice číslo 1 a její uložení na TOS
24 aload2 2C   reference načtení lokální proměnné typu reference na objekt z pozice číslo 2 a její uložení na TOS
25 aload3 2D   reference načtení lokální proměnné typu reference na objekt z pozice číslo 3 a její uložení na TOS

Zajímavé je, že většina výše zmíněných instrukcí vlastně existuje pouze proto, aby došlo k redukci celkové velikosti bajtkódu, a to zejména při práci s metodami majícími malý počet parametrů i malý počet lokálních proměnných (ušetří se vždy jeden bajt za operačním kódem instrukce).

3. Demonstrační příklad Test17.java: předávání parametrů typu int

Vzhledem k tomu, že JVM, jakožto i programovací jazyk Java, používá statické typování, ukážeme si způsob předávání parametrů volaným metodám na dvojici demonstračních příkladů. V prvním demonstračním příkladu se budou metodám předávat parametry typu int. Za povšimnutí stojí především již zmíněný způsob optimalizace, konkrétně použití instrukcí iload_x pro načtení prvních (až čtyř) parametrů:

/**
 * Ukazka predavani parametru typu int do volanych statickych metod.
 */
public class Test17 {
 
    /**
     * Metoda bez parametru.
     */
    public static int test0i() {
        return 42;
    }
 
    /**
     * Metoda s jednim parametrem typu int.
     */
    public static int test1i(int a) {
        return a;
    }
 
    /**
     * Metoda se dvema parametry typu int
     */
    public static int test2i(int a, int b) {
        return a + b;
    }
 
    /**
     * Metoda se tremi parametry typu int
     */
    public static int test3i(int a, int b, int c) {
        return a + b + c;
    }
 
    /**
     * Metoda se ctyrmi parametry typu int
     */
    public static int test4i(int a, int b, int c, int d) {
        return a + b + c + d;
    }
 
    /**
     * Metoda s peti parametry typu int
     */
    public static int test5i(int a, int b, int c, int d, int e) {
        return a + b + c + d + e;
    }
 
    /**
     * Metoda se sesti parametry typu int
     */
    public static int test6i(int a, int b, int c, int d, int e, int f) {
        return a + b + c + d + e + f;
    }
 
    /**
     * Vse je nutne otestovat.
     */
    public static void main(String[] args) {
        System.out.println(test0i());
        System.out.println(test1i(1));
        System.out.println(test2i(1, 2));
        System.out.println(test3i(1, 2, 3));
        System.out.println(test4i(1, 2, 3, 4));
        System.out.println(test5i(1, 2, 3, 4, 5));
        System.out.println(test6i(1, 2, 3, 4, 5, 6));
    }
}

Podívejme se nyní na vygenerovaný a okomentovaný bajtkód:

Compiled from "Test17.java"
public class Test17 extends java.lang.Object{
 
public static int test0i();
  Code:
   0:   bipush  42      // uložení celočíselné konstanty 42 na TOS
   2:   ireturn         // vrácení hodnoty typu int uložené na TOS
 
public static int test1i(int);
  Code:
   0:   iload_0         // uložení hodnoty prvního parametru na zásobník
   1:   ireturn         // vrácení hodnoty typu int uložené na TOS
 
public static int test2i(int, int);
  Code:
   0:   iload_0         // uložení hodnoty prvního parametru na zásobník
   1:   iload_1         // uložení hodnoty druhého parametru na zásobník
   2:   iadd
   3:   ireturn         // vrácení hodnoty typu int uložené na TOS
 
public static int test3i(int, int, int);
  Code:
   0:   iload_0         // uložení hodnoty prvního parametru na zásobník
   1:   iload_1         // uložení hodnoty druhého parametru na zásobník
   2:   iadd
   3:   iload_2         // uložení hodnoty třetího parametru na zásobník
   4:   iadd
   5:   ireturn         // vrácení hodnoty typu int uložené na TOS
 
public static int test4i(int, int, int, int);
  Code:
   0:   iload_0         // uložení hodnoty prvního parametru na zásobník
   1:   iload_1         // uložení hodnoty druhého parametru na zásobník
   2:   iadd
   3:   iload_2         // uložení hodnoty třetího parametru na zásobník
   4:   iadd
   5:   iload_3         // uložení hodnoty čtvrtého parametru na zásobník
   6:   iadd
   7:   ireturn         // vrácení hodnoty typu int uložené na TOS
 
public static int test5i(int, int, int, int, int);
  Code:
   0:   iload_0         // uložení hodnoty prvního parametru na zásobník
   1:   iload_1         // uložení hodnoty druhého parametru na zásobník
   2:   iadd
   3:   iload_2         // uložení hodnoty třetího parametru na zásobník
   4:   iadd
   5:   iload_3         // uložení hodnoty čtvrtého parametru na zásobník
   6:   iadd
   7:   iload   4       // uložení hodnoty pátého parametru na zásobník
   9:   iadd
   10:  ireturn         // vrácení hodnoty typu int uložené na TOS
 
public static int test6i(int, int, int, int, int, int);
  Code:
   0:   iload_0         // uložení hodnoty prvního parametru na zásobník
   1:   iload_1         // uložení hodnoty druhého parametru na zásobník
   2:   iadd
   3:   iload_2         // uložení hodnoty třetího parametru na zásobník
   4:   iadd
   5:   iload_3         // uložení hodnoty čtvrtého parametru na zásobník
   6:   iadd
   7:   iload   4       // uložení hodnoty pátého parametru na zásobník
   9:   iadd
   10:  iload   5       // uložení hodnoty šestého parametru na zásobník
   12:  iadd
   13:  ireturn         // vrácení hodnoty typu int uložené na TOS
 
public static void main(java.lang.String[]);
  Code:
   0:   getstatic       #2;  // Field java/lang/System.out:Ljava/io/PrintStream;
   3:   invokestatic    #3;  // Method test0i:()I
   6:   invokevirtual   #4;  // Method java/io/PrintStream.println:(I)V
 
   9:   getstatic       #2;  // Field java/lang/System.out:Ljava/io/PrintStream;
   12:  iconst_1             // první argument metody na zásobník
   13:  invokestatic    #5;  // Method test1i:(I)I
   16:  invokevirtual   #4;  // Method java/io/PrintStream.println:(I)V
 
   19:  getstatic       #2;  // Field java/lang/System.out:Ljava/io/PrintStream;
   22:  iconst_1             // první argument metody na zásobník
   23:  iconst_2             // druhý argument metody na zásobník
   24:  invokestatic    #6;  // Method test2i:(II)I
   27:  invokevirtual   #4;  // Method java/io/PrintStream.println:(I)V
 
   30:  getstatic       #2;  // Field java/lang/System.out:Ljava/io/PrintStream;
   33:  iconst_1             // první argument metody na zásobník
   34:  iconst_2             // druhý argument metody na zásobník
   35:  iconst_3             // třetí argument metody na zásobník
   36:  invokestatic    #7;  // Method test3i:(III)I
   39:  invokevirtual   #4;  // Method java/io/PrintStream.println:(I)V
 
   42:  getstatic       #2;  // Field java/lang/System.out:Ljava/io/PrintStream;
   45:  iconst_1             // první argument metody na zásobník
   46:  iconst_2             // druhý argument metody na zásobník
   47:  iconst_3             // třetí argument metody na zásobník
   48:  iconst_4             // čtvrtý argument metody na zásobník
   49:  invokestatic    #8;  // Method test4i:(IIII)I
   52:  invokevirtual   #4;  // Method java/io/PrintStream.println:(I)V
 
   55:  getstatic       #2;  // Field java/lang/System.out:Ljava/io/PrintStream;
   58:  iconst_1             // první argument metody na zásobník
   59:  iconst_2             // druhý argument metody na zásobník
   60:  iconst_3             // třetí argument metody na zásobník
   61:  iconst_4             // čtvrtý argument metody na zásobník
   62:  iconst_5             // pátý argument metody na zásobník
   63:  invokestatic    #9;  // Method test5i:(IIIII)I
   66:  invokevirtual   #4;  // Method java/io/PrintStream.println:(I)V
 
   69:  getstatic       #2;  // Field java/lang/System.out:Ljava/io/PrintStream;
   72:  iconst_1             // první argument metody na zásobník
   73:  iconst_2             // druhý argument metody na zásobník
   74:  iconst_3             // třetí argument metody na zásobník
   75:  iconst_4             // čtvrtý argument metody na zásobník
   76:  iconst_5             // pátý argument metody na zásobník
   77:  bipush  6            // šestý argument metody na zásobník
   79:  invokestatic    #10; // Method test6i:(IIIIII)I
   82:  invokevirtual   #4;  // Method java/io/PrintStream.println:(I)V
 
   85:  return
 
}

4. Demonstrační příklad Test18.java: předávání parametrů typu float

Ve druhém demonstračním příkladu nazvaném Test18.java se budou volaným metodám předávat parametry typu float, což znamená, že překladač vygeneruje instrukce fload_x a nikoli iload_x:

/**
 * Ukazka predavani parametru typu float do volanych statickych metod.
 */
public class Test18 {
 
    /**
     * Metoda bez parametru.
     */
    public static float test0i() {
        return 42.0f;
    }
 
    /**
     * Metoda s jednim parametrem typu float.
     */
    public static float test1i(float a) {
        return a;
    }
 
    /**
     * Metoda se dvema parametry typu float
     */
    public static float test2i(float a, float b) {
        return a + b;
    }
 
    /**
     * Metoda se tremi parametry typu float
     */
    public static float test3i(float a, float b, float c) {
        return a + b + c;
    }
 
    /**
     * Metoda se ctyrmi parametry typu float
     */
    public static float test4i(float a, float b, float c, float d) {
        return a + b + c + d;
    }
 
    /**
     * Metoda s peti parametry typu float
     */
    public static float test5i(float a, float b, float c, float d, float e) {
        return a + b + c + d + e;
    }
 
    /**
     * Metoda se sesti parametry typu float
     */
    public static float test6i(float a, float b, float c, float d, float e, float f) {
        return a + b + c + d + e + f;
    }
 
    /**
     * Vse je nutne otestovat.
     */
    public static void main(String[] args) {
        System.out.print(test0i());
        System.out.print(test1i(1.0f));
        System.out.print(test2i(1.0f, 2.0f));
        System.out.print(test3i(1.0f, 2.0f, 3.0f));
        System.out.print(test4i(1.0f, 2.0f, 3.0f, 4.0f));
        System.out.print(test5i(1.0f, 2.0f, 3.0f, 4.0f, 5.0f));
        System.out.print(test6i(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f));
    }
}

Opět se podívejme na výsledek překladu tohoto demonstračního příkladu a na rozdíly oproti bajtkódu příkladu předchozího:

Compiled from "Test18.java"
public class Test18 extends java.lang.Object{
 
public static float test0i();
  Code:
   0:   ldc     #2;     // uložení reálné konstanty 42.0f na TOS
   2:   freturn         // vrácení hodnoty typu float uložené na TOS
 
public static float test1i(float);
  Code:
   0:   fload_0         // uložení hodnoty prvního parametru na zásobník
   1:   freturn         // vrácení hodnoty typu float uložené na TOS
 
public static float test2i(float, float);
  Code:
   0:   fload_0         // uložení hodnoty prvního parametru na zásobník
   1:   fload_1         // uložení hodnoty druhého parametru na zásobník
   2:   fadd
   3:   freturn         // vrácení hodnoty typu float uložené na TOS
 
public static float test3i(float, float, float);
  Code:
   0:   fload_0         // uložení hodnoty prvního parametru na zásobník
   1:   fload_1         // uložení hodnoty druhého parametru na zásobník
   2:   fadd
   3:   fload_2         // uložení hodnoty třetího parametru na zásobník
   4:   fadd
   5:   freturn         // vrácení hodnoty typu float uložené na TOS
 
public static float test4i(float, float, float, float);
  Code:
   0:   fload_0         // uložení hodnoty prvního parametru na zásobník
   1:   fload_1         // uložení hodnoty druhého parametru na zásobník
   2:   fadd
   3:   fload_2         // uložení hodnoty třetího parametru na zásobník
   4:   fadd
   5:   fload_3         // uložení hodnoty čtvrtého parametru na zásobník
   6:   fadd
   7:   freturn         // vrácení hodnoty typu float uložené na TOS
 
public static float test5i(float, float, float, float, float);
  Code:
   0:   fload_0         // uložení hodnoty prvního parametru na zásobník
   1:   fload_1         // uložení hodnoty druhého parametru na zásobník
   2:   fadd
   3:   fload_2         // uložení hodnoty třetího parametru na zásobník
   4:   fadd
   5:   fload_3         // uložení hodnoty čtvrtého parametru na zásobník
   6:   fadd
   7:   fload   4       // uložení hodnoty pátého parametru na zásobník
   9:   fadd
   10:  freturn         // vrácení hodnoty typu float uložené na TOS
 
public static float test6i(float, float, float, float, float, float);
  Code:
   0:   fload_0         // uložení hodnoty prvního parametru na zásobník
   1:   fload_1         // uložení hodnoty druhého parametru na zásobník
   2:   fadd
   3:   fload_2         // uložení hodnoty třetího parametru na zásobník
   4:   fadd
   5:   fload_3         // uložení hodnoty čtvrtého parametru na zásobník
   6:   fadd
   7:   fload   4       // uložení hodnoty pátého parametru na zásobník
   9:   fadd
   10:  fload   5       // uložení hodnoty šestého parametru na zásobník
   12:  fadd
   13:  freturn         // vrácení hodnoty typu float uložené na TOS
 
public static void main(java.lang.String[]);
  Code:
   0:   getstatic       #3;  // Field java/lang/System.out:Ljava/io/PrintStream;
   3:   invokestatic    #4;  // Method test0i:()F
   6:   invokevirtual   #5;  // Method java/io/PrintStream.print:(F)V
 
   9:   getstatic       #3;  // Field java/lang/System.out:Ljava/io/PrintStream;
   12:  fconst_1             // první argument metody na zásobník
   13:  invokestatic    #6;  // Method test1i:(F)F
   16:  invokevirtual   #5;  // Method java/io/PrintStream.print:(F)V
 
   19:  getstatic       #3;  // Field java/lang/System.out:Ljava/io/PrintStream;
   22:  fconst_1             // první argument metody na zásobník
   23:  fconst_2             // druhý argument metody na zásobník
   24:  invokestatic    #7;  // Method test2i:(FF)F
   27:  invokevirtual   #5;  // Method java/io/PrintStream.print:(F)V
 
   30:  getstatic       #3;  // Field java/lang/System.out:Ljava/io/PrintStream;
   33:  fconst_1             // první argument metody na zásobník
   34:  fconst_2             // druhý argument metody na zásobník
   35:  ldc     #8;          // třetí argument metody na zásobník
   37:  invokestatic    #9;  // Method test3i:(FFF)F
   40:  invokevirtual   #5;  // Method java/io/PrintStream.print:(F)V
 
   43:  getstatic       #3;  // Field java/lang/System.out:Ljava/io/PrintStream;
   46:  fconst_1             // první argument metody na zásobník
   47:  fconst_2             // druhý argument metody na zásobník
   48:  ldc     #8;          // třetí argument metody na zásobník
   50:  ldc     #10;         // čtvrtý argument metody na zásobník
   52:  invokestatic    #11; // Method test4i:(FFFF)F
   55:  invokevirtual   #5;  // Method java/io/PrintStream.print:(F)V
 
   58:  getstatic       #3;  // Field java/lang/System.out:Ljava/io/PrintStream;
   61:  fconst_1             // první argument metody na zásobník
   62:  fconst_2             // druhý argument metody na zásobník
   63:  ldc     #8;          // třetí argument metody na zásobník
   65:  ldc     #10;         // čtvrtý argument metody na zásobník
   67:  ldc     #12;         // pátý argument metody na zásobník
   69:  invokestatic    #13; // Method test5i:(FFFFF)F
   72:  invokevirtual   #5;  // Method java/io/PrintStream.print:(F)V
 
   75:  getstatic       #3;  // Field java/lang/System.out:Ljava/io/PrintStream;
   78:  fconst_1             // první argument metody na zásobník
   79:  fconst_2             // druhý argument metody na zásobník
   80:  ldc     #8;          // třetí argument metody na zásobník
   82:  ldc     #10;         // čtvrtý argument metody na zásobník
   84:  ldc     #12;         // pátý argument metody na zásobník
   86:  ldc     #14;         // šestý argument metody na zásobník
   88:  invokestatic    #15; // Method test6i:(FFFFFF)F
   91:  invokevirtual   #5;  // Method java/io/PrintStream.print:(F)V
 
   94:  return
 
}

5. Předávání parametrů funkcím v Lua VM: demonstrační příklad Test17.lua

Předávání parametrů funkcím v Lua VM i Python VM se liší od JVM především v tom ohledu, že se využívá dynamického typování, což mj. znamená, že počet potřebných typů instrukcí bajtkódu je mnohem menší. Nejprve se podívejme na Lua VM a demonstrační příklad Test17.lua:

--
-- Ukazka predavani parametru do volanych funkci.
--
 
 
 
--
-- Funkce bez parametru.
--
function test0()
    return 42
end
 
--
-- Funkce s jednim parametrem
--
function test1(a)
    return a
end
 
--
-- Funkce se dvema parametry 
--
function test2(a, b)
    return a + b
end
 
--
-- Funkce se tremi parametry 
--
function test3(a, b, c)
    return a + b + c
end
 
--
-- Funkce se ctyrmi parametry 
--
function test4(a, b, c, d)
    return a + b + c + d
end
 
--
-- Funkce s peti parametry 
--
function test5(a, b, c, d, e)
    return a + b + c + d + e
end
 
--
-- Funkce se sesti parametry 
--
function test6(a, b, c, d, e, f)
    return a + b + c + d + e + f
end
 
--
-- Test.
--
function main()
    print(test0())
    print(test1(1))
    print(test2(1, 2))
    print(test3(1, 2, 3))
    print(test4(1, 2, 3, 4))
    print(test5(1, 2, 3, 4, 5))
    print(test6(1, 2, 3, 4, 5, 6))
end
 
 
 
main()

Z výpisu bajtkódu je patrné, že se pro předávání parametrů používají registry, což vede (mj. i díky tříadresovým kódům) k mnohem kratšímu bajtkódu, než jsme viděli v případě JVM (povšimněte si druhého řádku hlavičky každé funkce):

function <Test17.lua:10,12> (3 instructions at 0x90efc88)
0 params, 2 slots, 0 upvalues, 0 locals, 1 constant, 0 functions
        1       [11]    LOADK           0 -1    // načtení konstanty 42 do registru 0
        2       [11]    RETURN          0 2     // vrácení konstanty uložené v registru 0
        3       [12]    RETURN          0 1     // implicitně vkládáno překladačem
 
function <Test17.lua:17,19> (2 instructions at 0x90efe60)
1 param, 2 slots, 0 upvalues, 1 local, 0 constants, 0 functions
        1       [18]    RETURN          0 2     // vrácení konstanty uložené v registru 0
        2       [19]    RETURN          0 1     // implicitně vkládáno překladačem
 
function <Test17.lua:24,26> (3 instructions at 0x90effc0)
2 params, 3 slots, 0 upvalues, 2 locals, 0 constants, 0 functions
        1       [25]    ADD             2 0 1   // do registru 2 se uloží součet registrů 0 a 1
        2       [25]    RETURN          2 2     // vrácení konstanty uložené v registru 2
        3       [26]    RETURN          0 1     // implicitně vkládáno překladačem
 
function <Test17.lua:31,33> (4 instructions at 0x90efe08)
3 params, 4 slots, 0 upvalues, 3 locals, 0 constants, 0 functions
        1       [32]    ADD             3 0 1   // do registru 3 se uloží součet registrů 0 a 1
        2       [32]    ADD             3 3 2   // k registru 3 se připočte obsah registru 2
        3       [32]    RETURN          3 2     // vrácení konstanty uložené v registru 3
        4       [33]    RETURN          0 1     // implicitně vkládáno překladačem
 
function <Test17.lua:38,40> (5 instructions at 0x90f0408)
4 params, 5 slots, 0 upvalues, 4 locals, 0 constants, 0 functions
        1       [39]    ADD             4 0 1   // do registru 4 se uloží součet registrů 0 a 1
        2       [39]    ADD             4 4 2   // k registru 4 se připočte obsah registru 2
        3       [39]    ADD             4 4 3   // k registru 4 se připočte obsah registru 3
        4       [39]    RETURN          4 2     // vrácení konstanty uložené v registru 4
        5       [40]    RETURN          0 1     // implicitně vkládáno překladačem
 
function <Test17.lua:45,47> (6 instructions at 0x90f0110)
5 params, 6 slots, 0 upvalues, 5 locals, 0 constants, 0 functions
        1       [46]    ADD             5 0 1   // do registru 5 se uloží součet registrů 0 a 1
        2       [46]    ADD             5 5 2   // k registru 5 se připočte obsah registru 2
        3       [46]    ADD             5 5 3   // k registru 5 se připočte obsah registru 3
        4       [46]    ADD             5 5 4   // k registru 5 se připočte obsah registru 4
        5       [46]    RETURN          5 2     // vrácení konstanty uložené v registru 5
        6       [47]    RETURN          0 1     // implicitně vkládáno překladačem
 
function <Test17.lua:52,54> (7 instructions at 0x90f0658)
6 params, 7 slots, 0 upvalues, 6 locals, 0 constants, 0 functions
        1       [53]    ADD             6 0 1   // do registru 6 se uloží součet registrů 0 a 1
        2       [53]    ADD             6 6 2   // k registru 6 se připočte obsah registru 2
        3       [53]    ADD             6 6 3   // k registru 6 se připočte obsah registru 3
        4       [53]    ADD             6 6 4   // k registru 6 se připočte obsah registru 4
        5       [53]    ADD             6 6 5   // k registru 6 se připočte obsah registru 5
        6       [53]    RETURN          6 2     // vrácení konstanty uložené v registru 6
        7       [54]    RETURN          0 1     // implicitně vkládáno překladačem
 
function <Test17.lua:59,67> (50 instructions at 0x90f0760)
0 params, 8 slots, 1 upvalue, 0 locals, 14 constants, 0 functions
        1       [60]    GETTABUP        0 0 -1  // příprava na volání funkce "print"
        2       [60]    GETTABUP        1 0 -2  // příprava na volání funkce "test0"
        3       [60]    CALL            1 1 0   // zavolání funkce "test0"
        4       [60]    CALL            0 0 1   // zavolání funkce "print"
 
        5       [61]    GETTABUP        0 0 -1  // příprava na volání funkce "print"
        6       [61]    GETTABUP        1 0 -3  // příprava na volání funkce "test1"
        7       [61]    LOADK           2 -4    // vložit do registru 2 parametr číslo 1
        8       [61]    CALL            1 2 0   // zavolání funkce "test1"
        9       [61]    CALL            0 0 1   // zavolání funkce "print"
 
        10      [62]    GETTABUP        0 0 -1  // příprava na volání funkce "print"
        11      [62]    GETTABUP        1 0 -5  // příprava na volání funkce "test2"
        12      [62]    LOADK           2 -4    // vložit do registru 2 parametr číslo 1
        13      [62]    LOADK           3 -6    // vložit do registru 3 parametr číslo 2
        14      [62]    CALL            1 3 0   // zavolání funkce "test2"
        15      [62]    CALL            0 0 1   // zavolání funkce "print"
 
        16      [63]    GETTABUP        0 0 -1  // příprava na volání funkce "print"
        17      [63]    GETTABUP        1 0 -7  // příprava na volání funkce "test3"
        18      [63]    LOADK           2 -4    // vložit do registru 2 parametr číslo 1
        19      [63]    LOADK           3 -6    // vložit do registru 3 parametr číslo 2
        20      [63]    LOADK           4 -8    // vložit do registru 4 parametr číslo 3
        21      [63]    CALL            1 4 0   // zavolání funkce "test3"
        22      [63]    CALL            0 0 1   // zavolání funkce "print"
 
        23      [64]    GETTABUP        0 0 -1  // příprava na volání funkce "print"
        24      [64]    GETTABUP        1 0 -9  // příprava na volání funkce "test4"
        25      [64]    LOADK           2 -4    // vložit do registru 2 parametr číslo 1
        26      [64]    LOADK           3 -6    // vložit do registru 3 parametr číslo 2
        27      [64]    LOADK           4 -8    // vložit do registru 4 parametr číslo 3
        28      [64]    LOADK           5 -10   // vložit do registru 5 parametr číslo 4
        29      [64]    CALL            1 5 0   // zavolání funkce "test4"
        30      [64]    CALL            0 0 1   // zavolání funkce "print"
 
        31      [65]    GETTABUP        0 0 -1  // příprava na volání funkce "print"
        32      [65]    GETTABUP        1 0 -11 // příprava na volání funkce "test5"
        33      [65]    LOADK           2 -4    // vložit do registru 2 parametr číslo 1
        34      [65]    LOADK           3 -6    // vložit do registru 3 parametr číslo 2
        35      [65]    LOADK           4 -8    // vložit do registru 4 parametr číslo 3
        36      [65]    LOADK           5 -10   // vložit do registru 5 parametr číslo 4
        37      [65]    LOADK           6 -12   // vložit do registru 6 parametr číslo 5
        38      [65]    CALL            1 6 0   // zavolání funkce "test5"
        39      [65]    CALL            0 0 1   // zavolání funkce "print"
 
        40      [66]    GETTABUP        0 0 -1  // příprava na volání funkce "print"
        41      [66]    GETTABUP        1 0 -13 // příprava na volání funkce "test6"
        42      [66]    LOADK           2 -4    // vložit do registru 2 parametr číslo 1
        43      [66]    LOADK           3 -6    // vložit do registru 3 parametr číslo 2
        44      [66]    LOADK           4 -8    // vložit do registru 4 parametr číslo 3
        45      [66]    LOADK           5 -10   // vložit do registru 5 parametr číslo 4
        46      [66]    LOADK           6 -12   // vložit do registru 6 parametr číslo 5
        47      [66]    LOADK           7 -14   // vložit do registru 7 parametr číslo 6
        48      [66]    CALL            1 7 0   // zavolání funkce "test6"
        49      [66]    CALL            0 0 1   // zavolání funkce "print"
 
        50      [67]    RETURN          0 1     // implicitně vkládáno překladačem

6. Předávání parametrů funkcím v Python VM: demonstrační příklad Test17.py

Zbývá nám ukázka způsobu předávání parametrů volaným funkcím v Python VM. Nejprve se opět podívejme na zdrojový kód demonstračního příkladu:

#
# Ukazka predavani parametru do volanych funkci.
#
 
 
 
#
# Funkce bez parametru.
#
def test0():
    return 42
 
 
 
#
# Funkce s jednim parametrem
#
def test1(a):
    return a
 
 
 
#
# Funkce se dvema parametry 
#
def test2(a, b):
    return a + b
 
 
 
#
# Funkce se tremi parametry 
#
def test3(a, b, c):
    return a + b + c
 
 
 
#
# Funkce se ctyrmi parametry 
#
def test4(a, b, c, d):
    return a + b + c + d
 
 
 
#
# Funkce s peti parametry 
#
def test5(a, b, c, d, e):
    return a + b + c + d + e
 
 
 
#
# Funkce se sesti parametry 
#
def test6(a, b, c, d, e, f):
    return a + b + c + d + e + f
 
 
 
#
# Test.
#
def main():
    print(test0())
    print(test1(1))
    print(test2(1, 2))
    print(test3(1, 2, 3))
    print(test4(1, 2, 3, 4))
    print(test5(1, 2, 3, 4, 5))
    print(test6(1, 2, 3, 4, 5, 6))
 
 
 
#
# Ukazka disasembleru.
#
def disassemble():
    from dis import dis
 
    print("\ntest0:")
    dis(test0)
 
    print("\ntest1:")
    dis(test1)
 
    print("\ntest2:")
    dis(test2)
 
    print("\ntest3:")
    dis(test3)
 
    print("\ntest4:")
    dis(test4)
 
    print("\ntest5:")
    dis(test5)
 
    print("\ntest6:")
    dis(test6)
 
main()
 
disassemble()

Následuje bajtkód vzniklý překladem tohoto demonstračního příkladu:

test0:
 11           0 LOAD_CONST          // uložit konstantu 42 na zásobník
              3 RETURN_VALUE        // návrat z funkce s předáním výsledku
 
test1:
 19           0 LOAD_FAST    0      // uložit hodnotu parametru a na zásobník
              3 RETURN_VALUE        // návrat z funkce s předáním výsledku
 
test2:
 27           0 LOAD_FAST    0      // uložit hodnotu parametru a na zásobník
              3 LOAD_FAST    1      // uložit hodnotu parametru b na zásobník
              6 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
              7 RETURN_VALUE        // návrat z funkce s předáním výsledku
 
test3:
 35           0 LOAD_FAST    0      // uložit hodnotu parametru a na zásobník
              3 LOAD_FAST    1      // uložit hodnotu parametru b na zásobník
              6 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
              7 LOAD_FAST    2      // uložit hodnotu parametru c na zásobník
             10 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             11 RETURN_VALUE        // návrat z funkce s předáním výsledku
 
test4:
 43           0 LOAD_FAST    0      // uložit hodnotu parametru a na zásobník
              3 LOAD_FAST    1      // uložit hodnotu parametru b na zásobník
              6 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
              7 LOAD_FAST    2      // uložit hodnotu parametru c na zásobník
             10 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             11 LOAD_FAST    3      // uložit hodnotu parametru d na zásobník
             14 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             15 RETURN_VALUE        // návrat z funkce s předáním výsledku
 
test5:
 51           0 LOAD_FAST    0      // uložit hodnotu parametru a na zásobník
              3 LOAD_FAST    1      // uložit hodnotu parametru b na zásobník
              6 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
              7 LOAD_FAST    2      // uložit hodnotu parametru c na zásobník
             10 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             11 LOAD_FAST    3      // uložit hodnotu parametru d na zásobník
             14 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             15 LOAD_FAST    4      // uložit hodnotu parametru e na zásobník
             18 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             19 RETURN_VALUE        // návrat z funkce s předáním výsledku
 
test6:
 59           0 LOAD_FAST    0      // uložit hodnotu parametru a na zásobník
              3 LOAD_FAST    1      // uložit hodnotu parametru b na zásobník
              6 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
              7 LOAD_FAST    2      // uložit hodnotu parametru c na zásobník
             10 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             11 LOAD_FAST    3      // uložit hodnotu parametru d na zásobník
             14 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             15 LOAD_FAST    4      // uložit hodnotu parametru e na zásobník
             18 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             19 LOAD_FAST    5      // uložit hodnotu parametru f na zásobník
             22 BINARY_ADD          // provést součet dvou hodnot uložených na TOS a TOS-1
             23 RETURN_VALUE        // návrat z funkce s předáním výsledku

7. Složené datové typy v JVM, Lua VM a Python VM

Ve druhé polovině tohoto článku se budeme zabývat podporou složených datových typů v bajtkódech JVM, Lua VM i Python VM. Virtuální stroj jazyka Java podporuje jako (doposud) jediný složený datový typ pouze pole, a to jak pole obsahující primitivní datové typy, tak i pole obsahující reference na objekty. Pole může mít jednu dimenzi či větší počet dimenzí.

V případě programovacího jazyka Lua a tím pádem i Lua VM se namísto polí používají tabulky, které lze používat dvěma způsoby – buď jako skutečné pole nebo jako asociativní pole. V prvním případě jsou prvky pole indexovány od jedničky, což má ve vysokoúrovňovém jazyce větší smysl, než indexace od nuly (ta byla vynucena v céčku kvůli ukazatelové aritmetice, z céčka se pak tento způsob dostal i do Javy a dokonce i do JavaScriptu). Ve druhém případě se do tabulky ukládají dvojice klíč:hodnota, kde klíč musí být unikátní a nesmí mít hodnotu nil.

V Python VM se taktéž nepoužívají klasická pole; namísto toho nabízí tento programovací jazyk poněkud flexibilnější seznamy a taktéž n-tice (které jsou neměnitelné).

Podívejme se nyní na základní instrukce bajtkódu sloužící pro práci se zmíněnými složenými datovými typy:

Java Instrukce Význam
1 newarray konstrukce jednorozměrného pole
2 multianewarray konstrukce vícerozměrného pole
     
Lua Instrukce Význam
1 NEWTABLE vytvoření tabulky o zadané kapacitě
2 SETLIST inicializace více položek tabulky
3 SETTABLE vložení nové hodnoty či dvojice klíč:hodnota do tabulky
     
Python Instrukce Význam
1 BUILD_LIST vytvoření seznamu
2 BUILD_TUPLE vytvoření n-tice

8. Demonstrační příklad Test19.java: konstrukce jednorozměrných polí

Způsob použití instrukce newarray si ukážeme na jednoduchém demonstračním příkladu, v jehož třídě je deklarována jediná (statická) metoda, po jejímž zavolání se vytvoří osm lokálních proměnných, přičemž každá proměnná je referencí na pole zadané délky. Zdrojový kód tohoto demonstračního příkladu je skutečně velmi jednoduchý:

/**
 * Vytvareni (konstrukce) poli.
 */
public class Test19 {
 
    static void createArrays(int size) {
        boolean[] booleanArray    = new boolean[size];
        char[]    charArray       = new char[size];
        byte[]    byteArray       = new byte[size];
        short[]   shortArray      = new short[size];
        int[]     intArray        = new int[size];
        long[]    longArray       = new long[size];
        float[]   floatArray      = new float[size];
        double[]  doubleegerArray = new double[size];
    }
 
}

Překladač javac vygeneruje bajtkód, v němž jsou použity instrukce pro vytvoření všech osmi lokálních proměnných, i když ve skutečnosti nejsou tyto proměnné nikde použity. Z výpisu je patrné, že každé pole je vytvořeno s využitím pouze třech instrukcí – uložení počtu prvků vytvářeného pole na zásobník, vlastní vytvoření (konstrukce) pole a nakonec uložení reference do lokální proměnné:

static void createArrays(int);
  Code:
 
   0:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   1:     newarray boolean   // vytvoření pole s prvky typu boolean
   3:     astore_1           // reference na pole se uloží do lokální proměnné
 
   4:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   5:     newarray char      // vytvoření pole s prvky typu char
   7:     astore_2           // reference na pole se uloží do lokální proměnné
 
   8:     iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   9:     newarray byte      // vytvoření pole s prvky typu byte
   11:    astore_3           // reference na pole se uloží do lokální proměnné
 
   12:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   13:    newarray short     // vytvoření pole s prvky typu short
   15:    astore    4        // reference na pole se uloží do lokální proměnné
 
   17:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   18:    newarray int       // vytvoření pole s prvky typu int
   20:    astore    5        // reference na pole se uloží do lokální proměnné
 
   22:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   23:    newarray long      // vytvoření pole s prvky typu long
   25:    astore    6        // reference na pole se uloží do lokální proměnné
 
   27:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   28:    newarray float     // vytvoření pole s prvky typu float
   30:    astore    7        // reference na pole se uloží do lokální proměnné
 
   32:    iload_0            // na TOS zásobníku operandů se uloží délka vytvářeného pole
   33:    newarray double    // vytvoření pole s prvky typu double
   35:    astore    8        // reference na pole se uloží do lokální proměnné
 
   37:    return             // návrat z metody
}

9. Demonstrační příklad Test20.java: konstrukce vícerozměrných polí

I v dalším demonstračním příkladu nazvaném Test20 se budou vytvářet pole, ovšem v tomto případě se bude jednat o pole dvourozměrná, což znamená, že se v bajtkódu využije odlišná instrukce pro konstrukci těchto polí:

/**
 * Vytvareni (konstrukce) vicerozmernych poli.
 */
public class Test20 {
 
    static void createArrays(int size1, int size2) {
        boolean[][] booleanArray = new boolean[size1][size2];
        char[][]    charArray    = new char[size1][size2];
        byte[][]    byteArray    = new byte[size1][size2];
        short[][]   shortArray   = new short[size1][size2];
        int[][]     intArray     = new int[size1][size2];
        long[][]    longArray    = new long[size1][size2];
        float[][]   floatArray   = new float[size1][size2];
        double[][]  doubleArray  = new double[size1][size2];
    }
 
}

Překladač javac v tomto případě vygeneruje bajtkód, v němž je použita instrukce multianewarray, které se předá jak počet dimenzí vytvářeného pole, tak i rozměry dimenzí (ty jsou uloženy na zásobníku operandů) a typ pole (ten je uložen v constant poolu). Vytvoření každého pole je v tomto případě implementováno ve čtyřech instrukcích bajtkódu:

Compiled from "Test20.java"
public class Test20 extends java.lang.Object{
 
static void createArrays(int, int);
  Code:
   0:   iload_0                 // rozměr první dimenze pole
   1:   iload_1                 // rozměr druhé dimenze pole
   2:   multianewarray  #2,  2; // class "[[Z" (dvourozměrné pole prvků typu boolean)
   6:   astore_2                // uložení výsledku (nového pole) do lokální proměnné
 
   7:   iload_0                 // rozměr první dimenze pole
   8:   iload_1                 // rozměr druhé dimenze pole
   9:   multianewarray  #3,  2; // class "[[C" (dvourozměrné pole prvků typu char)
   13:  astore_3                // uložení výsledku (nového pole) do lokální proměnné
 
   14:  iload_0                 // rozměr první dimenze pole
   15:  iload_1                 // rozměr druhé dimenze pole
   16:  multianewarray  #4,  2; // class "[[B" (dvourozměrné pole prvků typu byte)
   20:  astore  4               // uložení výsledku (nového pole) do lokální proměnné
 
   22:  iload_0                 // rozměr první dimenze pole
   23:  iload_1                 // rozměr druhé dimenze pole
   24:  multianewarray  #5,  2; // class "[[S" (dvourozměrné pole prvků typu short)
   28:  astore  5               // uložení výsledku (nového pole) do lokální proměnné
 
   30:  iload_0                 // rozměr první dimenze pole
   31:  iload_1                 // rozměr druhé dimenze pole
   32:  multianewarray  #6,  2; // class "[[I" (dvourozměrné pole prvků typu int)
   36:  astore  6               // uložení výsledku (nového pole) do lokální proměnné
 
   38:  iload_0                 // rozměr první dimenze pole
   39:  iload_1                 // rozměr druhé dimenze pole
   40:  multianewarray  #7,  2; // class "[[J" (dvourozměrné pole prvků typu long)
   44:  astore  7               // uložení výsledku (nového pole) do lokální proměnné
 
   46:  iload_0                 // rozměr první dimenze pole
   47:  iload_1                 // rozměr druhé dimenze pole
   48:  multianewarray  #8,  2; // class "[[F" (dvourozměrné pole prvků typu float)
   52:  astore  8               // uložení výsledku (nového pole) do lokální proměnné
 
   54:  iload_0                 // rozměr první dimenze pole
   55:  iload_1                 // rozměr druhé dimenze pole
   56:  multianewarray  #9,  2; // class "[[D" (dvourozměrné pole prvků typu double)
   60:  astore  9               // uložení výsledku (nového pole) do lokální proměnné
 
   62:  return                  // návrat z metody
}

10. Demonstrační příklad Test19.lua: vytvoření tabulek

V demonstračním příkladu nazvaném Test19.lua je ukázáno vytvoření tabulky obsahující několik číselných položek a dále tabulky, jejíž prvky jsou taktéž tabulky, takže výsledkem je vlastně matice o velikosti 3×3 prvky. Povšimněte si taktéž způsobu výpisu obsahu tabulek s využitím funkce pairs() vracející iterátor. V tomto případě by bylo možné použít i funkci ipairs(), je ovšem dobré vědět, že i „normální“ tabulky mohou vracet pro své prvky klíče:

--
-- Vytvoreni tabulky.
--
 
 
 
--
-- Vytvoreni jednoduche tabulky.
--
function test0()
    local tabulka = {1, 3, 5, 7, 11, 13, 17}
    return tabulka
end
 
 
 
--
-- Vytvoreni vnorene tabulky.
--
function test1()
    local matice = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
    return matice
end
 
 
 
--
-- Test.
--
function main()
    local x = test0()
    for key,val in pairs(x) do
        print("table[" .. key .. "] = " .. val)
    end
 
    print()
 
    local y = test1()
    for i,vector in pairs(y) do
        for j,item in pairs(vector) do
            print("table[" .. i .. "," .. j .. "] = " .. item)
        end
    end
end
 
 
 
main()

Bajtkód vygenerovaný překladem demonstračního příkladu Test19.lua je poměrně zajímavý, protože zde najdeme vysokoúrovňové instrukce NEWTABLE (vytvoření tabulky), SETLIST (nastavení prvků tabulky) i TFORCALL+TFORLOOP (smyčka typu foreach vysvětlená příště):

function <Test19.lua:10,13> (11 instructions at 0x817bc88)
0 params, 8 slots, 0 upvalues, 1 local, 7 constants, 0 functions
        1       [11]    NEWTABLE        0 7 0  // konstrukce nové tabulky o velikosti 7 položek
        2       [11]    LOADK           1 -1   // uložit konstantu 1 do registru
        3       [11]    LOADK           2 -2   // uložit konstantu 3 do registru
        4       [11]    LOADK           3 -3   // uložit konstantu 5 do registru
        5       [11]    LOADK           4 -4   // uložit konstantu 7 do registru
        6       [11]    LOADK           5 -5   // uložit konstantu 11 do registru
        7       [11]    LOADK           6 -6   // uložit konstantu 13 do registru
        8       [11]    LOADK           7 -7   // uložit konstantu 17 do registru
        9       [11]    SETLIST         0 7 1  // inicializace položek
        10      [12]    RETURN          0 2    // tabulka je návratovou hodnotou
        11      [13]    RETURN          0 1    // implicitně vkládáno překladačem
 
function <Test19.lua:20,23> (19 instructions at 0x817c0f0)
0 params, 7 slots, 0 upvalues, 1 local, 9 constants, 0 functions
        1       [21]    NEWTABLE        0 3 0  // konstrukce nové tabulky o velikosti 3 položek
 
        2       [21]    NEWTABLE        1 3 0  // konstrukce nové podtabulky o velikosti 3 položek
        3       [21]    LOADK           2 -1   // uložit konstantu 1 do registru
        4       [21]    LOADK           3 -2   // uložit konstantu 2 do registru
        5       [21]    LOADK           4 -3   // uložit konstantu 3 do registru
        6       [21]    SETLIST         1 3 1  // inicializace položek podtabulky
 
        7       [21]    NEWTABLE        2 3 0  // konstrukce nové podtabulky o velikosti 3 položek
        8       [21]    LOADK           3 -4   // uložit konstantu 4 do registru
        9       [21]    LOADK           4 -5   // uložit konstantu 5 do registru
        10      [21]    LOADK           5 -6   // uložit konstantu 6 do registru
        11      [21]    SETLIST         2 3 1  // inicializace položek tabulky
 
        12      [21]    NEWTABLE        3 3 0  // konstrukce nové podtabulky o velikosti 3 položek
        13      [21]    LOADK           4 -7   // uložit konstantu 7 do registru
        14      [21]    LOADK           5 -8   // uložit konstantu 8 do registru
        15      [21]    LOADK           6 -9   // uložit konstantu 9 do registru
        16      [21]    SETLIST         3 3 1  // inicializace položek tabulky
 
        17      [21]    SETLIST         0 3 1  // inicializace položek (podtabulek) hlavní tabulky
        18      [22]    RETURN          0 2    // tabulka je návratovou hodnotou
        19      [23]    RETURN          0 1    // implicitně vkládáno překladačem
 
function <Test19.lua:30,44> (41 instructions at 0x817c630)
0 params, 19 slots, 1 upvalue, 17 locals, 7 constants, 0 functions
        1       [31]    GETTABUP        0 0 -1 // příprava na volání funkce "test0"
        2       [31]    CALL            0 1 2
        3       [32]    GETTABUP        1 0 -2 // příprava na volání funkce "pairs"
        4       [32]    MOVE            2 0
        5       [32]    CALL            1 2 4  // zavolání funkce "pairs"
        6       [32]    JMP             0 7     ; to 14
        7       [33]    GETTABUP        6 0 -3 // příprava na volání funkce "print"
        8       [33]    LOADK           7 -4    ; "table["
        9       [33]    MOVE            8 4
        10      [33]    LOADK           9 -5    ; "] = "
        11      [33]    MOVE            10 5
        12      [33]    CONCAT          7 7 10
        13      [33]    CALL            6 2 1  // zavolání funkce "print"
        14      [32]    TFORCALL        1 2
        15      [32]    TFORLOOP        3 -9    ; to 7
        16      [36]    GETTABUP        1 0 -3 // příprava na volání funkce "print"
        17      [36]    CALL            1 1 1
        18      [38]    GETTABUP        1 0 -6 // příprava na volání funkce "test1"
        19      [38]    CALL            1 1 2
        20      [39]    GETTABUP        2 0 -2 // příprava na volání funkce "pairs"
        21      [39]    MOVE            3 1
        22      [39]    CALL            2 2 4  // zavolání funkce "pairs"
        23      [39]    JMP             0 15    ; to 39
        24      [40]    GETTABUP        7 0 -2 // příprava na volání funkce "pairs"
        25      [40]    MOVE            8 6
        26      [40]    CALL            7 2 4  // zavolání funkce "pairs"
        27      [40]    JMP             0 9     ; to 37
        28      [41]    GETTABUP        12 0 -3// příprava na volání funkce "print"
        29      [41]    LOADK           13 -4   ; "table["
        30      [41]    MOVE            14 5
        31      [41]    LOADK           15 -7   ; ","
        32      [41]    MOVE            16 10
        33      [41]    LOADK           17 -5   ; "] = "
        34      [41]    MOVE            18 11
        35      [41]    CONCAT          13 13 18
        36      [41]    CALL            12 2 1  // zavolání funkce "print"
        37      [40]    TFORCALL        7 2
        38      [40]    TFORLOOP        9 -11   ; to 28
        39      [39]    TFORCALL        2 2
        40      [39]    TFORLOOP        4 -17   ; to 24
        41      [44]    RETURN          0 1    // implicitně vkládáno překladačem

11. Demonstrační příklad Test20.lua: vytvoření asociativního pole

V demonstračním příkladu nazvaném Test20.lua je vytvořeno asociativní pole s pěticí dvojic klíč:hodnota, jehož obsah je následně vypsán na standardní výstup s využitím programové smyčky typu foreach:

--
-- Vytvoreni asociativniho pole.
--
 
 
 
--
-- Vytvoreni asociativniho pole.
--
function test0()
    local pole = {first=1, second=3, third=5, fourth=7, fifth=11}
    return pole
end
 
 
 
--
-- Test.
--
function main()
    local x = test0()
    for key,val in pairs(x) do
        print("table[" .. key .. "] = " .. val)
    end
end
 
 
 
main()

Podívejme se nyní na bajtkód vytvořený překladem demonstračního příkladu Test20.lua. Můžeme zde vidět již známou instrukci NEWTABLE a taktéž novou instrukci SETTABLE sloužící pro přidání prvku do asociativního pole:

function <Test20.lua:10,13> (8 instructions at 0x961ec88)
0 params, 2 slots, 0 upvalues, 1 local, 10 constants, 0 functions
        1       [11]    NEWTABLE        0 0 5    // konstrukce nové tabulky o velikosti 5 položek
        2       [11]    SETTABLE        0 -1 -2  // vložení nové dvojice ("first" 1) do tabulky
        3       [11]    SETTABLE        0 -3 -4  // vložení nové dvojice ("second" 3) do tabulky
        4       [11]    SETTABLE        0 -5 -6  // vložení nové dvojice ("third" 5) do tabulky
        5       [11]    SETTABLE        0 -7 -8  // vložení nové dvojice ("fourth" 7) do tabulky
        6       [11]    SETTABLE        0 -9 -10 // vložení nové dvojice ("fifth" 11) do tabulky
        7       [12]    RETURN          0 2      // tabulka je návratovou hodnotou
        8       [13]    RETURN          0 1      // implicitně vkládáno překladačem
 
function <Test20.lua:20,25> (16 instructions at 0x961f178)
0 params, 11 slots, 1 upvalue, 6 locals, 5 constants, 0 functions
        1       [21]    GETTABUP        0 0 -1   // příprava na volání funkce "test0"
        2       [21]    CALL            0 1 2
        3       [22]    GETTABUP        1 0 -2   // příprava na volání funkce "pairs"
        4       [22]    MOVE            2 0
        5       [22]    CALL            1 2 4    // zavolání funkce "pairs"
        6       [22]    JMP             0 7     ; to 14
        7       [23]    GETTABUP        6 0 -3   // příprava na volání funkce "print"
        8       [23]    LOADK           7 -4    ; "table["
        9       [23]    MOVE            8 4
        10      [23]    LOADK           9 -5    ; "] = "
        11      [23]    MOVE            10 5
        12      [23]    CONCAT          7 7 10
        13      [23]    CALL            6 2 1    // zavolání funkce "print"
        14      [22]    TFORCALL        1 2
        15      [22]    TFORLOOP        3 -9    ; to 7
        16      [25]    RETURN          0 1      // implicitně vkládáno překladačem

12. Demonstrační příklad Test19.py: vytvoření seznamu

V demonstračním příkladu nazvaném Test19.py je ukázáno vytvoření seznamu obsahujícího několik číselných položek a dále pak seznamu obsahujícího jako své prvky podseznamy (toto je jedna z možností, jak v Pythonu vytvořit obdobu matic):

#
# Vytvoreni seznamu.
#
 
 
 
#
# Vytvoreni jednoducheho seznamu.
#
def test0():
    ntice = [1, 2, 3, 4]
    return ntice
 
 
 
#
# Vytvoreni seznamu seznamu.
#
def test1():
    pole = [[1, 2], [3, 4]]
    return pole
 
 
 
#
# Test.
#
def main():
    print(test0())
    print(test1())
 
 
 
#
# Ukazka disasembleru.
#
def disassemble():
    from dis import dis
 
    print("\ntest0:")
    dis(test0)
 
    print("\ntest1:")
    dis(test1)
 
main()
 
disassemble()

Následuje bajtkód vzniklý překladem tohoto demonstračního příkladu:

test0:
 11           0 LOAD_CONST               1 // načtení konstanty 1
              3 LOAD_CONST               2 // načtení konstanty 2
              6 LOAD_CONST               3 // načtení konstanty 3
              9 LOAD_CONST               4 // načtení konstanty 4
             12 BUILD_LIST               4 // vytvoření seznamu o velikosti čtyři položky
             15 STORE_FAST               0 // uložit referenci do lokální proměnné
 
 12          18 LOAD_FAST                0 // uložit referenci na seznam na TOS
             21 RETURN_VALUE               // vrácení seznamu
 
test1:
 20           0 LOAD_CONST               1 // načtení konstanty 1
              3 LOAD_CONST               2 // načtení konstanty 2
              6 BUILD_LIST               2 // vytvoření podseznamu o velikosti dvě položky
              9 LOAD_CONST               3 // načtení konstanty 3
             12 LOAD_CONST               4 // načtení konstanty 4
             15 BUILD_LIST               2 // vytvoření podseznamu o velikosti dvě položky
             18 BUILD_LIST               2 // vytvoření seznamu o velikosti dvě položky typu podseznam
             21 STORE_FAST               0 // uložit referenci na pole na TOS
 
 21          24 LOAD_FAST                0 // uložit referenci na pole na TOS
             27 RETURN_VALUE               // vrácení pole

13. Demonstrační příklad Test19.py: vytvoření n-tice

Demonstrační příklad nazvaný Test20.py se v mnoha ohledech podobá předchozímu demonstračnímu příkladu, ovšem s tím (poměrně závažným) rozdílem, že se namísto seznamů vytváří n-tice, a to jak n-tice obsahující číselné konstanty, tak i n-tice obsahující další pod-n-tice :-) jako své prvky:

CS24 tip temata

#
# Vytvoreni n-tice.
#
 
 
 
#
# Vytvoreni jednoduche n-tice.
#
def test0():
    seznam = (1, 2, 3, 4)
    return seznam
 
 
#
# Vytvoreni n-tice n-tic.
#
def test1():
    pole = ((1, 2), (3, 4))
    return pole
 
 
#
# Test.
#
def main():
    print(test0())
    print(test1())
 
 
 
#
# Ukazka disasembleru.
#
def disassemble():
    from dis import dis
 
    print("\ntest0:")
    dis(test0)
 
    print("\ntest1:")
    dis(test1)
 
main()
 
disassemble()

Opět následuje bajtkód vzniklý překladem tohoto demonstračního příkladu:

test0:
 11           0 LOAD_CONST               5  // n-tice je konstanta ((1, 2, 3, 4))
              3 STORE_FAST               0  // do lokální proměnné
 
 12           6 LOAD_FAST                0  // načtení lokální proměnné na TOS
              9 RETURN_VALUE                // vrácení n-tice
 
test1:
 19           0 LOAD_CONST               5  // n-tice je konstanta ((1, 2))
              3 LOAD_CONST               6  // n-tice je konstanta ((3, 4))
              6 BUILD_TUPLE              2  // vytvoření n-tice
              9 STORE_FAST               0  // do lokální proměnné
 
 20          12 LOAD_FAST                0  // načtení lokální proměnné na TOS
             15 RETURN_VALUE                // vrácení pole

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

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

15. 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.