Pohled pod kapotu JVM – volání funkcí a metod v Lua VM, rozdíly oproti JVM

12. 8. 2014
Doba čtení: 26 minut

Sdílet

V předcházející části seriálu jsme si ukázali, jakým způsobem je v bajtkódu JVM implementováno volání statických i nestatických metod. Taktéž jsme si ukázali způsob volání konstruktorů. Dnes se budeme zabývat podobnou problematikou, ovšem z pohledu programovacího jazyka Lua a virtuálního stroje Lua VM.

Obsah

1. Volání funkcí a metod v bajtkódu Lua VM

2. Rozdíly mezi programovacími jazyky Java a Lua při volání funkcí/metod

3. Demonstrační příklad Test25.lua: volání funkcí v programovacím jazyku Lua

4. Překlad demonstračního příkladu Test25.lua do bajtkódu Lua VM

5. Globální proměnná _ENV a její použití v bajtkódu

6. Demonstrační příklad Test26.lua: výpis obsahu globální proměnné _ENV

7. Demonstrační příklad Test27.lua: výpis obsahu globální proměnné _ENV (úprava příkladu Test25.lua)

8. Demonstrační příklad Test28.lua: volání „statických metod“ v programovacím jazyku Lua

9. Překlad demonstračního příkladu Test28.lua do bajtkódu Lua VM

10. Demonstrační příklad Test29.lua: volání „nestatických metod“ v programovacím jazyku Lua

11. Překlad demonstračního příkladu Test29.lua do bajtkódu Lua VM

12. Překlad volání metod do bajtkódu

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

14. Odkazy na Internetu

1. Volání funkcí a metod v bajtkódu Lua VM

V předchozí části seriálu o programovacím jazyku Java i o virtuálním stroji Javy jsme si na několika demonstračních příkladech ukázali, jakým způsobem je v bajtkódu JVM realizováno volání metod. Víme již, že je rozdíl mezi voláním statických metod, nestatických metod, privátních metod, konstruktorů i metod předepsaných v nějakém rozhraní (interface). Volání je realizováno přes instrukce INVOKESTATIC, INVOKEVIRTUAL, INVOKESPECIALINVOKEINTERFACE. Tyto instrukce navíc využívají takzvanou signaturu metody, což je jméno metody doplněné o typ její návratové hodnoty i o počet a typ všech parametrů metody (JVM, přesněji řečeno bajtkód JVM zde musí reflektovat fakt, že Java je silně a současně i staticky typovaný programovací jazyk). Dnes se budeme zabývat podobným tématem, ovšem z pohledu programovacího jazyka Lua a bajtkódu virtuálního stroje Lua VM. Uvidíme, že mezi JVM a Lua VM existují v této oblasti značné rozdíly.

2. Rozdíly mezi programovacími jazyky Java a Lua při volání funkcí/metod

Mezi programovacími jazyky Java a Lua existují velké rozdíly v tom, jakým způsobem je realizováno volání funkcí popř. metod. Většina těchto rozdílů vychází z faktu, že programovací jazyk Java je striktně a navíc ještě staticky typovaný, což se týká i parametrů metod, zatímco v případě programovacího jazyka Lua je typ parametrů vyhodnocován až v době běhu aplikace (při volání konkrétní funkce či metody). Navíc se v jazyku Lua nemusí při volání funkcí dodržet přesný počet parametrů – nadbytečné parametry nejsou využity a naopak, pokud se při volání uvede menší počet parametrů, než by odpovídalo počtu argumentů funkce, jsou tyto argumenty nastaveny na hodnotu nil. Aby byla situace ještě poněkud komplikovanější, je v Lua možné, aby funkce vracely více než jednu hodnotu a z funkcí lze i s (na)vázanými proměnnými vytvořit uzávěr (closure). Základní rozdíly mezi Javou a Luou jsou vypsány v tabulce pod tímto odstavcem:

# Vlastnost Java Lua
1 Podpora pro volání funkcí Ne funkce()
2 Podpora pro volání metod Ano (viz níže) Ano (viz níže)
3 Volání statických metod Třída.funkce() objekt.funkce()
4 Volání nestatických metod objekt.funkce() objekt:funkce()
5 Kontrola počtu parametrů při překladu Ano Ne
6 Podpora typu parametrů při překladu Ano Ne
7 Podpora proměnného počtu parametrů Ano Ano
8 Podpora proměnného počtu návratových hodnot Ne Ano
9 Funkce je plnohodnotný datový typ Ne pro Javu<=7 Ano
10 Podpora uzávěrů (closures) Ne pro Javu<=7 Ano

3. Demonstrační příklad Test25.lua: volání funkcí v programovacím jazyce Lua

Dnešní první demonstrační příklad nazvaný Test25.lua je velmi jednoduchý. Jsou v něm implementovány funkce se jmény function1(), function2()function3(), přičemž funkce function1() neočekává žádné argumenty, funkce function2() očekává jeden argument a konečně funkce function3() očekává dva argumenty, které jsou sečteny (v případě, že argumenty nejsou typu celé či reálné číslo, vznikne při běhu programu chyba). Všechny tři zmíněné funkce jsou volány z kódu, který je implementován v další trojici funkcí nazvaných callFunction1(), callFunction2()callFunction3(). Povšimněte si, že se nikde nekontroluje ani počet ani typ skutečně předávaných parametrů:

--
-- Demonstracni priklad cislo 25.
--
-- Volani funkci v programovacim jazyce Lua.
--
 
 
 
--
-- Funkce bez parametru.
--
function function1()
end
 
 
 
--
-- Funkce s jednim parametrem.
--
function function2(x)
    return x
end
 
 
 
--
-- Funkce se dvema parametry.
--
function function3(x, y)
    if x and y then
        return x+y
    else
        return nil
    end
end
 
 
 
--
-- Volani funkce function1().
--
function callFunction1()
    function1()
    function1(nil)
    function1(42)
    function1(1, 2)
    function1("xyzzy")
end
 
 
 
--
-- Volani funkce function2().
--
function callFunction2()
    function2()
    function2(nil)
    function2(42)
    function2(1, 2)
    function2("xyzzy")
end
 
 
 
--
-- Volani funkce function3().
--
function callFunction3()
    function3()
    function3(nil)
    function3(42)
    function3(1, 2)
    function3("xyzzy")
end
 
 
 
--
-- Spusteni testu.
--
function main()
    callFunction1()
    callFunction2()
    callFunction3()
end
 
 
 
main()
 
 
 
--
-- Finito.
--

4. Překlad demonstračního příkladu Test25.lua do bajtkódu Lua VM

Funkce function1(), function2()function3() se do bajtkódu Lua VM přeloží následujícím způsobem:

function1():
function <Test25.lua:12,13> (1 instruction at 0x8549c88)
0 params, 2 slots, 0 upvalues, 0 locals, 0 constants, 0 functions
        1       [13]    RETURN          0 1    ; navrat z funkce (automaticky vkladana instrukce)
constants (0) for 0x8549c88:
locals (0) for 0x8549c88:
upvalues (0) for 0x8549c88:
 
 
 
function2():
function <Test25.lua:20,22> (2 instructions at 0x8549de0)
1 param, 2 slots, 0 upvalues, 1 local, 0 constants, 0 functions
        1       [21]    RETURN          0 2    ; navratova hodnota - konstanta ulozena na indexu 2
        2       [22]    RETURN          0 1    ; navrat z funkce (automaticky vkladana instrukce)
constants (0) for 0x8549de0:
locals (1) for 0x8549de0:
        0       x       1       3              ; parametr funkce zde vystupuje jako lokalni promenna
upvalues (0) for 0x8549de0:
 
 
 
function3():
function <Test25.lua:29,35> (10 instructions at 0x8549f58)
2 params, 3 slots, 0 upvalues, 2 locals, 0 constants, 0 functions
        1       [30]    TEST            0 0    ; test hodnoty prvniho parametru funkce
        2       [30]    JMP             0 5    ; kdyz x==nil, skok na instrukci cislo 8
        3       [30]    TEST            1 0    ; test hodnoty druheho parametru funkce
        4       [30]    JMP             0 3    ; kdyz y==nil, skok na instrukci cislo 8
        5       [31]    ADD             2 0 1  ; secist hodnoty obou parametru
        6       [31]    RETURN          2 2    ; a vratit vysledek souctu
        7       [31]    JMP             0 2    ; skok na instrukci cislo 10
        8       [33]    LOADNIL         2 0    ; cil obou podminenych skoku, bude se vracet nil
        9       [33]    RETURN          2 2    ; vyskok z funkce, vraci se hodnota nil
        10      [35]    RETURN          0 1    ; navrat z funkce (automaticky vkladana instrukce)
constants (0) for 0x8549f58:
locals (2) for 0x8549f58:
        0       x       1       11             ; prvni parametr funkce zde vystupuje jako lokalni promenna
        1       y       1       11             ; druhy parametr funkce zde vystupuje jako lokalni promenna
upvalues (0) for 0x8549f58:

Na způsobu překladu všech tří funkcí function1(), function2()function3() není nic překvapivého, zajímavější ovšem bude zjistit, jakým způsobem se tyto funkce volají:

callFunction1():
function <Test25.lua:42,48> (16 instructions at 0x8549d88)
0 params, 3 slots, 1 upvalue, 0 locals, 6 constants, 0 functions
        1       [43]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        2       [43]    CALL            0 1 1   ; zavolani funkce function1()
        3       [44]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        4       [44]    LOADNIL         1 0     ; parametr funkce se preda v registru R1
        5       [44]    CALL            0 2 1   ; zavolani funkce function1()
        6       [45]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        7       [45]    LOADK           1 -2    ; parametr funkce se preda v registru R1
        8       [45]    CALL            0 2 1   ; zavolani funkce function1()
        9       [46]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        10      [46]    LOADK           1 -4    ; prvni parametr funkce
        11      [46]    LOADK           2 -5    ; druhy parametr funkce
        12      [46]    CALL            0 3 1   ; zavolani funkce function1()
        13      [47]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        14      [47]    LOADK           1 -6    ; prvni parametr funkce se preda v registru R1
        15      [47]    CALL            0 2 1   ; zavolani funkce function1()
        16      [48]    RETURN          0 1     ; navrat z funkce (automaticky vkladana instrukce)
constants (6) for 0x8549d88:
        1       "function1"
        2       42
        3       "function3"
        4       1
        5       2
        6       "xyzzy"
locals (0) for 0x8549d88:
upvalues (1) for 0x8549d88:
        0       _ENV    0       0
 
 
 
callFunction2():
function <Test25.lua:55,61> (16 instructions at 0x854a410)
0 params, 3 slots, 1 upvalue, 0 locals, 6 constants, 0 functions
        1       [56]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        2       [56]    CALL            0 1 1   ; zavolani funkce function2()
        3       [57]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        4       [57]    LOADNIL         1 0     ; parametr funkce se preda v registru R1
        5       [57]    CALL            0 2 1   ; zavolani funkce function2()
        6       [58]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        7       [58]    LOADK           1 -2    ; parametr funkce se preda v registru R1
        8       [58]    CALL            0 2 1   ; zavolani funkce function2()
        9       [59]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        10      [59]    LOADK           1 -4    ; prvni parametr funkce
        11      [59]    LOADK           2 -5    ; druhy parametr funkce
        12      [59]    CALL            0 3 1   ; zavolani funkce function1()
        13      [60]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        14      [60]    LOADK           1 -6    ; prvni parametr funkce se preda v registru R1
        15      [60]    CALL            0 2 1   ; zavolani funkce function2()
        16      [61]    RETURN          0 1     ; navrat z funkce (automaticky vkladana instrukce)
constants (6) for 0x854a410:
        1       "function2"
        2       42
        3       "function3"
        4       1
        5       2
        6       "xyzzy"
locals (0) for 0x854a410:
upvalues (1) for 0x854a410:
        0       _ENV    0       0
 
 
 
callFunction3():
function <Test25.lua:68,74> (16 instructions at 0x854a690)
0 params, 3 slots, 1 upvalue, 0 locals, 5 constants, 0 functions
        1       [69]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        2       [69]    CALL            0 1 1   ; zavolani funkce function3()
        3       [70]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        4       [70]    LOADNIL         1 0     ; parametr funkce se preda v registru R1
        5       [70]    CALL            0 2 1   ; zavolani funkce function3()
        6       [71]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        7       [71]    LOADK           1 -2    ; parametr funkce se preda v registru R1
        8       [71]    CALL            0 2 1   ; zavolani funkce function3()
        9       [72]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        10      [72]    LOADK           1 -3    ; prvni parametr funkce
        11      [72]    LOADK           2 -4    ; druhy parametr funkce
        12      [72]    CALL            0 3 1   ; zavolani funkce function1()
        13      [73]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na funkci
        14      [73]    LOADK           1 -5    ; prvni parametr funkce se preda v registru R1
        15      [73]    CALL            0 2 1   ; zavolani funkce function3()
        16      [74]    RETURN          0 1     ; navrat z funkce (automaticky vkladana instrukce)
constants (5) for 0x854a690:
        1       "function3"
        2       42
        3       1
        4       2
        5       "xyzzy"
locals (0) for 0x854a690:
upvalues (1) for 0x854a690:
        0       _ENV    0       0

5. Globální proměnná _ENV a její použití v bajtkódu

Z předchozího výpisu bajtkódu je patrné, že volání všech tří funkcí se provádí naprosto stejným způsobem, bez ohledu na očekávaný počet parametrů. Hodnoty aktuálních parametrů se přenáší v pracovních registrech, ne tedy na zásobníku, jako je tomu v JVM. Samotné zavolání funkce zajišťuje dvojice instrukcí GETTABUPCALL, přičemž instrukce CALL očekává v prvním uvedeném registru referenci na volanou funkci, která je získána přes instrukci GETTABUP z globální proměnné _ENV.

Právě lokální proměnná nazvaná _ENV má v bajtkódu Lua VM velký význam, protože jsou v ní uloženy mj. i všechny globální funkce. Připomeňme si, že v programovacím jazyku Lua jsou funkce plnohodnotným datovým typem, což mj. znamená, že funkce (=hodnoty datového typu function) lze přiřazovat do proměnných, předávat je jiným funkcím jako parametry, získávat funkce jako návratovou hodnotu jiných funkcí atd. Právě díky této vlastnosti funkcí (viz též http://lua-users.org/wiki/FunctionsTutorial) je konstrukce bajtkódu při volání funkcí tak jednoduchá a navíc univerzální (nemusí se zavádět takové monstrózní jazykové konstrukce jako jsou anonymní třídy v Javě jen proto, že je zapotřebí v určitém místě kódu předat odkaz/referenci na již existující funkci nebo na funkci vytvořenou přímo na místě, kde je její tělo využíváno).

6. Demonstrační příklad Test26.lua: výpis obsahu globální proměnné _ENV

Dnešní druhý demonstrační příklad nazvaný Test26.lua je velmi jednoduchý. Po svém spouštění vypíše na standardní výstup obsah globální proměnné _ENV popsané v předchozí kapitole. Žádná další činnost se neprovádí:

--
-- Demonstracni priklad cislo 26.
--
-- Vypis obsahu lokalni promenne _ENV.
--
 
 
 
--
-- Spusteni testu.
--
function main()
    -- vypis obsahu celeho asociativniho pole _ENV
    for key,val in pairs(_ENV) do
         print(key,val)
    end
end
 
 
 
main()
 
 
 
--
-- Finito.
--

Podívejme se nyní na to, jaký obsah proměnná _ENV měla na testovacím počítači. Pro větší přehlednost byl výstup seřazen filtrem sort. Vyznačen je prvek main odpovídající stejnojmenné funkci implementované v demonstračním příkladu:

arg             table: 0x9845970
assert          function: 0x8061d80
bit32           table: 0x98430e8
collectgarbage  function: 0x8061c80
coroutine       table: 0x98437a0
debug           table: 0x9844160
dofile          function: 0x8061be0
error           function: 0x8061b50
getmetatable    function: 0x8061ae0
_G              table: 0x9842308
io              table: 0x9843b58
ipairs          function: 0x8061710
loadfile        function: 0x8061a40
load            function: 0x8061820
loadstring      function: 0x8061820
main            function: 0x9845de0
math            table: 0x9844f68
module          function: 0x9843700
next            function: 0x8061730
os              table: 0x9843930
package         table: 0x9842858
pairs           function: 0x80616f0
pcall           function: 0x8061580
print           function: 0x8061420
rawequal        function: 0x80613c0
rawget          function: 0x80612f0
rawlen          function: 0x8061350
rawset          function: 0x8061280
require         function: 0x9843740
select          function: 0x8061140
setmetatable    function: 0x8061070
string          table: 0x9842d58
table           table: 0x98439a8
tonumber        function: 0x8060e70
tostring        function: 0x8060e30
type            function: 0x8060de0
unpack          function: 0x80694a0
_VERSION        Lua 5.2
xpcall          function: 0x8060cf0

7. Demonstrační příklad Test27.lua: výpis obsahu globální proměnné _ENV (úprava příkladu Test25.lua)

Zkusme si nyní pro úplnost zkombinovat oba předchozí demonstrační příklady Test25.luaTest26.lua, aby bylo možné se ujistit, že reference na volané funkce jsou skutečně uloženy v globální proměnné _ENV. Nový demonstrační příklad nazvaný Test27.lua obsahuje všech šest funkcí function1(), function2(), function3(), callFunction1(), callFunction2()callFunction3(). Tyto funkce by měly být viditelné ve výpisu globální proměnné _ENV:

--
-- Demonstracni priklad cislo 27.
--
-- Kombinace prikladu 25 a 26.
--
 
 
 
--
-- Funkce bez parametru.
--
function function1()
end
 
 
 
--
-- Funkce s jednim parametrem.
--
function function2(x)
    return x
end
 
 
 
--
-- Funkce se dvema parametry.
--
function function3(x, y)
    if x and y then
        return x+y
    else
        return nil
    end
end
 
 
 
--
-- Volani funkce function1().
--
function callFunction1()
    function1()
    function1(nil)
    function1(42)
    function3(1, 2)
    function1("xyzzy")
end
 
 
 
--
-- Volani funkce function2().
--
function callFunction2()
    function2()
    function2(nil)
    function2(42)
    function3(1, 2)
    function2("xyzzy")
end
 
 
 
--
-- Volani funkce function3().
--
function callFunction3()
    function3()
    function3(nil)
    function3(42)
    function3(1, 2)
    function3("xyzzy")
end
 
 
 
--
-- Spusteni testu.
--
function main()
    -- vypis obsahu celeho asociativniho pole _ENV
    for key,val in pairs(_ENV) do
         print(key,val)
    end
end
 
 
 
main()
 
 
 
--
-- Finito.
--

Po spuštění tohoto demonstračního příkladu lze ze (seřazeného) výpisu obsahu globální proměnné _ENV vyčíst, že jsou zde skutečně uloženy jak všechny tři volané funkce, tak i volající funkce, funkce main atd. atd.:

arg             table: 0x95ec970
assert          function: 0x8061d80
bit32           table: 0x95ea0e8
callFunction1   function: 0x95edf70
callFunction2   function: 0x95edd68
callFunction3   function: 0x95ecde0
collectgarbage  function: 0x8061c80
coroutine       table: 0x95ea7a0
debug           table: 0x95eb160
dofile          function: 0x8061be0
error           function: 0x8061b50
function1       function: 0x95ed7e0
function2       function: 0x95edc80
function3       function: 0x95edcb0
getmetatable    function: 0x8061ae0
_G              table: 0x95e9308
io              table: 0x95eab58
ipairs          function: 0x8061710
loadfile        function: 0x8061a40
load            function: 0x8061820
loadstring      function: 0x8061820
main            function: 0x95ed6e0
math            table: 0x95ebf68
module          function: 0x95ea700
next            function: 0x8061730
os              table: 0x95ea930
package         table: 0x95e9858
pairs           function: 0x80616f0
pcall           function: 0x8061580
print           function: 0x8061420
rawequal        function: 0x80613c0
rawget          function: 0x80612f0
rawlen          function: 0x8061350
rawset          function: 0x8061280
require         function: 0x95ea740
select          function: 0x8061140
setmetatable    function: 0x8061070
string          table: 0x95e9d58
table           table: 0x95ea9a8
tonumber        function: 0x8060e70
tostring        function: 0x8060e30
type            function: 0x8060de0
unpack          function: 0x80694a0
_VERSION        Lua 5.2
xpcall          function: 0x8060cf0

8. Demonstrační příklad Test28.lua: volání „statických metod“ v programovacím jazyku Lua

Díky tomu, že funkce jsou v programovacím jazyku Lua plnohodnotným datovým typem, je možné odkazy/reference na funkce vkládat i do tabulek (což je jediný strukturovaný datový typ tohoto jazyka). Tímto způsobem je možné v Lue vytvořit objekty, přičemž funkce vložené do tabulek lze chápat jako obdobu „statických metod“. „Statické metody“ jsou běžné funkce, při jejichž deklaraci je mezi jménem tabulky a jménem funkce použita tečka, která je též použita při volání této funkce. Podívejme se na příklad Test28.lua, který je přímo odvozen od dnešního prvního příkladu Test25.lua až na ten rozdíl, že původní funkce function1(), function2()function3() jsou uloženy do tabulky testClass:

--
-- Demonstracni priklad cislo 28.
--
-- Volani "statickych metod" v programovacim jazyce Lua.
--
 
 
 
testClass = {}
 
--
-- Funkce/staticka metoda bez parametru.
--
function testClass.function1()
end
 
 
 
--
-- Funkce/staticka metoda s jednim parametrem.
--
function testClass.function2(x)
    return x
end
 
 
 
--
-- Funkce/staticka metoda se dvema parametry.
--
function testClass.function3(x, y)
    if x and y then
        return x+y
    else
        return nil
    end
end
 
 
 
--
-- Volani funkci/statickych metod.
--
function callFunction1()
    testClass.function1()
    testClass.function1(nil)
    testClass.function1(42)
    testClass.function1(1, 2)
    testClass.function1("xyzzy")
end
 
 
 
--
-- Volani funkce function2().
--
function callFunction2()
    testClass.function2()
    testClass.function2(nil)
    testClass.function2(42)
    testClass.function2(1, 2)
    testClass.function2("xyzzy")
end
 
 
 
--
-- Volani funkce function3().
--
function callFunction3()
    testClass.function3()
    testClass.function3(nil)
    testClass.function3(42)
    testClass.function3(1, 2)
    testClass.function3("xyzzy")
end
 
 
 
--
-- Spusteni testu.
--
function main()
    callFunction1()
    callFunction2()
    callFunction3()
end
 
 
 
main()
 
 
 
--
-- Finito.
--

9. Překlad demonstračního příkladu Test28.lua do bajtkódu Lua VM

Zajímavé bude se podívat na způsob překladu demonstračního příkladu Test28.lua. Nejprve si opět uvedeme překlad všech tří volaných „statických metod“:

function1():
function <Test28.lua:14,15> (1 instruction at 0x87f2d00)
0 params, 2 slots, 0 upvalues, 0 locals, 0 constants, 0 functions
        1       [15]    RETURN          0 1    ; navrat z funkce (automaticky vkladana instrukce)
constants (0) for 0x87f2d00:
locals (0) for 0x87f2d00:
upvalues (0) for 0x87f2d00:
 
 
 
function2():
function <Test28.lua:22,24> (2 instructions at 0x87f2e20)
1 param, 2 slots, 0 upvalues, 1 local, 0 constants, 0 functions
        1       [23]    RETURN          0 2    ; navratova hodnota - konstanta ulozena na indexu 2
        2       [24]    RETURN          0 1    ; navrat z funkce (automaticky vkladana instrukce)
constants (0) for 0x87f2e20:
locals (1) for 0x87f2e20:
        0       x       1       3              ; parametr funkce zde vystupuje jako lokalni promenna
upvalues (0) for 0x87f2e20:
 
 
 
function3():
function <Test28.lua:31,37> (10 instructions at 0x87f2ca8)
2 params, 3 slots, 0 upvalues, 2 locals, 0 constants, 0 functions
        1       [32]    TEST            0 0    ; test hodnoty prvniho parametru funkce
        2       [32]    JMP             0 5    ; kdyz x==nil, skok na instrukci cislo 8
        3       [32]    TEST            1 0    ; test hodnoty druheho parametru funkce
        4       [32]    JMP             0 3    ; kdyz y==nil, skok na instrukci cislo 8
        5       [33]    ADD             2 0 1  ; secist hodnoty obou parametru
        6       [33]    RETURN          2 2    ; a vratit vysledek souctu
        7       [33]    JMP             0 2    ; skok na instrukci cislo 10
        8       [35]    LOADNIL         2 0    ; cil obou podminenych skoku, bude se vracet nil
        9       [35]    RETURN          2 2    ; vyskok z funkce, vraci se hodnota nil
        10      [37]    RETURN          0 1    ; navrat z funkce (automaticky vkladana instrukce)
constants (0) for 0x87f2ca8:
locals (2) for 0x87f2ca8:
        0       x       1       11             ; prvni parametr funkce zde vystupuje jako lokalni promenna
        1       y       1       11             ; druhy parametr funkce zde vystupuje jako lokalni promenna
upvalues (0) for 0x87f2ca8:

Oproti prvnímu demonstračnímu příkladu zde nenastaly žádné změny, ovšem rozdílný je inicializační kód, který tabulku _ENV naplní:

        1       [9]     NEWTABLE        0 0 0
        2       [9]     SETTABUP        0 -1 0  ; _ENV "testClass"
        3       [14]    GETTABUP        0 0 -1  ; _ENV "testClass"
        4       [15]    CLOSURE         1 0     ; 0x87f2d00
        5       [14]    SETTABLE        0 -2 1  ; "function1" -
        6       [22]    GETTABUP        0 0 -1  ; _ENV "testClass"
        7       [24]    CLOSURE         1 1     ; 0x87f2e20
        8       [22]    SETTABLE        0 -3 1  ; "function2" -
        9       [31]    GETTABUP        0 0 -1  ; _ENV "testClass"
        10      [37]    CLOSURE         1 2     ; 0x87f2ca8
        11      [31]    SETTABLE        0 -4 1  ; "function3" -
        12      [50]    CLOSURE         0 3     ; 0x87f3398
        13      [44]    SETTABUP        0 -5 0  ; _ENV "callFunction1"
        14      [63]    CLOSURE         0 4     ; 0x87f3528
        15      [57]    SETTABUP        0 -6 0  ; _ENV "callFunction2"
        16      [76]    CLOSURE         0 5     ; 0x87f3238
        17      [70]    SETTABUP        0 -7 0  ; _ENV "callFunction3"
        18      [87]    CLOSURE         0 6     ; 0x87f3830
        19      [83]    SETTABUP        0 -8 0  ; _ENV "main"
        20      [91]    GETTABUP        0 0 -8  ; _ENV "main"
        21      [91]    CALL            0 1 1
        22      [91]    RETURN          0 1
constants (8) for 0x87f2b50:
        1       "testClass"
        2       "function1"
        3       "function2"
        4       "function3"
        5       "callFunction1"
        6       "callFunction2"
        7       "callFunction3"
        8       "main"

Nyní se podívejme na způsob volání všech tří testovacích statických metod:

function <Test28.lua:44,50> (21 instructions at 0x87f3398)
0 params, 3 slots, 1 upvalue, 0 locals, 7 constants, 0 functions
        1       [45]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        2       [45]    GETTABLE        0 0 -2  ; "function1"
        3       [45]    CALL            0 1 1   ; zavolani funkce function1()
        4       [46]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        5       [46]    GETTABLE        0 0 -2  ; "function1"
        6       [46]    LOADNIL         1 0     ; parametr funkce se preda v registru R1
        7       [46]    CALL            0 2 1   ; zavolani funkce function1()
        8       [47]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        9       [47]    GETTABLE        0 0 -2  ; "function1"
        10      [47]    LOADK           1 -3    ; 42
        11      [47]    CALL            0 2 1   ; zavolani funkce function1()
        12      [48]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        13      [48]    GETTABLE        0 0 -2  ; "function3"
        14      [48]    LOADK           1 -5    ; 1
        15      [48]    LOADK           2 -6    ; 2
        16      [48]    CALL            0 3 1   ; zavolani funkce function1()
        17      [49]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        18      [49]    GETTABLE        0 0 -2  ; "function1"
        19      [49]    LOADK           1 -7    ; "xyzzy"
        20      [49]    CALL            0 2 1   ; zavolani funkce function1()
        21      [50]    RETURN          0 1     ; navrat z funkce (automaticky vkladana instrukce)
constants (7) for 0x87f3398:
        1       "testClass"
        2       "function1"
        3       42
        4       "function3"
        5       1
        6       2
        7       "xyzzy"
locals (0) for 0x87f3398:
upvalues (1) for 0x87f3398:
        0       _ENV    0       0
 
 
 
function <Test28.lua:57,63> (21 instructions at 0x87f3528)
0 params, 3 slots, 1 upvalue, 0 locals, 7 constants, 0 functions
        1       [58]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        2       [58]    GETTABLE        0 0 -2  ; "function2"
        3       [58]    CALL            0 1 1   ; zavolani funkce function2()
        4       [59]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        5       [59]    GETTABLE        0 0 -2  ; "function2"
        6       [59]    LOADNIL         1 0     ; parametr funkce se preda v registru R1
        7       [59]    CALL            0 2 1   ; zavolani funkce function2()
        8       [60]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        9       [60]    GETTABLE        0 0 -2  ; "function2"
        10      [60]    LOADK           1 -3    ; 42
        11      [60]    CALL            0 2 1   ; zavolani funkce function2()
        12      [61]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        13      [61]    GETTABLE        0 0 -2  ; "function2"
        14      [61]    LOADK           1 -5    ; 1
        15      [61]    LOADK           2 -6    ; 2
        16      [61]    CALL            0 3 1   ; zavolani funkce function2()
        17      [62]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        18      [62]    GETTABLE        0 0 -2  ; "function2"
        19      [62]    LOADK           1 -7    ; "xyzzy"
        20      [62]    CALL            0 2 1   ; zavolani funkce function2()
        21      [63]    RETURN          0 1     ; navrat z funkce (automaticky vkladana instrukce)
constants (7) for 0x87f3528:
        1       "testClass"
        2       "function2"
        3       42
        4       "function3"
        5       1
        6       2
        7       "xyzzy"
locals (0) for 0x87f3528:
upvalues (1) for 0x87f3528:
        0       _ENV    0       0
 
 
 
function <Test28.lua:70,76> (21 instructions at 0x87f3238)
0 params, 3 slots, 1 upvalue, 0 locals, 6 constants, 0 functions
        1       [71]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        2       [71]    GETTABLE        0 0 -2  ; "function3"
        3       [71]    CALL            0 1 1   ; zavolani funkce function3()
        4       [72]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        5       [72]    GETTABLE        0 0 -2  ; "function3"
        6       [72]    LOADNIL         1 0     ; parametr funkce se preda v registru R1
        7       [72]    CALL            0 2 1   ; zavolani funkce function3()
        8       [73]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        9       [73]    GETTABLE        0 0 -2  ; "function3"
        10      [73]    LOADK           1 -3    ; 42
        11      [73]    CALL            0 2 1   ; zavolani funkce function3()
        12      [74]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        13      [74]    GETTABLE        0 0 -2  ; "function3"
        14      [74]    LOADK           1 -4    ; 1
        15      [74]    LOADK           2 -5    ; 2
        16      [74]    CALL            0 3 1   ; zavolani funkce function3()
        17      [75]    GETTABUP        0 0 -1  ; z globalni promenne _ENV ziskat referenci na testClass
        18      [75]    GETTABLE        0 0 -2  ; "function3"
        19      [75]    LOADK           1 -6    ; "xyzzy"
        20      [75]    CALL            0 2 1   ; zavolani funkce function3()
        21      [76]    RETURN          0 1     ; navrat z funkce (automaticky vkladana instrukce)
constants (6) for 0x87f3238:
        1       "testClass"
        2       "function3"
        3       42
        4       1
        5       2
        6       "xyzzy"
locals (0) for 0x87f3238:
upvalues (1) for 0x87f3238:
        0       _ENV    0       0

Vidíme, že volání „statických metod“ se skutečně liší, a to zejména kvůli nutnosti načítat odkaz/referenci na funkci nikoli přímo z tabulky _ENV, ale z tabulky testClass. To je vlastně jediný rozdíl oproti prvnímu demonstračnímu příkladu.

10. Demonstrační příklad Test29.lua: volání „nestatických metod“ v programovacím jazyku Lua

V programovacím jazyku Lua je možné funkce vkládat do tabulek i s využitím dvojtečky namísto tečky. Tento malý syntaktický rozdíl však vede k vytvoření sémanticky odlišného kódu – takto vytvořená funkce totiž bude mít navíc jeden parametr, v němž se předá odkaz na objekt, tedy hodnota, která se v jiných programovacích jazycích označuje klíčovým slovem self nebo this. Odlišné je pak i volání takových funkcí, které lze podle jejich vlastností již nazývat „metodami“:

--
-- Demonstracni priklad cislo 29.
--
-- Volani "metod" v programovacim jazyce Lua.
--
 
 
 
testClass = {}
 
--
-- Funkce/metoda bez parametru.
--
function testClass:function1()
end
 
 
 
--
-- Funkce/metoda s jednim parametrem.
--
function testClass:function2(x)
    return x
end
 
 
 
--
-- Funkce/metoda se dvema parametry.
--
function testClass:function3(x, y)
    if x and y then
        return x+y
    else
        return nil
    end
end
 
 
 
--
-- Volani funkce function1().
--
function callFunction1()
    testClass:function1()
    testClass:function1(nil)
    testClass:function1(42)
    testClass:function1(1, 2)
    testClass:function1("xyzzy")
end
 
 
 
--
-- Volani funkce function2().
--
function callFunction2()
    testClass:function2()
    testClass:function2(nil)
    testClass:function2(42)
    testClass:function2(1, 2)
    testClass:function2("xyzzy")
end
 
 
 
--
-- Volani funkce function3().
--
function callFunction3()
    testClass:function3()
    testClass:function3(nil)
    testClass:function3(42)
    testClass:function3(1, 2)
    testClass:function3("xyzzy")
end
 
 
 
--
-- Spusteni testu.
--
function main()
    callFunction1()
    callFunction2()
    callFunction3()
end
 
 
 
main()
 
 
 
--
-- Finito.
--

11. Překlad demonstračního příkladu Test29.lua do bajtkódu Lua VM

Jak se výše uvedený příklad přeloží do bajtkódu?

function1():
function <Test29.lua:14,15> (1 instruction at 0x8cb2d00)
1 param, 2 slots, 0 upvalues, 1 local, 0 constants, 0 functions
        1       [15]    RETURN          0 1
constants (0) for 0x8cb2d00:
locals (1) for 0x8cb2d00:
        0       self    1       2              novy parametr!
upvalues (0) for 0x8cb2d00:
 
 
 
function2():
function <Test29.lua:22,24> (2 instructions at 0x8cb2ea8)
2 params, 2 slots, 0 upvalues, 2 locals, 0 constants, 0 functions
        1       [23]    RETURN          1 2
        2       [24]    RETURN          0 1
constants (0) for 0x8cb2ea8:
locals (2) for 0x8cb2ea8:
        0       self    1       3              novy parametr!
        1       x       1       3
upvalues (0) for 0x8cb2ea8:
 
 
 
function3():
function <Test29.lua:31,37> (10 instructions at 0x8cb2ca8)
3 params, 4 slots, 0 upvalues, 3 locals, 0 constants, 0 functions
        1       [32]    TEST            1 0     zde je zmena, posun indexu parametru!
        2       [32]    JMP             0 5     ; to 8
        3       [32]    TEST            2 0     zde je zmena, posun indexu parametru!
        4       [32]    JMP             0 3     ; to 8
        5       [33]    ADD             3 1 2
        6       [33]    RETURN          3 2
        7       [33]    JMP             0 2     ; to 10
        8       [35]    LOADNIL         3 0
        9       [35]    RETURN          3 2
        10      [37]    RETURN          0 1
constants (0) for 0x8cb2ca8:
locals (3) for 0x8cb2ca8:
        0       self    1       11              novy parametr!
        1       x       1       11
        2       y       1       11
upvalues (0) for 0x8cb2ca8:

Při zpracování parametrů jsou indexy oproti předchozímu příkladu o jedničku zvýšeny, protože prvním parametrem je self, což je ostatně patrné i ze struktury locals.

12. Překlad volání metod do bajtkódu

Volání metod vypadá v bajtkódu následovně:

function <Test29.lua:44,50> (21 instructions at 0x8cb3450)
0 params, 4 slots, 1 upvalue, 0 locals, 7 constants, 0 functions
        1       [45]    GETTABUP        0 0 -1  ; _ENV "testClass"
        2       [45]    SELF            0 0 -2  ; "function1"
        3       [45]    CALL            0 2 1
        4       [46]    GETTABUP        0 0 -1  ; _ENV "testClass"
        5       [46]    SELF            0 0 -2  ; "function1"
        6       [46]    LOADNIL         2 0
        7       [46]    CALL            0 3 1
        8       [47]    GETTABUP        0 0 -1  ; _ENV "testClass"
        9       [47]    SELF            0 0 -2  ; "function1"
        10      [47]    LOADK           2 -3    ; 42
        11      [47]    CALL            0 3 1
        12      [48]    GETTABUP        0 0 -1  ; _ENV "testClass"
        13      [48]    SELF            0 0 -4  ; "function3"
        14      [48]    LOADK           2 -5    ; 1
        15      [48]    LOADK           3 -6    ; 2
        16      [48]    CALL            0 4 1
        17      [49]    GETTABUP        0 0 -1  ; _ENV "testClass"
        18      [49]    SELF            0 0 -2  ; "function1"
        19      [49]    LOADK           2 -7    ; "xyzzy"
        20      [49]    CALL            0 3 1
        21      [50]    RETURN          0 1
constants (7) for 0x8cb3450:
        1       "testClass"
        2       "function1"
        3       42
        4       "function3"
        5       1
        6       2
        7       "xyzzy"
locals (0) for 0x8cb3450:
upvalues (1) for 0x8cb3450:
        0       _ENV    0       0
 
 
 
function <Test29.lua:57,63> (21 instructions at 0x8cb2df0)
0 params, 4 slots, 1 upvalue, 0 locals, 7 constants, 0 functions
        1       [58]    GETTABUP        0 0 -1  ; _ENV "testClass"
        2       [58]    SELF            0 0 -2  ; "function2"
        3       [58]    CALL            0 2 1
        4       [59]    GETTABUP        0 0 -1  ; _ENV "testClass"
        5       [59]    SELF            0 0 -2  ; "function2"
        6       [59]    LOADNIL         2 0
        7       [59]    CALL            0 3 1
        8       [60]    GETTABUP        0 0 -1  ; _ENV "testClass"
        9       [60]    SELF            0 0 -2  ; "function2"
        10      [60]    LOADK           2 -3    ; 42
        11      [60]    CALL            0 3 1
        12      [61]    GETTABUP        0 0 -1  ; _ENV "testClass"
        13      [61]    SELF            0 0 -4  ; "function3"
        14      [61]    LOADK           2 -5    ; 1
        15      [61]    LOADK           3 -6    ; 2
        16      [61]    CALL            0 4 1
        17      [62]    GETTABUP        0 0 -1  ; _ENV "testClass"
        18      [62]    SELF            0 0 -2  ; "function2"
        19      [62]    LOADK           2 -7    ; "xyzzy"
        20      [62]    CALL            0 3 1
        21      [63]    RETURN          0 1
constants (7) for 0x8cb2df0:
        1       "testClass"
        2       "function2"
        3       42
        4       "function3"
        5       1
        6       2
        7       "xyzzy"
locals (0) for 0x8cb2df0:
upvalues (1) for 0x8cb2df0:
        0       _ENV    0       0
 
 
 
function <Test29.lua:70,76> (21 instructions at 0x8cb2fd0)
0 params, 4 slots, 1 upvalue, 0 locals, 6 constants, 0 functions
        1       [71]    GETTABUP        0 0 -1  ; _ENV "testClass"
        2       [71]    SELF            0 0 -2  ; "function3"
        3       [71]    CALL            0 2 1
        4       [72]    GETTABUP        0 0 -1  ; _ENV "testClass"
        5       [72]    SELF            0 0 -2  ; "function3"
        6       [72]    LOADNIL         2 0
        7       [72]    CALL            0 3 1
        8       [73]    GETTABUP        0 0 -1  ; _ENV "testClass"
        9       [73]    SELF            0 0 -2  ; "function3"
        10      [73]    LOADK           2 -3    ; 42
        11      [73]    CALL            0 3 1
        12      [74]    GETTABUP        0 0 -1  ; _ENV "testClass"
        13      [74]    SELF            0 0 -2  ; "function3"
        14      [74]    LOADK           2 -4    ; 1
        15      [74]    LOADK           3 -5    ; 2
        16      [74]    CALL            0 4 1
        17      [75]    GETTABUP        0 0 -1  ; _ENV "testClass"
        18      [75]    SELF            0 0 -2  ; "function3"
        19      [75]    LOADK           2 -6    ; "xyzzy"
        20      [75]    CALL            0 3 1
        21      [76]    RETURN          0 1
constants (6) for 0x8cb2fd0:
        1       "testClass"
        2       "function3"
        3       42
        4       1
        5       2
        6       "xyzzy"
locals (0) for 0x8cb2fd0:
upvalues (1) for 0x8cb2fd0:
        0       _ENV    0       0

Jako novinka se zde objevuje nová instrukce SELF, která má tři operandy A,B a C. Tato instrukce naplní obsah registru R(A+1) obsahem registru R(B) a následně provede druhou operaci R(A) := R(B)[RK©], tj. naplní obsah registru R(A) hodnotou přečtenou z tabulky, jejíž reference je uložena v registru R(B) a index v konstantě RK©. Tato instrukce se použije před voláním metody pro naplnění jejího prvního (skrytého) parametru.

bitcoin_skoleni

Příště si kromě dalších informací přehledně ukážeme rozdíly mezi Lua VM a JVM při volání metod (bude se jednat o o shrnutí dnešního tématu).

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

Všech pět dnes popsaných a využitých demonstračních příkladů naprogramovaných v jazyku Lua bylo uloženo do Mercurial repositáře umístěného na adrese http://icedtea.classpath.or­g/people/ptisnovs/jvm-tools/. Odkazy na prozatím poslední verze těchto příkladů naleznete v tabulce pod tímto odstavcem:

14. Odkazy na Internetu

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