1 / 27

naciśnij klawisz...

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

daquan-neal
Télécharger la présentation

naciśnij klawisz...

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. naciśnij klawisz...

  2. Bytecode vs CIL Nie zawsze kto pierwszy, ten lepszy Mirosław Szymański marzec 2004 Porównanie

  3. <=> CLR – Common Language Runtime lub VES – Virtual Execution System <=> CIL – Common Intermediate Language MSIL – Microsoft Intermediate Language <=> CLI – Common Language Infrastructure Terminologia JVM – Java Virtual Machine Bytecode JVM + .class

  4. 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# 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

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

  6. Cechy wspólne • garbage collector • brak wielodziedziczenia • możliwość implementowania wielu interfejsów • jednobajtowe instrukcje

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

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

  9. CIL istnieją wersje instrukcji arytmetycznych wyrzucające OverflowException wymagane przez niektóre języki, np.: Ada95, SML add.ovf add.ovf.un (unsigned) Operacje arytmetyczne Bytecode • przepełnienie nigdy nie jest wykrywane

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

  11. Wskaźniki cd. [CIL] .method static void swap(int32& xa, int32& ya) { .maxstack 2 .locals (int32 z) ldarg xa; ldind.i4; stloc z ldarg xa; ldarg ya; ldind.i4 stind.i4; ldarg ya; ldloc z stind.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 stos ldind.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 Z stind.T zapisuje wartość typu T z wierzchołka stosu pod adresem pobranem ze stosu ldloc Z wkłada zmienną lokalną Z na stos ldloca X wkłada na stos adres zmiennej lokalnej X

  12. CIL jedna instrukcja alokująca i wywołuąca konstruktor newobj C::.ctor() 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

  13. 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 8 tail. call void Bootom() ret }

  14. CLR Stacktrace tworzony jest podczas przekazywania wyjątku Wyjątki – stack trace JVM • Stacktrace tworzony jest w momencie tworzenia obiektu wyjątku Zwykle efekt jest ten sam. Wyjątkiem jest sytuacja, gdy obiekt wyjątku tworzony jest w innej metodzie niż jest wyrzucany.

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

  16. 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); }

  17. 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 }

  18. 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 wykonania myVehicles[1] = c; } void main() { Car[] myCars = new Car[2]; m(myCars); }

  19. Klasy zagnieżdżone class outerClass{ publicintouter = 5; class innerClass{ publicvoid inc() { outer++; } } public outerClass(){ innerClass i = new innerClass(); i.inc(); } publicstaticvoid main(String args[]) { outerClass o = new outerClass(); } }

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

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

  22. 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++; } } ... }

  23. 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 }

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

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

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

  27. 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)

More Related