naciśnij klawisz...

27
naciśnij klawisz...

description

naciśnij klawisz. Bytecode vs CIL Nie zawsze kto pierwszy, ten lepszy Mirosław Szymański marzec 2004. Porównanie. CLR – Common Language Runtime lub VES – Virtual Execution System CIL – Common Intermediate Language MSIL – Microsoft Intermediate Language - PowerPoint PPT Presentation

Transcript of naciśnij klawisz...

Page 1: naciśnij klawisz...

naciśnij klawisz...

Page 2: naciśnij klawisz...

Bytecode vs CIL

Nie zawsze kto pierwszy, ten lepszy

Mirosław Szymańskimarzec 2004

Porównanie

Page 3: naciśnij klawisz...

Terminologia

JVM – Java Virtual Machine

Bytecode

JVM + .class

<=> CLR – Common Language Runtime lub VES – Virtual Execution System

<=> CIL – Common Intermediate Language MSIL – Microsoft Intermediate Language

<=> CLI – Common Language Infrastructure

Page 4: naciśnij klawisz...

Założenia projektowe i ich konsekwencje

Bytecode● oprogramowanie urządzeń

“sieciowych”

● zwięzłość kodu

● nacisk na możliwość interpretacji kodu (czasami chcemy uniknąć dużego kosztu kompilacji JIT)

● ograniczone wsparcie dla języków innych niż Java

CLI● zwięzłość kodu

● praktycznie rezygnacja z możliwości interpretacji

● nacisk na wspieranie wielu języków programowania (w szczególności Javy)

● w rzeczywistości języki oferowane w .NET to “skórki” na C#

Page 5: naciśnij klawisz...

Cechy wspólne

● Wirtualna maszyna

– stos + zestaw instrukcji operujących na stosie● Instrukcje wspierające obiektowy model programowania● Pliki .class oraz assembly files

– opisują klasy– wszelkie odwołania do elementów są odwołaniami

przez referencje do puli stałych, pozwala to na sprawdzanie zgodności typów podczas ładowania

Page 6: naciśnij klawisz...

Cechy wspólne

● garbage collector● brak wielodziedziczenia● możliwość implementowania wielu interfejsów● jednobajtowe instrukcje

Page 7: naciśnij klawisz...

Wirtualna maszyna – różnice

JVM● wspólna tablica dla zmiennych

lokalnych i argumentów

● pozycje w tablicy zmiennych lokalnych mogą być wielokrotnie używane, nawet dla zmiennych różnych typów

● rozmiar tablicy zm. lokalnych określony podczas kompilacji

CLR● osobne tablice dla zmiennych

lokalnych i argumentów

● pozycje w tablicy zm.lokalnych mają określony typ, mogą być używane tylko przez zmienne danego typu

● rozmiar tablicy zm.lokalnych nie jest z góry znany, ponieważ mogą tam się znaleźć struktury

● przy kompilacij znana jest tylko liczba zmiennych lokalnych

Page 8: naciśnij klawisz...

Podstawowe instrukcje

Bytecode

iload_1 ; push local int variable 1

iload_2 ; push local int variable 2

iadd ; add the two top elements

istore_3 ; pop result into variable 3

CIL

ldloc.1 ; push local variable 1

ldloc.2 ; push local variable 2

add ; add the two top elements

stloc.3 ; pop result into variable 3

Page 9: naciśnij klawisz...

Operacje arytmetyczne

Bytecode● przepełnienie nigdy nie

jest wykrywane

CIL● istnieją wersje instrukcji

arytmetycznych wyrzucające OverflowException

– wymagane przez niektóre języki, np.: Ada95, SML

add.ovf

add.ovf.un (unsigned)

Page 10: naciśnij klawisz...

Wskaźniki [CIL]

● unmanaged pointers– operacje bezpieczne (typesafe)

● odczytanie/zapisanie zawartości

– operacje niebezpieczne● pointer ± integer● pointer ± pointer

● managed pointers– np. wskaźnik do pola obiektu

– w C# używane do przekazywania parametrów typu out

Page 11: naciśnij klawisz...

Wskaźniki cd. [CIL] .method static void swap(int32& xa, int32& ya) {

.maxstack 2

.locals (int32 z)ldarg xa; ldind.i4; stloc zldarg xa; ldarg ya; ldind.i4stind.i4; ldarg ya; ldloc zstind.i4; ret

}

Przykładowe wywołanie metody swap() .locals (int32 x, int32 y)

ldloca x; ldloca y;call void swap(int32&, int32&)

ldarg X wkłada argument na stosldind.T pobiera adres ze stosu, wkłada na stos wartość spod danego adresu (dereferencja)stloc Z pobiera wartość ze stosu i zapisuje ją w argumencie Zstind.T zapisuje wartość typu T z wierzchołka stosu pod adresem pobranem ze stosuldloc Z wkłada zmienną lokalną Z na stosldloca X wkłada na stos adres zmiennej lokalnej X

Page 12: naciśnij klawisz...

Tworzenie obiektu

Bytecode● stała sekwencja instrukcji:new C

dup

invokespecial C.<init>()V

● weryfikator musi sprawdzać czy każdy obiekt został zainicjalizowany przed użyciem, oraz czy nie został zainicjalizowany więcej niż raz

CIL● jedna instrukcja alokująca i

wywołuąca konstruktor

newobj C::.ctor()

Page 13: naciśnij klawisz...

Wywołania ogonowe (tailcalls) [CIL]

● wsparcie dla języków funkcyjnych● prefiks tail. informuje kompilator, aby skasował

ramke stosu przed wywołaniem metody● następujący kod zapętli się zamiast wyrzucić wyjątek

przepełnienia stosu:

.method public static void Bottom() {.maxstack 8tail. call void Bootom()ret

}

Page 14: naciśnij klawisz...

Wyjątki – stack trace

JVM● Stack trace tworzony jest

w momencie tworzenia obiektu wyjątku

CLR● Stack trace tworzony jest

podczas przekazywania wyjątku

Zwykle efekt jest ten sam. Wyjątkiem jest sytuacja, gdy obiekt wyjątku tworzony jest w innej metodzie niż jest wyrzucany.

Page 15: naciśnij klawisz...

Tablice [CIL]

Tablice wielowymiarowe:– “prawdziwe”, np.: int[,]

– w stylu C/Java (jagged arrays), np..: int [][]● są typu System.Array, w szczególności nie jest poprawne

następujące przeciążenie metody:

void method(int [][])void method(float [][])

Tablice 0-wymiarowe - brak– jedyny język w którym zostały zaimplementowane to APL

– problemy związane z implementacją

Page 16: naciśnij klawisz...

Tablice

Pytanie: powinny być invariant czy covariant ?przykład:

class Vehicle {. . .}class Car: Vehicle {. . .}void m(Vehicle[] myVehicles) {

Vehicle v = new Vehicle();Car c = new Car();myVehicles[0] = v;myVehicles[1] = c;

}void main() {

Car[] myCars = new Car[2];m(myCars);

}

Page 17: naciśnij klawisz...

Tablice

Opcja pierwsza: invariant

class Vehicle {. . .}class Car: Vehicle {. . .}void m(Vehicle[] myVehicles) {

Vehicle v = new Vehicle();Car c = new Car();myVehicles[0] = v;myVehicles[1] = c;

}void main() {

Car[] myCars = new Car[2];m(myCars); // błąd podczas kompilacji

}

Page 18: naciśnij klawisz...

Tablice

Opcja druga: covariant (zgodna z Javą)

class Vehicle {. . .}class Car: Vehicle {. . .}void m(Vehicle[] myVehicles) {

Vehicle v = new Vehicle();Car c = new Car();myVehicles[0] = v; // błąd podczas wykonaniamyVehicles[1] = c;

}void main() {

Car[] myCars = new Car[2];m(myCars);

}

Page 19: naciśnij klawisz...

Klasy zagnieżdżoneclass outerClass{

public int outer = 5;

class innerClass{public void inc() {

outer++;}

}

public outerClass(){innerClass i = new innerClass();i.inc();

}

public static void main(String args[]) {outerClass o = new outerClass();

}}

Page 20: naciśnij klawisz...

Method void inc() aload_0 getfield #2 <Field outerClass this$0> dup getfield #4 <Field int outer> iconst_1 iadd putfield #4 <Field int outer> return}

Method outerClass. innerClass(outerClass) aload_0 invokespecial #1 <Method java.lang.Object()> aload_0 aload_1 putfield #2 <Field outerClass this$0> aload_0 iconst_3 putfield #3 <Field int inner> return

Page 21: naciśnij klawisz...

Method outerClass() aload_0 invokespecial #1 <Method java.lang.Object()> aload_0 iconst_5 putfield #2 <Field int outer> new #3 <Class outerClass. innerClass> dup aload_0 invokespecial #4 <Method outerClass. innerClass(outerClass)> astore_1 aload_1 invokevirtual #5 <Method void inc()> return

Page 22: naciśnij klawisz...

Klasy zagnieżdżone c.d.class outerClass2{

public int outer = 5;

class innerClass{public int inner = 3;

class innerClass2{

public void write2() {

inner++;outer++;

}}

...

}

Page 23: naciśnij klawisz...

Method void write2() aload_0 getfield #2 <Field outerClass2.innerClass this$1> dup getfield #4 <Field int inner> iconst_1 iadd putfield #4 <Field int inner> aload_0 getfield #2 <Field outerClass2.innerClass this$1> invokestatic #5 <Method outerClass2 access$000(outerClass2.innerClass)> dup getfield #6 <Field int outer> iconst_1 iadd putfield #6 <Field int outer> return}

Statyczna metoda klasy innerClass:

Method outerClass2 access$000(outerClass2.innerClass) 0 aload_0 1 getfield #1 <Field outerClass2 this$0> 4 areturn}

Page 24: naciśnij klawisz...

Kierunki rozwoju

JVM● klasy zagnieżdżone (na poziomie JVM)

● dodanie generics na poziomie JVM

● dodanie innych sposobów przekazywania parametrów metod

● rozwój hamowany przez konieczność zachowania kompatybilności wstecz

Page 25: naciśnij klawisz...

Kierunki rozwoju

CLI● dodanie preprocesora języka pośredniego, generującego kod

bardziej przyjazny interpretacji – cel – systemy o ograniczonych możliwościach, np. telefony komórkowe

– okrojona wersja VM mogłaby być pozbawiona możliwości dynamicznego ładowania modułów. Dzięki temu VM nie musiałaby sprawdzać zgodności typów. Efekt: bardzo mała wirtualna maszyna, idealna do urządzeń dedykowanych (telefony, mikrofalówki :) )

● dodanie generics

● dodanie wielodziedziczenia

Page 26: naciśnij klawisz...

Literatura

● “Stacking them up: a Comparison of Virtual Machines”– K. John Gough

● “The Common Language Infrastructure Annotated Standard”– Jim Miller, Susann Ragsdale, Addison Wesley 2003

● “Technical Overview of the Common Language Runtime”– Eric Meijer (Microsoft), John Gough (QUT)

● “The JavaTM Virtual Machine Specification”, Second Edition– Tim Lindholm, Frank Yellin, (java.sun.com)

● “Shared Source CLI, Essentials”– David Stutz, Ted Neward & Geoff Shilling – O'Reilly 2003

● “One Runtime to Bind Them All”– Osvaldo Pinali Doederlein, 2002

Page 27: naciśnij klawisz...

Epilog

“It would be unfair to state that the CLI as it is now, is already the perfect multi-language platform. It currently has good support for imperative (COBOL, C, Pascal, Fortran) and statically typed OO languages (such as C#, Eiffel, Oberon, Component Pascal). Microsoft continues to work with language implementers and researchers to improve support for languages in nonstandard paradigms”

Eric Meijer (Microsoft), John Gough (QUT)