DE69911468T2 - Verfahren zum direkten inlinen von virtuellen anrufen ohne on-stack-vertretung - Google Patents

Verfahren zum direkten inlinen von virtuellen anrufen ohne on-stack-vertretung Download PDF

Info

Publication number
DE69911468T2
DE69911468T2 DE69911468T DE69911468T DE69911468T2 DE 69911468 T2 DE69911468 T2 DE 69911468T2 DE 69911468 T DE69911468 T DE 69911468T DE 69911468 T DE69911468 T DE 69911468T DE 69911468 T2 DE69911468 T2 DE 69911468T2
Authority
DE
Germany
Prior art keywords
procedure
call
code
virtual
object code
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Expired - Fee Related
Application number
DE69911468T
Other languages
English (en)
Other versions
DE69911468D1 (de
Inventor
L. David DETLEFS
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Sun Microsystems Inc
Original Assignee
Sun Microsystems Inc
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Sun Microsystems Inc filed Critical Sun Microsystems Inc
Publication of DE69911468D1 publication Critical patent/DE69911468D1/de
Application granted granted Critical
Publication of DE69911468T2 publication Critical patent/DE69911468T2/de
Anticipated expiration legal-status Critical
Expired - Fee Related legal-status Critical Current

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/44Arrangements for executing specific programs
    • G06F9/448Execution paradigms, e.g. implementations of programming paradigms
    • G06F9/4488Object-oriented
    • G06F9/449Object-oriented method invocation or resolution
    • G06F9/4491Optimising based on receiver type

Description

  • HINTERGRUND DER ERFINDUNG
  • Die vorliegende Erfindung ist auf das Kompilieren von Computerprogrammen gerichtet. Insbesondere betrifft sie das sogenannte Inlinen von virtuellen Verfahren (Methods).
  • 1 zeigt ein typisches Computersystem 10. Ein Mikroprozessor 12 empfängt Daten und Befehle für einen Betrieb mit diesen von einem auf einer Platte angeordneten (On-Board) Cache-Speicher oder einem weiteren Cache-Speicher 18, möglicherweise über die Vermittlung eines Cache-Controllers 20, der wiederum derartige Daten von einem Systemlese-/Schreib-Speicher ("RAM") 22 durch einen RAM-Controller 24, oder von verschiedenen Peripherieeinrichtungen über einen Systembus 26, empfangen kann.
  • Die Daten- und Befehlsinhalte des RAM 22 werden normalerweise von Peripherieeinrichtungen wie einer Systemplatte 27 geladen worden sein. Andere Quellen umfassen eine Kommunikationsschnittstelle 28, die Befehle und Daten von anderen Computersystemen empfangen kann.
  • Die Befehle, die der Mikroprozessor ausführt, sind Maschinenbefehle. Diese Befehle werden letztlich von einem Programmierer bestimmt, aber es gibt selten einen Programmierer, der mit den spezifischen Maschinenbefehlen vertraut ist, zu denen seine Anstrengungen schließlich führen. In einer typischeren Weise schreibt der Programmierer einen "Quellcode" in einer Sprache einer höheren Ebene, aus dem eine Computersoftware – die konfiguriert ist dies zu tun, diese Maschinenbefehle oder einen "Objektcode" erzeugt.
  • 2 zeigt diese Sequenz. Der Block 30 der 2 stellt einen Kompilierer-Prozess (Compiler-Prozess) dar, den ein Computer unter der Anweisung eines Kompilierer-Objektcodes ausführt. Dieser Objektcode wird typischer Weise auf der Systemplatte 27 oder irgendeinem anderen Medium, das von einer Maschine lesbar ist, gespeichert und durch eine Übernagung von elektrischen Signalen in den Systemspeicher 24 geladen, um das Computersystem zu konfigurieren, um als ein Kompilierer (Compiler) zu arbeiten. Der fortwährende Speicher des Kompilierer-Objektcodes kann aber anstelle davon in einem Serversystem entfernt von der Maschine sein, die die Kompilierung ausführt. Die elektrischen Signale, die die digitalen Daten führen, über die die Computersysteme den Code austauschen, sind beispielhafte Formen von Trägerwellen, die die Information transportieren.
  • Der Kompilierer (Compiler) wandelt einen Quellcode in einen weiteren Objektcode um, den er in einem von einer Maschine lesbaren Speicher, wie einem RAM 24 oder einer Platte 27, platziert. Ein Computer wird Befehlen dieses Objektcodes bei der Ausführung einer Anwendung 32 folgen, die typischer Weise einen Ausgang von einem Eingang erzeugt. Der Kompilierer 30 ist selbst eine Anwendung, und zwar eine, bei der der Eingang der Quellcode ist und der Ausgang ein Objektcode ist, aber der Computer, der die Anwendung 32 ausführt, ist nicht notwendiger Weise der gleiche wie derjenige, der den Kompilierer-Prozess ausführt.
  • Der Quellcode muss nicht unbedingt von einem menschlichen Programmierer direkt geschrieben werden. Integrierte Entwicklungsumgebungen automatisieren den Quellcode-Schreibprozess oft bis zu dem Ausmaß, dass für viele Anwendungen ein sehr geringer Teil des Source-Codes (Quellcodes) "manuell" erzeugt wird. Auch wird ersichtlich werden, dass der Ausdruck Kompilierer (Compiler) in der folgenden Diskussion breit verwendet wird, wobei er sich auf Umwandlungen auf einen Code auf einer niedrigen Ebene (low-level code), beispielsweise auf den Byte-Code, der der JavaTM virtuellen Maschine virtuellen Maschine eingegeben wird, erstreckt, den Programmierer fast niemals direkt schreiben (Sun, das Sun Logo, Sun Microsystems, und Java sind Marken oder registrierte Marken von Sun Microsystems, Inc., in den Vereinigten Staaten und anderen Ländern). Obwohl es so erscheint, als ob 2 einen Stapel-Prozess (Batch-Prozess) vorschlägt, bei dem der gesamte Objektcode einer Anwendung erzeugt wird, bevor irgendein Teil davon ausgeführt wird, kann der gleiche Prozessor ferner den Code sowohl kompilieren als auch ausführen, wobei in diesem Fall der Prozessor seine Kompilierer-Anwendung gleichzeitig mit – und in der Tat in einer Weise, die abhängig sein kann von – seiner Ausfuhrung des Ausgangsobjektcodes des Kompilierers ausführen kann.
  • Die verschiedenen Befehls- und Datenquellen, die in 1 gezeigt sind, bilden eine Geschwindigkeitshierarchie. Mikroprozessoren erzielen einen großen Grad ihrer Geschwindigkeit durch ein "Pipelining" der Befehlsausführung: Frühere Stufen von einigen Befehlen werden gleichzeitig mit späteren Stufen von früheren ausgeführt. Um die Pipeline bei der sich ergebenden Geschwindigkeit versorgt zu halten, liefern sehr schnelle On-Board-Register die Operanden und Versatzwerte (Offset-Werte), von denen angenommen wird, dass sie am häufigsten verwendet werden. Andere Daten und Befehle, bei denen es wahrscheinlich ist, dass sie verwendet werden, werden in dem On-Board-Cache gehalten, auf den ein Zugriff ebenfalls schnell ist. Ein Signalabstand zu dem Cache-Speicher 18 ist größer als für einen On-Board-Cache, so dass ein Zugriff auf ihn, obwohl er sehr schnell ist, nicht so schnell wie für einen On-Board-Cache ist.
  • In der Geschwindigkeitshierarchie befindet sich als nächstes das System RAM 22, welches gewöhnlicher Weise relativ groß ist und deshalb gewöhnlicher Weise aus einem relativ kostengünstigem dynamischen Speicher besteht, der eine Tendenz aufweist, wesentlich langsamer zu sein als der kostenaufwendige statische Speicher, der für Caches verwendet wird. Sogar innerhalb eines derartigen Speichers ist jedoch ein Zugriff auf Orte in der gleichen "Seite" im Vergleich mit einem Zugriff auf Orte auf unterschiedlichen Seiten relativ schnell. Beträchtlich langsamer als jede Vorgehensweise ist die Ermittlung von Daten von dem Platten-Controller, aber diese Quelle ist gewöhnlicher Weise nicht annähernd so langsam wie das Herunterladen von Daten durch eine Kommunikationsstrecke 28 sein kann.
  • Die Geschwindigkeitsdifferenzen zwischen diesen verschiedenen Quellen können sich über vier Größenordnungen erstrecken, so dass Entwerfer von Kompilierern beträchtliche Anstrengungen darauf richten, dass Kompilierer veranlasst werden, ihre Ausgangsbefehle so zu organisieren, dass sie eine Hochgeschwindigkeits-Ressowcenverwendung maximieren und die langsamsten Ressourcen so weit wie möglich vermeiden. Diese Anstrengung wird durch die gemeinsame Programmiertechnik einer Aufteilung eines Programms in einen Satz von Prozeduren, die an jeweilige spezifische Aufgaben (Tasks) gerichtet sind, kompliziert.
  • Die stärkste Komplexität ergibt sich aus Prozeduren, die andere Prozeduren auf einer niedrigeren Ebene aktivieren, um ihre Arbeiten auszuführen. Das heißt, verschiedene "Aufrufer" ("Caller") Prozeduren transferieren eine Steuerung an eine gemeinsame "Aufgerufener" ("Callee") Prozedur in einer derartigen Weise, dass dann, wenn der Aufgerufene aussteigt (exits), er eine Steuerung an immer die Prozedur zurückgibt, die ihn aufgerufen hat. Von dem Standpunkt des Programmierers ist diese Organisation vorteilhaft, weil es das Schreiben von Codes modularer und somit besser behandelbar macht. Sie erlaubt auch eine Code-Wiederverwendung: Eine gemeinsame Prozedur muss nicht an jede Stelle kopiert werden, an der sie verwendet werden soll. Dies bedeutet, dass irgendwelche Überarbeitungen nicht an zahlreichen Stellen wiederholt durchgeführt werden müssen. Aber eine derartige Organisation fügt einen Zusatz hinzu: Der Zustand des Aufrufers muss gespeichert werden, Cache-Verfehlungen und Seiten-Fehler können auftreten, und Prozessor-Pipelines müssen oft ausgeräumt werden. Mit anderen Worten, das System geht in der Geschwindigkeitshierarchie herunter.
  • Somit führen optimierende Kompilierer ("Compiler") oft ein "Inlining" von kurzen oder häufig verwendeten Prozeduren aus: Sie kopieren den Körper der Prozedur – ohne den Prozedur-Prolog und Epilog – an jede Stelle, an der der Source-Code ihn aufruft. Mit anderen Worten, der Compiler kann eine Wiederverwendung gegenüber einem Betriebsverhalten opfern. Aber der Programmierer zieht noch einen Nutzen aus der Codeschreibe-Modularität. Ein Inlining weist einen zusätzlichen wichtigen Nutzen auf Ein Kompilieren der inlined-Prozedur in einen spezifischen Aufruflcontext (Calling context) legt einem optimierenden Kompilierer mehr Information frei und erlaubt dadurch dem Optimierer, einen effizienteren Maschinencode zu erzeugen.
  • Gewisse modernere Programmiersprachen komplizieren den Inlining-Prozess. Um dies zu würdigen, sollte man sich die grundlegenden Funktionen/Merkmale von Objekt-orientierten Sprachen ins Gedächtnis zurückrufen. In derartigen Sprachen, wobei die Java-Programmiersprache und C++ Beispiele davon sind, wird der Code in Einheiten von "Objekten" geschrieben, die Exemplare (Instanzen) von "Klassen" sind. Die Definition einer Klasse listet die "Mitglieder" ("Members") von irgendeinem Objekt auf, die ein Exemplar (Instance) der Klasse ist. Ein Mitglied kann eine Variable sein. Oder sie kann eine Prozedur sein, die in diesem Kontext typischer Weise als ein "Verfahren" ("Method") bezeichnet wird.
  • 3 zeigt eine Vorgehensweise, in der man die Java-Programmiersprache verwenden kann, um Klassen zu definieren. Ihr erstes Codesegment definiert Objekte einer Klasse A, so dass sie unter anderem jeweilige Gleitpunkt-variablen Mitglieder h und w und ein Verfahrensmitglied ml einschließen, das (in dem Beispiel) mit den Mitgliedsvariablen des Objekts arbeitet, um einen Gleitpunktwert zurückzugeben, der deren Produkt darstellt. Jedes Exemplar der Klasse A wird seine jeweiligen Mitgliedsvariablen h und w aufweisen, und es wird auch ein Verfahren (Method) vorhanden sein, dessen Name ml ist und das auf diesem Exemplar aufgerufen werden kann. (Obwohl, wie nachstehend diskutiert werden wird, dieses Verfahren unter Umständen nicht den gleichen Betrieb für sämtliche Exemplare ausführen kann).
  • 4 zeigt die Verwendung der ml-en. Da das Verfahren ml ein Klassenmitglied ist, kann es lediglich dadurch aktiviert werden, dass es bei einem Exemplar dieser Klasse "aufgerufen" ("called on") wird. Somit deklariert die erste Anweisung (Statement) des linken Codefragments der 4 die Variable a eine Referenz auf ein Objekt einer Klasse A zu enthalten. Sie ordnet einem Objekt dieser Klasse auch einen Speicher zu und initialisiert die Variable a mit einer Referenz auf ein neu zugeordnetes Klasse A-Objekt. Die zwei Anweisungen danach platzieren Werte in zwei Mitgliedsvariablen dieses Objekts. Die letzte Anweisung übergibt die Objektreferenz in der Variablen a an eine Prozedur X.foo.
  • Diese Objektreferenz kann an diese Prozedur übergeben werden, weil, so wie dies das rechte Codefragment anzeigt, foo als einen Parameter des Typs A aufweisend definiert wurde und die Variable a zu dieser Klasse gehört. Wie dieser Code anzeigt, ruft die Definition von foo das Verfahren (Method) ml auf seinem Parameter o auf. Dies ist legal, weil ein Verfahren mit diesem Namen ein Mitglied der Klasse A ist. Wenn die Objektreferenz in der Variablen a an die Prozedur foo übergeben wird, wird das Verfahren ml mit Werten der Variablen h und w dieses Objekts ausgeführt.
  • Eine zentrale Funktion bzw. ein zentrales Merkmal von derartigen Objekt-orientierten Sprachen ist die "Vererbung" ("Inleritance"). Man kann in einer neuen Klassendefinition deklarieren, dass die neue Klasse ein "Kind" ("Child") einer anderen "Eltern" ("Parent") Klasse ist. Das extends-Schlüsselwort in der Definition der Klasse B in 3 deklariert die Kind-Beziehung dieser Klasse zu der Klasse A. Dies bedeutet, dass sämtliche Objekte der Klasse B so angesehen werden, dass sie auch Objekte der Eltern-Klasse sind, obwohl dies umgekehrt nicht notwendiger Weise zutrifft. Da sie auch zu der Klasse A gehören, werden sämtliche Objekte der Klasse B jeweilige Werte der Mitgliedsvariablen h und w einschließen und das Verfahren ml kann auf ihnen aufgerufen werden. Dies trifft sogar zu, obwohl die Definition der Klasse B nicht explizit diese Mitglieder auflistet: Die Klasse B erbt sie von der Klasse A. Somit wird der Kompilierer einem Objekt b der Klasse B erlauben, an foo übergeben zu werden, obwohl die Signatur von foo erfordert, dass sein Parameter eine Referenz auf ein Objekt der Klasse A sein soll.
  • Wie bis hierhin beschrieben, kompliziert der Vererbungsmechanismus den Inlining-Prozess nicht besonders. Der Kompilierer kopiert einfach in den Objektcode von foo den Objektcode, der sich aus der Definition des Verfahrens ml in der Klasse A ergibt, und dieser inlined-Code kann verwendet werden, obwohl an foo manchmal Referenzen auf Objekte der Klasse B übergeben werden.
  • Nun sei aber die Definition der Klasse C der 3 betrachtet. Die Definition führt eine "Außerkraftsetzung" (overriding) des geerbten Verfahrens ml aus. Weil sei ein Kind der Klasse A ist, umfasst die Klasse C notwendigerweise ein Mitgliedsverfahren ml, aber die Klasse C gibt diesem Verfahren eine andere Definition als ihre Definition für andere Objekte der Klasse A. Wenn an foo ein Objekt c der Klasse C übergeben wird – dies ist legal, da die Klasse C ein Kind der Klasse A ist – so erfordert der Aufruf des Verfahrens ml bei einem Objekt o einen anderen Code als den Code, der benötigt wird, wenn an foo ein Objekt übergeben wird, dessen Klasse A oder B ist. Verfahren (Methods), die außer Kraft gesetzt (overridden) werden dürfen, werden als "virtuell" ("virtual") bezeichnet, und virtuelle Verfahren, die außer Kraft gesetzt worden sind, werden als "polymorph" ("polymorphic") bezeichnet. Aufrufe an derartige Verfahren werden als "virtuelle Aufrufe" ("virtual calls") bezeichnet, die durch die Tatsache unterschieden werden, dass der Ort des aufgerufenen Verfahrens zur Laufzeit (runtime) berechnet werden muss. Demzufolge kann ein Inlining von einer Form eines polymorphen Verfahren unrichtige Ergebnisse hervorrufen.
  • Aggressive optimierende Kompilierer führen ein Inlining von polymorphen Verfahren in einigen Fällen trotzdem aus. Sie vermeiden unrichtige Ergebnisse durch "Überwachen" des inlined Codes mit einem Test, um zu bestimmen, ob die inlined-Form des Verfahrens konsistent mit der spezifischen Klasse des "Empfänger"-Objekts ist, auf dem das Verfahren aufgerufen wird. Wenn dem so ist, wird ein virtueller Aufruf vermieden.
  • Es würde dennoch besser sein, wenn ein aufgerufenes Verfahren direkt inlined werden könnte, d. h. ohne einen Schutzcode, der eine Ausführung an einen virtuellen Aufruf richten kann, weil ein derartiges Schützen sowohl Kosten mit sich bringt als auch den Kompilierer um bestimmte Optimierungsgelegenheiten bringt. Deshalb kann ein optimierender Kompilierer den Code suchen, um zu bestimmen, ob irgendeine reale Möglichkeit besteht, dass eine Form des Aufgerufenen – Verfahrens (Callee Method) außer der Kandidat für ein Inlining jemals an der Aufrufstelle aufgerufen werden würde, wo ein Inlining in Erwägung gezogen wird, und dann den Aufgerufenen (calle) zu inlinen, wenn dem nicht so ist. Unglücklicherweise kann der Kompilierer diese Bestimmung in einer Dynamik-Kompilierungsumgebung, die eine Klasse des Verfahrens des Aufgerufenen (Callee Method) außer Kraft setzt, geladen werden kann, nachdem der Aufrufer kompiliert ist und eine Ausführung des sich ergebenden Codes begonnen hat, nicht schlüssig durchführen.
  • Somit haben einige Entwickler vorgeschlagen, dass Inlining eventuell auszuführen, d. h. den Aufrufer unter der Annahme zu kompilieren, dass der Aufgerufene nicht außer Kraft gesetzt worden ist, und dann den Aufrufer später zu kompilieren, wenn eine später geladene Klasse ihn außer Kraft setzt. Dies ist einfach genug, wenn der Aufrufer gerade nicht ausgeführt wird, wenn die Rekompilierung auftritt: Die neue Kompilierung ersetzt die alte, und die nächste Aktivierung des Aufrufers erhält den korrigierten Code. Die Sache ist aber komplizierter, wenn der Aufrufer gegenwärtig gerade ausgeführt wird, wenn das Ereignis, das die Rekompilierung notwendig macht, auftritt. In diesem Fall müssen derartige Systeme in der Lage sein, einen Ausführungszustand entsprechend zu einer Kompilierung eines Verfahrens auf den "äquivalenten" Ausführungszustand für eine andere Kompilierung dieses Verfahrens zu ändern. Dieser Prozess ist als "Ersetzung auf dem Stapel" ("On-Stack Replacement") bezeichnet worden.
  • Die Self-Sprache (Selbst-Sprache) war unter Umständen das erste Programmiersystem, um eine On-Stack-Ersetzung zu implementieren. In dieser Sprache erzeugt der Kompilierer Strukturen in Assoziation mit verschiedenen "Deoptimierungspunkten" (deoptimization points") in dem kompilierten Code für ein Verfahren (Method). Diese Strukturen enthalten Information, die ermöglichen, dass ein "Quellzustand" ("source state") des Verfahrens, d. h. der Zustand der Variablen des Verfahrens, wie von der Interpretation des Quellcodes definiert, aus dem "Maschinenzustand" ("machine state") des kompilierten Codes an dem assoziierten Deoptimierungspunkt zurückgewonnen werden. Wenn eine weitere Kompilierung später zu einer Invalidierung einer Annahme, von der die Kompilierung abhängt, führt, beispielsweise, dass der Aufgerufene nicht außer Kraft gesetzt worden ist, muss diese Kompilierung an einem derartigen Deoptimierungspunkt auftreten. Das Self-System gewinnt dann den Quellzustand zurück, rekompiliert das Verfahren ohne die verletzte Annahme, berechnet den entsprechenden Maschinenzustand der neuen Kompilierung aus dem Quellzustand und ersetzt Registerwerte und Einträge in dem Stapelrahmen (stack frame) des Verfahrens, um sie konsistent mit dem neuen Maschinenzustand zu machen.
  • Es lässt sich leicht ersehen, dass eine derartige n-Stack-Ersetzungsmöglichkeit relativ komplex ist. Ferner können die Datenstrukturen, die benötigt werden, um dies zu unterstützen, alarmierend voluminös werden. Auch verhindert die Aufrechterhaltung von Deoptimierungspunkten, dass ein Codeplaner (Code-Scheduler) einen Code umordnet, den derartige Deoptimierungspunkte trennen.
  • Chambers C. et al.; "An Efficient Implementation of SELF, a dynamically-typed object-oriented Language Based on Prototypes", OOPSLA Conference Proceedings, Special Issue of Sigplan Notices, Vol. 24, Nr. 10, Oktober 1989, Seiten 49–70 beschreibt die Self-Sprache, eine dynamisch-geschriebene Objektorientierte Sprache und wie sie effizient implementiert werden kann. Sie verwendet ein Nachrichten-Lining (messaging lining) und inkrementale Rekompilierungs-Inlined-Stapel-Rahmen (incremental recompilation inlined stack frames), die bei der Debugging-Zeit rekonstruiert werden.
  • ZUSAMMENFASSUNG DER ERFINDUNG
  • Die vorliegende Erfindung erlaubt, dass eine signifikante Anzahl von Orten mit virtuellen Aufrufen direkt inlined werden, ohne dass irgendwelche Beschränkungen auf die Kompilierung des Aufrufers auferlegt werden, und sie hält die Aufgabe einer Erfassung und einer Reaktion auf Annahme-Invalidierungsänderungen relativ einfach. In Übereinstimmung mit der vorliegenden Erfindung inlined der Kompilierer virtuelle Aufrufe direkt nur an Stellen, an denen der Kompilierer zur Kompilierungszeit wissen kann, dass der Empfängerausdruck während irgendeiner Laufzeitausführung des aufrufenden Verfahrens notwendigerweise auf ein Objekt Bezug nehmen wird, dessen Klasse geladen wurde, als diese besondere Ausführung des Aufrufers begann. Wenn diese Bedingung erfüllt wird, dann muss eine Kompilierung, die einen Aufgerufenen außer Kraft setzt, während der Ausfuhrung des Aufrufenden nicht dazu führen, dass der Aufrufende für eine Rekompilierung unterbrochen wird, weil die Implementierung des Aufgerufenen-Verfahrens durch den Empfänger in diesem Fall nicht die außer Kraft setzende sein kann, und die Inlined-Implementierung deshalb die richtige sein muss. Dies beseitigt vollständig die Notwendigkeit, Einträge in dem Stapelrahmen (stack frame) des Aufrufenden zu ersetzen.
  • In einer Ausführungsform werden derartige Stellen leicht gefunden, indem Aufrufstellen identifiziert werden, an denen die Empfängeneferenz ein Aufrufer-Argument ist, an das der Aufrufende keine Zuweisung vornimmt. Wenn Parameterwerte nach dem Wert übergeben werden, dann ist die Empfängeneferenz notwendigerweise eine lokale Variable, an die nur der Aufrufer eine Zuweisung vornehmen kann, so dass das Objekt, auf das die Variable Bezug nimmt, vorher existierend sein muss, wenn der Aufrufer nicht selbst eine Zuweisung daran vornimmt.
  • In einem Aspekt der Erfindung stellt die vorliegende Erfindung ein Computersystem nach Anspruch 1 bereit. In einem anderen Aspekt stellt die vorliegende Erfindung ein Verfahren nach Anspruch 9 bereit.
  • KURZBESCHREIBUNG DER ZEICHNUNGEN
  • Die nachstehende Erfindungsbeschreibung bezieht sich auf die beiliegenden Zeichnungen. In den Zeichnungen zeigen:
  • 1, die voranstehend diskutiert wurde, ein Blockdiagramm eines typischen Computersystems des Typs, der konfiguriert werden kann, um ein Quellprogramm (Source-Programm) zu kompilieren;
  • 2, die voranstehend diskutiert wurde, ein Blockdiagramm des Übergangs von einem Quellcode (Source Code) zu der Ausführung der Anwendung;
  • 3, die voranstehend diskutiert wurde, eine Quellcode-Auflistung, die typische Klassendeklarationen aufführt;
  • 4, die voranstehend diskutiert wurde, eine Quellcode-Auflistung, die die Verwendung eines Objekts darstellt, das ein Exemplar einer in 3 deklarierten Klasse ist;
  • 5 ein Flussdiagramm des Entscheidungsprozesses, der von der illustrierten Ausführungsform der Erfindung verwendet wird, um zu bestimmen, ob ein virtueller Anruf direkt inlined werden soll;
  • 6 ein Quellcode-Fragment, welches verschiedene Aufrufstellen darstellt, die Kandidaten für ein Inlining sein können;
  • 7 ein Flussdiagramm, das eine Auferlegung von verschiedenen Versionen des Vorexistenzkriteriums der vorliegenden Erfindung darstellt;
  • 8 ein Codefragment, das die Klassendefinition einer Klasse darstellt, die ein unveränderliches Mitglied aufweist;
  • 9 ein Diagramm von verschiedenen Datenstrukturen, die die illustrierte Ausführungsform verwendet, um zu bestimmen, wann Aufrufprozeduren zu rekompilieren sind, die unter den Annahmen kompiliert worden sind, dass bestimmte von ihren Aufgerufenen nicht außer Kraft gesetzt worden sind;
  • 10 ein ausführlicheres Diagramm einer Abhängigkeitsstruktur, die 9 einschließt; und
  • 11 ein Diagramm ähnlich wie 9, wobei das Ergebnis einer Ladung einer Klasse dargestellt ist, die ein Direkt-Inlined-Verfahren eines Aufgerufenen außer Kraft setzt.
  • AUSFÜHRLICHE BESCHREIBUNG EINER ILLUSTRATIVEN AUSFÜHRUNGSFORM
  • In einer typischen Umgebung mit einer dynamischen Kompilierung, bei der die Lehren der vorliegenden Erfindung umgesetzt werden können, wird nicht die gesamte Kompilierung fertiggestellt, bevor eine Ausführung eines Teils des sich ergebenden Objektcodes beginnt. Zum Beispiel kann der Kompilierungsprozess "faul" ("lazy") in dem Sinne sein, dass er nur beispielsweise eine Hauptprozedur kompiliert, ohne zu Anfang irgendwelche der Prozeduren zu kompilieren, die die Hauptprozedur aufrufen kann. Anstelle der Aufrufe an diese Prozeduren kann er zum Beispiel Rumpfeinheiten (Stubs) bereitstellen, die bestimmen, ob der Quellcode der Prozedur des Aufgerufenen kompiliert oder interpretiert werden sollte. Somit wird eine Prozedur eines Aufgerufenen nicht kompiliert, außer wenn die Ausführung des Objektcodes einen derartigen Stub erreicht.
  • Nun sei die sich ergebende Kompilierung in einer derartigen Umgebung betrachtet. Die Kompilierung schreitet in der normalen Weise voran, wobei Quellcode-Anweisungen in Maschinencode-Anweisungen umgewandelt werden, bis ein Punkt erreicht wird, an dem der Quellcode einen Prozeduraufruf darstellt. Das gewöhnliche Ergebnis ist einfach ein Objektcode zum Implementieren des Prozeduraufrufs, d. h. zum Speichern des Kontext des Aufruferprozesses und zum Übergeben von irgendwelchen Argumenten und einer Steuerung an den Aufrufer. Aber Verfahren (Methods), die bestimmte Kriterien erfüllen, sind gute Kandidaten, um anstelle davon inlined zu sein, so dass der Kompilierer derartige Kandidaten in Übereinstimmung mit einem Entscheidungsprozess, wie beispielsweise derjenige, den das vereinfachte Flussdiagramm der 5 darstellt, identifiziert.
  • Der Entscheidungsblock 40 stellt ein grundlegendes Inlining-Kriterium, nämlich die Größe, dar. Wenn das Verfahren des Aufgerufenen lang ist, ist es nicht ein guter Inlining-Kandidat. In den meisten Fällen wird der Kompilierer auch von einer Betrachtung irgendein polymorphes Verfahren beseitigen, z. B. ein virtuelles Verfahren, das auf einer Variablen aufgerufen wird, deren statischer Typ einen Abkömmling aufweist, der dieses Verfahren außer Kraft setzt, so dass die bestimmte Form des Verfahrens, das ausgeführt werden wird, bis zur Laufzeit nicht bekannt ist. Obwohl eine derartige Beseitigung nicht eine absolute Anforderung für die breiteren Lehren der vorliegenden Erfindung ist, ist sie ein Merkmal der meisten Implementierungen, so dass 5 einen Block 44 einschließt, um ein derartiges Kriterium darzustellen.
  • Obwohl nicht wesentlich, sind die Kriterien der Blöcke 40 und 44 typisch, und die meisten Implementierungen werden zusätzlich andere Schwellenkriterien auferlegen, wie der Block 46 anzeigt. Der Block 48 zeigt an, dass der Kompilierer zusätzlich die Anforderung auferlegt, dass der Empfängerausdruck des Verfahrens etwas erfüllen muss, was als ein Vorexistenz-Kriterium bezeichnet wird. Wie ersichtlich werden wird, ist eine Auferlegung dieses Kriteriums praktischer in einer Umgebung mit einer dynamischen Kompilierung, um virtuelle Anrufe direkt zu inlinen.
  • Der Zweck dieses Kriteriums kann verstanden werden, indem eine Aufrufprozedur m 1 betrachtet wird, die eine Verfahrensaktivierung o.m2 ( ) an irgendeiner gegebenen Aufrufstelle enthält, an der die Variable o deklariert ist, um eine Referenz auf ein Objekt der Klasse 0 zu enthalten. Es wird angenommen, dass zu der Zeit der Kompilierung der Aufruferprozedur ml kein Abkömmling der Klasse 0, der ein Verfahren m2 der Klasse 0 außer Kraft setzt, geladen worden ist, und, dass die Stelle andere Schwellenkriterien genauso erfüllt. In einer Umgebung mit einer dynamischen Kompilierung kann dieses Kriterium jedoch unter Umständen später verletzt werden, da ein Laden und ein Kompilieren gleichzeitig mit der Ausführung des sich ergebenden Codes voranschreiten. Um derartige Änderungen zu erfassen und auf sie zu reagieren, müssten bei Abwesenheit der Lehren der vorliegenden Erfindung Schritte vorgenommen werden, die einer Attraktivität eines direkten Inlinings entgegenwirken könnten.
  • Die vorliegende Erfindung hält die Aufgabe einer Erfassung und Reaktion auf derartige Änderungen relativ einfach, erlaubt aber, dass eine signifikante Anzahl von Stellen mit virtuellen Anrufen direkt inlined werden. In Übereinstimmung mit der vorliegenden Erfindung führt der Kompilierer ein Inlining von virtuellen Aufrufen direkt nur an Stellen durch, von denen der Kompilierer zur Kompilierungszeit wissen kann, dass der Empfängerausdruck während irgendeiner Laufzeitausführung des Aufrufverfahrens nicht notwendiger Weise auf ein Objekt Bezug nehmen wird, dessen Klasse geladen wurde, als diese besondere Ausführung des Aufrufers begann. Wenn dieses Kriterium erfüllt ist, dann wird der Objektcode für das Aufrufverfahren ml keine speziellen Vorkehrungen benötigen, um sicherzustellen, dass die Annahmen, auf denen das Inlining des virtuellen Aufrufs o.m2 ( ) basiert war, gültig bleiben. Wie gegenwärtig erläutert werden wird, besteht die einzige Anforderung darin, die Annahmen zu überprüfen – und die Aufruferprozedur wenn erforderlich, zu rekompilieren – bevor das erste Objekt irgendeiner neu geladenen Klasse zugeordnet wird. Es wird nachstehend auch gezeigt werden, dass die sich ergebende Rekompilierung niemals irgendeine Ausführung des Aufrufercodes, in den der Aufgerufene unter Annahmen inlined wurde, deren Verletzung die Rekompilierung bedingt hat, unterbrechen muss.
  • Es sei zunächst darauf hingewiesen, dass jedes zugeordnete Objekt notwendigerweise eine Klasse aufweist, die geladen ist. Somit reicht ein Nachweis, dass ein Objekt beim Eintritt in ein Verfahren zugeordnet ist, aus, um zu zeigen, dass es das Kriterium erfüllt, das heißt, dass seine Klasse beim Eintritt in das Verfahren geladen wurde. Es ergibt sich, dass viele Stellen, die dieses "Zuordnungsfähigkeits" ("Allocatedness") Kriterium erfüllen, relativ einfach identifiziert werden können. 6 verwendet ein Codefragment in der Java-Programmiersprache, welches eine einfache Technik zur Durchführung darstellt, die hier als eine Analyse mit invariantem Argument (Invariant-Argument-Analyse) bezeichnet wird. Es sei das Empfängerobjekt betrachtet, auf das die Objektvariable o in dem Verfahrensaufruf o.m2 ( ) Bezug nimmt. Eine Inspektion des Aufruferverfahrens ml enthüllt, dass dessen Körper keine Zuweisung an eine Objektvariable o innerhalb des Aufruferverfahrens enthält. Nun bedeutet die Abwesenheit einer Anweisung an eine Variable innerhalb einer Prozedur nicht alleine, dass das Objekt, auf das die Variable Bezug nimmt, bereits zugeordnet worden sein muss, als die Prozedur begonnen wurde; ein unterschiedlicher Ausführungszweig (Ausführungs-Thread) oder eine andere Prozedur, die von der Aufrufenden-Prozedur aufgerufen wird, könnte einer nicht-lokalen Variablen eine Referenz auf ein neu zugeordnetes Objekt zuweisen. Aber die Variable o des Empfängerobjekts, die ihren Wert übergeben hat, als das Aufruferverfahren ml aufgerufen wurde, ist eine lokale Variable, so dass das Objekt, auf das es Bezug nimmt, notwendigerweise vor dem Eintritt der Aufrufenden-Prozedur zugeordnet sein muss, wenn das Aufruferverfahren nicht selbst ihm einen Wert zuweist. Dies bedeutet, dass eine Ausführung des Aufrufers niemals für eine Rekompilierung – und eine Ersetzung der Werte, die mit ihm auf dem Aufruf-Stapel (call stack) assoziiert sind – unterbrochen werden muss, sogar wenn ein außer Kraft setzendes Verfahren gleichzeitig mit der Ausführung des Aufrufers kompiliert wird und somit die Annahme invalidiert (für ungültig erklärt), auf die das Inlining gestützt wurde.
  • Somit besteht eine Aufrufstelle die Analyse mit invariantem Argument, wenn ihr Empfängerausdruck ein Aufruferargument ist, dessen Wert beim Eintritt in den Aufrufer übergeben wird und der Aufrufer danach ihm nicht einen neuen Wert zuweist. Da sämtliche Prozedurparameter nach dem Wert in der Java-Programmiersprache übergeben werden, werden Empfänger, die dieses Kriterium erfüllen, leicht erkannt. In einigen anderen Sprachen, bei denen Parameter nach der Referenz übergeben werden, muss Vorsicht walten gelassen werden, um Nach-Referenz-Parameter nicht als Invariante Argumente zu betrachten und als mögliche Zuweisungen Exemplare (Instances) zu erkennen, in denen der Aufrufer den Empfänger (Receiver) an einen Aufrufenden (Callee) nach der Referenz übergibt.
  • 7 zeigt den Schritt 48 der 5 mit näheren Einzellieiten und zeigt, dass auch andere alternative Vorexistenz-Kriterien vorhanden sein können. Der Block 50 stellt den eben erläuterten Test einer Identifizierung von Stellen dar, an denen die Empfängervariable ein invariantes Argument ist. Wie der Schritt 54 der 5 zeigt, führt dieser Test zu einem direkten Inlining, wenn der Aufrufer niemals einen Wert der Empfängervariablen zuweist. Sogar dann, wenn der Aufrufer eine derartige Zuweisung nicht durchführt, kann ein direktes Inlining noch geeignet sein, und einige Ausführungsformen der Erfindung können entsprechend einen Test wie denjenigen, den der Block 56 der 7 darstellt, einschließen. Die Stellen der 6, die die Aufrufe 02.m2 ( ) und o3.m2 ( ) enthalten, sind Beispiele von Stellen (Sites), die diesen Test bestehen.
  • Für den Fall von o2.m2 ( ) zeigt die vorangehende Anweisung "O o2 = o", dass der Aufrufer eine Zuweisung eines Werts an die Variable o2, die die Empfänger-Objekt-Referenz enthält, vornimmt, aber der dadurch zugewiesene Wert derjenige eines Invarianten Argument ist. Die Vorexistenz des Objekts, auf das sich eine lokale Variable bezieht, kann daraus abgeleitet werden, dass ihm nur der Wert einer anderen derartigen Variablen zugewiesen ist. Somit muss o2.m2 die gleiche Implementierung wie o.m2 sein. Es sei darauf hingewiesen, dass eine lokale Variable dieses Kriterium rekursiv erfüllen kann: Eine lokale Variable, der nur der Wert von o2 zugewiesen ist, würden den Test ebenfalls bestehen.
  • Für den Fall des Aufrufs o3.m2 ( ) macht die vorangehende Anweisung "O o3 = o.clone ( )" eine Zuweisung an die Variable o3, die die Empfängerreferenz enthält. Der Wert ist nicht der gleiche wie derjenige der Variablen o, aber er ist eine Referenz auf ein Objekt, welches notwendigerweise den gleichen dynamischen Typ wie das Invariante Argument o aufweist. Eine Implementierung o3.m2 muss deshalb die gleiche Implementierung o.m2 sein und somit die gleiche wie die Inlined-Implementierung. Deshalb erfüllt die beteiligte Anruf- bzw. Aufrufstelle wieder das Vorexistenz-Kriterium der vorliegenden Erfindung und der Aufgerufene an dieser Stelle kann inlined werden.
  • Die Stelle der 6, die den Aufruf o.f.m3 ( ) enthält, kann unter Umständen einen anderen alternativen Vorexistenz-Test erfüllen, der als der Test mit unveränderlichem Feld (immutable-field test) bezeichnet werden wird. Eine Aufrufstelle besteht diesen Test, wenn der Empfängerausdruck auf ein Mitglied eines vorher existierenden Objekts verweist, das in dem Sinn "unveränderlich" ist, dass es nur von dem Konstruktur-Verfahren (Constructor Method) von der Klasse dieses Objekts zugewiesen werden kann. Zum Beispiel sei angenommen, dass die Klasse 0 ihr Mitglied f in der Weise definiert, die 8 darstellt, nämlich als ein "privates" Mitglied, dem kein anderes Mitgliedsverfahren als der Klasse-Konstruktur einen Wert zuweist. Da das "private" ("private") Schlüsselwort der Java-Programmiersprache anzeigt, dass ein Zugriff auf ein Mitglied, dessen Deklaration so modifiziert ist, auf Mitglieder der gleichen Klasse beschränkt ist, wird dem Mitglied f ein Wert nur auf die Konstruktion des Objekts hin, von dem es ein Mitglied ist, nämlich dem Objekt, auf das die Variable o Bezug nimmt, zugewiesen. Der Wert, der dem Mitglied o. f. zugewiesen werden soll, wird an den Konstruktur des Objekts o als ein Argument übergeben. Somit muss das Mitgliedsobjekt, auf dass sich die Variable f bezieht, notwendigerweise vor der Aktivierung des Konstruktors zugeordnet worden sein. Wenn aber das Objekt, auf das die Variable o Bezug nimmt, vorher existiert und vor der Konstruktion dieses Objekts dasjenige, auf das o. f. Bezug nimmt, zugeordnet wurde, dann muss auch das Objekt, auf das o. f. Bezug nimmt, vorher existierend sein. Das gleiche würde zutreffen, wenn das Mitglied f anstelle von "privat" als "abschließend" ("final") deklariert worden wäre, da dieses Schlüsselwort die Randbedingung auferlegt, dass der so modifizierte Wert einer Variablen nicht geändert werden kann, nachdem er zu Anfang zugewiesen wird. In beiden Fällen erfüllt die Anrufstelle, an der der Empfängerausdruck o. f. ist, ein Vorexistenz-Kriterium.
  • In jedem der Inlining-Fälle, die eben erwähnt wurden, besteht keine Notwendigkeit, in dem Objektcode der Aufrufenden-Prozedur irgendwelche Vorkehrungen zum Überarbeiten des Inlined-Teils, wenn die Annahmen, auf denen das Inlining gestützt wurde, verletzt werden, einzubauen. Derartige Vorkehrungen können anstelle davon in zweckdienlicher Weise vollständig in den Kompilierungs-Betriebsvorgängen implementiert werden, die die Verletzung der Annahmen verursachen, wie nun unter Bezugnahme auf 9 erläutert werden wird.
  • Der Objektcode, der sich aus einer Kompilierung der Aufruferprozedur ml ergibt, wird in einen Block 70 mit kompiliertem Code gelegt, in dem ihm möglicherweise ein Header-Teil (Anfangsblock-Teil) 72 vorausgeht, der eine Housekeeping-Information (Aufräum-Information) enthält. In einer Umgebung mit einer dynamischen Kompilierung kann der kompilierte Code vorläufig sein: Seine fortgesetzte Gültigkeit kann davon abhängen, welcher Code danach geladen wird. Wenn die Prozedur das virtuelle Verfahren m2 in Übereinstimmung mit den voranstehend beschriebenen Kriterien direkt inlined hat, hängt die fortgesetzte Gültigkeit des Objektcodes im Block 70 insbesondere davon ab, ob die Anzahl der Implementierungen des Aufgerufenen-Verfahrens m2 die gleiche ist wie sie war, als die Aufrufer-Prozedur ml kompiliert wurde. In der dargestellten Ausfuhrungsform, die nur "monomorphe" Verfahren direkt inlined, hängt die Gültigkeit des Inlined-Codes von der Annahme ab, dass nur eine derartige Implementierung vorhanden ist.
  • Um einen Mechanismus zur Reaktion bereitzustellen, wenn diese Annahme verletzt wird, schafft der Kompilierungsbetrieb eine "Abhängigkeitsstruktur", wobei 10 ein typisches Format davon zeigt. Eine fortgesetzte Gültigkeit eines Objektcodeblocks kann von verschiedenen Typen von Annahmen abhängen, die eine Abhängigkeitsstruktur dokumentieren könnten, so dass das erste Feld der Struktur den Einzelimplementierungs-Typ der Abhängigkeit spezifiziert, was in diesem Fall bedeutet, dass die Gültigkeit der Prozedur ml von der Annahme abhängt, dass das Aufgerufenen-Verfahren m2 nicht außer Kraft gesetzt worden ist. Das nächste "Ziel"("target")-Feld der Struktur identifiziert, dass angenommen wird, dass der Aufgerufene nur einzeln implementiert ist, während ihr letztes "abhängiges" ("dependent") Feld die Aufrufprozedur identifiziert, deren Gültigkeit von dieser Annahme abhängt. In der dargestellten Ausführungsform nehmen diese Identifikationen die Form von Zeigern auf den "Verfahrensblock" 74 ( 9) in Assoziation mit der Aufgerufenen-Prozedur m2 und mit dem Behälter 70 mit kompiliertem Code im Zusammenhang mit der Aufgerufenen-Prozedur ml an. Der Kompilierer verwendet einen Verfahrensblock, um verschiedene Information zu speichern, die sämtlichen Implementierungen ihres assoziierten Verfahrens gemeinsam ist.
  • Als Beispiel zeigt 9 den Verfahrensblock 74 des Verfahrens m2, so dass er getrennt von dem Behälter mit kompiliertem Code des Aufgerufenen-Verfahrens sowie von einer Klassendatei 76, die verschiedene Information über die Klasse 0, den statischen Typ des Empfängerausdrucks des Verfahrens m2 an der Aufrufstelle von Interesse, enthält. Die Klassendatei enthält typischer Weise viele Arten von Klassen-bezogener Information, die die Zeichnung nicht darstellt, wie den Quellcode der Mitgliedsverfahren in der Form eines Java Virtual Machine Byte-Codes. Als weiteres Beispiel ist die Klassendatei so dargestellt, als ob sie beim Laden mit einem getrennten Verfahren und Virtualfunktionstabellen 78 und 80 versehen worden ist, die jeweils auf die Verfahrensblöcke und Behälter mit kompiliertem Code für die verschiedenen Mitgliedsverfahren der Klasse 0 zeigen.
  • Die verbleibenden Felder, die 10 zeigt, unterstützen die Implementierung der Abhängigkeitsstruktur der dargestellten Ausführungsform als ein Element von zwei doppelt verbundenen Listen. Wenn die Abhängigkeitsstruktur 84 geschaffen wird, um die Abhängigkeit des Aufrufers ml davon, dass der Aufgerufene m2 nur einzeln implementiert ist, zu dokumentieren, wird sie in einer verbundenen Liste 86 von Strukturen angeordnet, die andere Abhängigkeiten darstellen. Insbesondere dann, wenn irgendwelche Abhängigkeitsstrukturen geschaffen worden sind, um andere Annahmen zu dokumentieren, auf denen die Gültigkeit des Aufrufer-Objektcodes gestützt ist, spezifiziert ein Zeiger in dem Header des Behälters mit kompiliertem Code des Aufrufers m 1 den Ort der ersten Struktur in einer verbundenen Liste von derartigen Strukturen, wie der Pfeil 88 andeutet, und die neue Abhängigkeitsstruktur wird zu dem Kopf der Liste hinzugefügt, indem ihr "nächste abhängige Abhängigkeit"-Feld mit dem Ort der ersteren ersten Struktur gefüllt wird, ihr "frühere abhängige Abhängigkeit"-Feld mit dem Ort der neuen Struktur gefüllt wird, und ihr Listenkopfzeiger umgeleitet wird, wie der Pfeil 90 andeutet.
  • Nachdem die neue Struktur in einer Liste von Strukturen installiert worden ist, die Annahmen dokumentieren, auf denen die Gültigkeit des Aufrufer-Objektcodes gestützt ist, wird sie auch in einer Liste 94 von Strukturen installiert, die Abhängigkeiten von einem oder einem anderen der Merkmale des Aufgerufenen dokumentieren. Insbesondere findet sie in dem "Abhängige" ("dependents")-Feld des Verfahrensblocks des Aufgerufenen-Verfahrens m2 einen Zeiger auf die Struktur an dem Kopf dieser Liste, installiert die neue Struktur, indem geeignete Einträge in den Feldern "nächste Zielabhängigkeit" und "frühere Zielabhängigkeit" von diesen Strukturen gemacht werden und der Listenkopfzeiger umgeleitet bzw. umgerichtet wird.
  • Wenn eine danach geladene Klasse A ein Abkömmling der Klasse 0 ist, in der das Direkt-Inlined-Aufgerufenen-Verfahren m2 definiert ist, wird dieser Abkömmling per Definition irgendwelche nichtprivate Verfahren der Klasse 0 erben, so dass seine Verfahrenstabelle irgendeinen Eintrag empfangen wird, der auf den Verfahrensblock 74 mit gemeinsamem Merkmal dieses Verfahrens verweist, und dieser Block wird aktualisiert werden. Wenn die Klasse A das Verfahren m2 jedoch nicht außer Kraft setzt, wird es keine Änderung in dem "Implementierungs-Feld" des Verfahrens, das anzeigt, wie viele verschiedene m2-Implementierungen kompiliert worden sind, geben. Vorausgesetzt, dass dieses Feld anzeigt, dass das Verfahren m2 nur eine Implementierung aufweist, kann das Objektcode-Programm die Nutzen von dem direkten Inlining dieses Verfahrens fortgesetzt nutzen.
  • Nun sei betrachtet, was passiert, wenn die Verfahren (Methods), die gerade kompiliert werden, anstelle davon diejenigen einer Abkömmlings-Klasse B sind, die ein m2 außer Kraft setzt. Das Ergebnis ist eine andere Implementierung von diesem Verfahren, wie der Behälter 96 mit kompiliertem Code der 11 anzeigt. Somit wird das Implementierungsfeld des Verfahrensblocks 74 des Verfahrens m2 aktualisiert, um anzuzeigen, dass nun zwei Abhängigkeiten vorhanden sind, und die Abhängigkeitsliste, auf die das "Abhängigkeits"-Feld des Verfahrensblocks des Verfahrens m2 verweist, wird nach Einzelimplementierungs-Abhängigkeiten durchsucht.
  • Diese Suche identifiziert die Abhängigkeitsstruktur 84, die anzeigt, dass die Kompilierung der Prozedur ml darauf gestützt war, dass das Verfahren m2 einzeln implementiert ist. Die Prozedur ml wird entsprechend rekompiliert, ohne das direkte Inlining, wie der Block der 11 mit dem Einbau eines virtuellen Aufrufs in einem neuen Behälter für den kompilierten Code für das Verfahren m2 anzeigt. Sämtliche Bezugnahmen auf das Verfahren ml, wie die zugehörigen Einträge in der virtuellen Tabelle seiner Klasse und seiner Vorfahrens-Klasse, werden so aktualisiert, dass irgendein Code, der die Prozedur ml aufruft, an den neuen Behälter 96 mit kompiliertem Code anstelle an den Behälter 70 für den vorangehenden Code, dessen Code nicht mehr gültig ist, gerichtet werden wird. Da die Gültigkeit des neuen Codes nicht von der Annahme abhängt, dass O.m2 außer Kraft gesetzt worden ist, wird die Abhängigkeitsstruktur 84 von beiden Listen entfernt. Die Kompilierung der Klasse B kann nun abgeschlossen werden und irgendeine Prozedur, die darauf wartete, diese Klasse als Exemplar zu etablieren, kann dies tun.
  • Um die Einfachheit zu würdigen, die diese Erfindung anbietet, sei die Situation betrachtet, bei der ein Ausführungs-Thread mitten bei der Ausführung der Prozedur ml des Aufgerufenen ist, wenn die Klasse B kompiliert wird. In einem derartigen Fall ist eine zweite Implementierung des Verfahrens m2 während der Ausführung einer Prozedur, die unter der Annahme kompiliert wurde, dass das Verfahren m2 nur eine Implementierung aufweist, in Existenz gekommen. Wenn ein direktes Inlining an Stellen ausgeführt worden wäre, die nicht die Kriterien der vorliegenden Erfindung erfüllt haben, dann hätte die Prozedur ml unter Umständen das Inlining mit einem Code zum Überprüfen der Anzahl von m2-Implementierungen schützen müssen, und Einträge in dem Stapel-Rahmen (stack frame) des Verfahrens m2 müssten ersetzt werden. Aber keine derartige On-Stack-Ersetzung (Ersetzung auf dem Stapel) ist notwendig, wenn die Kriterien der vorliegenden Erfindung beachtet werden, weil kein Exemplar der Klasse B vor einem Eintritt in die Prozedur ml, wie durch das direkte Inlining kompiliert, zugeordnet gewesen sein kann, und das Verfahren m2 an der Inlining-Stelle auf einem Objekt, das noch nicht zugeordnet worden ist, als diese Ausführung der Prozedur ml begann, nicht aufgerufen werden kann.
  • Somit vereinfacht die vorliegende Erfindung ein Inlining in dynamischen Kompilierungs-Umgebungen und bildet somit einen signifikanten Fortschritt in dem technischen Gebiet.
  • Ausführungsformen der Erfindung sind auf einer programmierbaren Verarbeitungsvorrichtung wie einem Computer oder einem Prozessor implementiert worden. Verfahren (Methods) in Übereinstimmung mit den Ausführungsformen der Erfindung können als ein von einem Computer lesbarer Code, der auf einem Trägermedium getragen wird, das ein Signal oder ein Speichermedium sein kann, verkörpert werden.

Claims (16)

  1. Computersystem, umfassend: eine Einrichtung zum Lesen von elektrischen Signalen, die eine Quellcode-Aufrufprozedur darstellen, die wenigstens eine Aufrufstelle einschließt, an der die Aufrufprozedur ein virtuelles Verfahren auf einem Objekt aufruft, auf das von einem Empfängerausdruck verwiesen wird, der auf ein Objekt verweist; gekennzeichnet durch: eine Einrichtung zum Kompilieren der Quellcode-Aufrufprozedur in eine Objektcode-Aufrufprozedur durch: Bestimmen, für jede Aufrufstelle, die Schwellenkriterien für ein direktes Inlinen erfüllt, ob diese Anrufstelle irgendeines von wenigstens einem vorher existierenden Kriterium erfüllt, von dem während der Kompilierung der Aufrufprozedur gefolgert werden kann, dass die Klasse des Objekts, auf das der Empfänger während irgendeiner Ausführung der Aufrufprozedur verweist, zu der Zeit, zu der die gegebene Ausführung beginnt, geladen worden ist; und für jede Aufrufstelle, die dadurch bestimmt wird, um ein vorher existierendes Kriterium zu erfüllen, Platzieren von direkt inlined Code in die Objektcode-Aufrufprozedur für jede gegenwärtig geladene Form des virtuellen Verfahrens, das von der Quellcode-Aufrufprozedur dort aufgerufen wird; und eine Einrichtung zum Speichern der Objektcode-Aufrufprozedur in einem Speichermedium, das von einer Maschine lesbar ist.
  2. Computersystem nach Anspruch 1, ferner umfassend: eine Einrichtung zum Aufzeichnen, gegen jedes virtuelle Verfahren, welches in der Objektcode-Aufrufprozedur als Folge davon, dass dessen Aufrufstelle wenigstens ein besagtes vorher existierendes Kriterium erfüllt, inlined ist, der Abhängigkeit der Objektcode-Aufrufprozedur von der gegenwärtigen Anzahl von Implementierungen von diesem virtuellen Verfahren; eine Einrichtung, um danach elektrische Signale zu lesen, die eine neue Quellcodeform eines virtuellen Verfahrens darstellen, nachdem die Objektcode-Aufrufprozedur in dem Speichermedium gespeichert worden ist, das von einer Maschine lesbar ist; eine Einrichtung zum Kompilieren der neuen Quellcodeform in eine neue Objektcodeform; eine Einrichtung zum Bestimmen, ob die neue Form ein virtuelles Verfahren außer Kraft setzt, gegen das die Abhängigkeit der Aufrufprozedur von einer gegebenen Anzahl von Implementierungen aufgezeichnet worden ist; und eine Einrichtung, wenn die neue Form ein derartiges virtuelles Verfahren außer Kraft setzt, zum: Rekompilieren der Quellcode-Aufrufprozedur in eine Ersetzungs-Objektcode-Aufrufprozedur; und Speichern der Ersetzungs-Objektcode-Aufrufprozedur in einem Speichermedium, das von einer Maschine lesbar ist, bevor erlaubt wird, dass irgendein kompilierter Objektcode ausgeführt wird, nachdem die neue Quellcodeform kompiliert worden ist.
  3. Computersystem nach Anspruch 1 oder 2, wobei eines der Schwellenkriterien zum direkten Inlinen an einer Anrufstelle ist, dass nur eine Form des virtuellen Vefahrens, das an der Aufrufstelle aufgerufen wird, geladen worden ist.
  4. Computersystem nach irgendeinem vorangehenden Anspruch, wobei ein besagtes vorher existierendes Kriterium ist, dass der Empfängerausdruck eine Aufrufprozedur-Lokalvariable ist, an die die Aufrufprozedur einen Wert nicht zuweist.
  5. Computersystem nach irgendeinem vorangehenden Anspruch, wobei ein vorher existierendes Kriterium darin besteht, dass der Empfängerausdruck eine invariante lokale Variable ist, wobei eine invariante lokale Variable als eine lokale Variable definiert ist, an die die Aufrufprozedur einen anderen Wert als denjenigen einer anderen Invarianten lokalen Variablen nicht zuweist.
  6. Computersystem nach irgendeinem vorangehenden Anspruch, wobei ein besagtes vorher existierendes Kriterium für eine Aufrufstelle darin besteht, dass der Empfängerausdruck auf ein unveränderbares Element eines Objekts verweist, welches ein Kriterium erfüllt, aus dem während der Kompilierung der Aufrufprozedur gefolgert werden kann, dass das Objekt, auf das ein Empfänger während irgendeiner gegebenen Ausführung der Aufrufprozedur weist, durch die Zeit, zu der die gegebene Ausführung beginnt, konstruiert worden sein wird.
  7. Computersystem nach irgendeinem vorangehenden Anspruch, wobei ein besagtes vorher existierendes Kriterium für eine Aufrufstelle darin besteht, dass der Empfängerausdruck auf ein unveränderbares Element entweder eines anderen unveränderbaren Elements oder eines Objekts, auf das durch eine invariante lokale Variable verwiesen wird, verweist, wobei ein unveränderbares Element eines ist, das nur in einem Konstruierer zugewiesen werden kann, und eine invariante lokale Variable als eine lokale Variable definiert wird, an die die Aufrufprozedur einen anderen Wert als denjenigen einer anderen Invarianten lokalen Variablen nicht zuweist.
  8. Computersystem nach irgendeinem vorangehenden Anspruch, wobei das System durch Befehle, die von einer Maschine lesbar sind, konfiguriert ist, um die Einrichtungen zu implementieren.
  9. Verfahren zum Erzeugen eines Objektcodes, umfassend die folgenden Schritte, Lesen von elektrischen Signalen, die eine Quellcode-Aufrufprozedur darstellen, die wenigstens eine Aufrufstelle einschließt, an der die Aufrufprozedur ein virtuelles Verfahren auf einem Objekt aufruft, auf das durch einen Empfängerausdruck verwiesen wird, der auf ein Objekt verweist; gekennzeichnet durch die folgenden Schritte: Kompilieren der Quellcode-Aufrufprozedur in eine Objektcode-Aufrufprozedur durch die folgenden Schritte: Bestimmen, für jede Aufrufstelle, die Schwellenkriterien für ein direktes Inlinen erfüllt, ob diese Aufrufstelle irgendeines von wenigstens einem vorher existierenden Kriterium erfüllt, von dem während der Kompilierung der Aufrufprozedur geschlossen werden kann, dass die Klasse des Objekts, auf das der Empfänger während irgendeiner gegebenen Ausführung der Aufrufprozedur verweist, zu der Zeit, zu der die gegebene Ausführung beginnt, geladen worden sein wird; und für jede Aufrufstelle, die dadurch bestimmt wird, um ein vorher existierendes Kriterium zu erfüllen, Platzieren eines direkt inlined Codes für jede gegenwärtig geladene Form des virtuellen Verfahrens, das von der Quellcode-Aufrufprozedur dort aufgerufen wird, in die Objektcode-Aufrufprozedur dort; und Speichern der Objektcode-Aufrufprozedur in einem Speichermedium, das von einer Maschine lesbar ist.
  10. Verfahren nach Anspruch 9, ferner umfassend: Aufzeichnen, gegenüber jedem virtuellen Verfahren, das in der Objektcode-Aufrufprozedur als Folge davon, dass dessen Aufrufstelle wenigstens ein besagtes vorher existierendes Kriterium erfüllt, inlined ist, der Abhängigkeit der Objektcode-Aufrufprozedur von der gegenwärtigen Anzahl von Implementierungen dieses virtuellen Verfahrens; danach Lesen von elektrischen Signalen, die eine neue Quellcodeform eines virtuellen Verfahrens darstellen, nachdem die Objektcode-Aufrufprozedur in dem Speichermedium, das von einer Maschine lesbar ist, gespeichert worden ist; Kompilieren der neuen Quellcodeform in eine neue Objektcodeform; Bestimmen, ob die neue Form ein virtuelles Verfahren außer Kraft setzt, gegen das die Abhängigkeit der Aufrufprozedur von einer gegebenen Anzahl von Implementierungen aufgezeichnet worden ist; und wenn die neue Form ein derartiges virtuelles Verfahren außer Kraft setzt: Rekompilieren der Quellcode-Aufrufprozedur in eine Ersetzungs-Objektcode-Aufrufprozedur; und Speichern der Ersetzungs-Objektcode-Aufrufprozedur in einem Speichermedium, das von einer Maschine lesbar ist, bevor erlaubt wird, dass irgendein kompilierter Objektcode ausgeführt wird, nachdem die neue Quellcodeform kompiliert worden ist.
  11. Verfahren nach Anspruch 9 oder 10, wobei ein besagtes Schwellenkriterium für ein direktes Inlinen an einer Aufrufstelle darin besteht, dass nur eine Form des virtuellen Verfahrens, das an der Aufrufstelle aufgerufen wird, geladen worden ist.
  12. Verfahren nach irgendeinem der Ansprüche 9 bis 11, wobei das vorher existierende Kriterium darin besteht, dass der Empfängerausdruck eine Aufrufprozedur-Lokalvariable ist, an die die Aufrufprozedur einen Wert nicht zuweist.
  13. Verfahren nach irgendeinem der Ansprüche 9 bis 12, wobei ein besagtes vorher existierendes Kriterium darin besteht, dass der Empfängerausdruck eine Invariante lokale Variable ist, wobei eine Invariante lokale Variable als eine lokale Variable definiert wird, an die die Aufrufprozedur einen anderen Wert als denjenigen einer anderen Invarianten lokalen Variablen nicht zuweist.
  14. Verfahren nach irgendeinem der Ansprüche 9 bis 13, wobei ein besagtes vorher existierendes Kriterium für eine Aufrufstelle darin besteht, dass der Empfängerausdruck auf ein unveränderbares Element eines Objekts verweist, das ein Kriterium erfüllt, aus dem während der Kompilierung der Aufrufprozedur gefolgert werden kann, dass das Objekt, auf das der Empfänger verweist, während irgendeiner gegebenen Ausführung der Aufrufprozedur zu der Zeit, zu der die gegebene Ausführung beginnt, konstruiert worden sein wird.
  15. Verfahren nach irgendeinem der Ansprüche 9 bis 14, wobei ein besagtes vorher existierendes Kriterium für eine Aufrufstelle darin besteht, dass der Empfängerausdruck auf ein unveränderbares Element entweder eines anderen unveränderbaren Elements oder eines Objekts verweist, auf das von einer Invarianten lokalen Variablen verwiesen wird, wobei ein unveränderbares Element eines ist, das nur in einem Konstruierer zugewiesen werden kann, und eine Invariante lokale Variable als eine lokale Variable definiert wird, an die die Aufrufprozedur einen anderen Wert als denjenigen einer anderen Invarianten lokalen Variablen nicht zuweist.
  16. Trägermedium, das einen Code trägt, der von dem Computer lesbar ist, zum Steuern eines Computers, um das Verfahren auszuführen, das von irgendeinem der Ansprüche 9 bis 15 beansprucht wird.
DE69911468T 1998-10-09 1999-10-07 Verfahren zum direkten inlinen von virtuellen anrufen ohne on-stack-vertretung Expired - Fee Related DE69911468T2 (de)

Applications Claiming Priority (3)

Application Number Priority Date Filing Date Title
US169341 1998-10-09
US09/169,341 US6223340B1 (en) 1998-10-09 1998-10-09 Method for directly inlining virtual calls without on-stack replacement
PCT/US1999/023349 WO2000022509A2 (en) 1998-10-09 1999-10-07 Method for directly inlining virtual calls without on-stack replacement

Publications (2)

Publication Number Publication Date
DE69911468D1 DE69911468D1 (de) 2003-10-23
DE69911468T2 true DE69911468T2 (de) 2004-06-24

Family

ID=22615266

Family Applications (1)

Application Number Title Priority Date Filing Date
DE69911468T Expired - Fee Related DE69911468T2 (de) 1998-10-09 1999-10-07 Verfahren zum direkten inlinen von virtuellen anrufen ohne on-stack-vertretung

Country Status (6)

Country Link
US (1) US6223340B1 (de)
EP (1) EP1145111B1 (de)
JP (1) JP2002527811A (de)
AT (1) ATE250239T1 (de)
DE (1) DE69911468T2 (de)
WO (1) WO2000022509A2 (de)

Families Citing this family (31)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5933635A (en) * 1997-10-06 1999-08-03 Sun Microsystems, Inc. Method and apparatus for dynamically deoptimizing compiled activations
JP3762867B2 (ja) * 1999-01-29 2006-04-05 富士通株式会社 コンパイラ装置、コンパイル方法、およびそのためのプログラムを格納した記憶媒体
US6487714B1 (en) * 1999-05-24 2002-11-26 International Business Machines Corporation Mechanism for dynamic selection of an object's method
US6507946B2 (en) * 1999-06-11 2003-01-14 International Business Machines Corporation Process and system for Java virtual method invocation
US6526572B1 (en) * 2000-02-09 2003-02-25 Hewlett-Packard Company Mechanism for software register renaming and load speculation in an optimizer
US7089403B2 (en) * 2002-06-26 2006-08-08 International Business Machines Corporation System and method for using hardware performance monitors to evaluate and modify the behavior of an application during execution of the application
US7484095B2 (en) * 2003-01-16 2009-01-27 Sun Microsystems, Inc. System for communicating program data between a first device and a second device
US20040143739A1 (en) * 2003-01-16 2004-07-22 Sun Mircosystems, Inc., A Delaware Corporation Run time code integrity checks
US7281244B2 (en) * 2003-01-16 2007-10-09 Sun Microsystems, Inc. Using a digital fingerprint to commit loaded data in a device
US7165246B2 (en) * 2003-01-16 2007-01-16 Sun Microsystems, Inc. Optimized representation of data type information in program verification
US8121955B2 (en) * 2003-01-16 2012-02-21 Oracle America, Inc. Signing program data payload sequence in program loading
US7272830B2 (en) * 2003-01-16 2007-09-18 Sun Microsystems, Inc. Ordering program data for loading on a device
US7222331B2 (en) * 2003-01-16 2007-05-22 Sun Microsystems, Inc. Linking of virtual methods
US7386686B2 (en) * 2003-03-28 2008-06-10 Intel Corporation Inlining with stack trace cache-based dynamic profiling
US7340732B2 (en) * 2003-11-26 2008-03-04 Sun Microsystems, Inc. Updating profile frequency for procedure inlining
CA2453776A1 (en) * 2003-12-19 2005-06-19 Ibm Canada Limited-Ibm Canada Limitee Compiler optimization
US7526760B1 (en) * 2004-03-17 2009-04-28 Sun Microsystems, Inc. Methods for implementing virtual method invocation with shared code
US20070250825A1 (en) * 2006-04-21 2007-10-25 Hicks Daniel R Compiling Alternative Source Code Based on a Metafunction
US7913236B2 (en) * 2006-09-29 2011-03-22 Intel Corporation Method and apparatus for performing dynamic optimization for software transactional memory
US8291393B2 (en) * 2007-08-20 2012-10-16 International Business Machines Corporation Just-in-time compiler support for interruptible code
US8370821B2 (en) * 2007-08-21 2013-02-05 International Business Machines Corporation Method for enabling profile-based call site tailor-ing using profile gathering of cloned functions
US8276131B2 (en) * 2007-08-30 2012-09-25 International Business Machines Corporation Method and system for dynamic loop transfer by populating split variables
US20090182689A1 (en) * 2008-01-15 2009-07-16 Microsoft Corporation Rule-based dynamic operation evaluation
US8281296B2 (en) * 2008-08-12 2012-10-02 Oracle America, Inc. Cross-ISA inlining in a system virtual machine
US8621447B1 (en) * 2009-08-25 2013-12-31 Adobe Systems Incorporated Systems and methods for dynamic struct variable creation including inline declaration with dynamic keys
US20130167144A1 (en) * 2009-09-04 2013-06-27 Bernd Mathiske Virtual Machine Persisted Within Itself
US8561045B2 (en) * 2010-07-30 2013-10-15 Apple Inc. Constructing runtime state for inlined code
US9146759B2 (en) 2010-07-30 2015-09-29 Apple Inc. Assumption-based compilation
US9195486B2 (en) 2010-07-30 2015-11-24 Apple Inc. Observation and analysis based code optimization
JP5583514B2 (ja) * 2010-08-11 2014-09-03 インターナショナル・ビジネス・マシーンズ・コーポレーション バイナリコードを最適化するコンパイル方法、及びそのコンパイラシステム、並びにコンピュータ・プログラム
US10229031B2 (en) 2011-07-15 2019-03-12 Microsoft Technology Licensing, Llc. Debugging inline functions in optimized code

Family Cites Families (8)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US5339419A (en) * 1990-06-25 1994-08-16 Hewlett-Packard Company ANDF compiler using the HPcode-plus compiler intermediate language
US5481708A (en) 1992-06-05 1996-01-02 Borland International, Inc. System and methods for optimizing object-oriented compilations
JP3178151B2 (ja) 1993-03-19 2001-06-18 富士ゼロックス株式会社 オブジェクト指向言語のメッセージコンパイル装置
US5845331A (en) 1994-09-28 1998-12-01 Massachusetts Institute Of Technology Memory system including guarded pointers
US5835771A (en) * 1995-06-07 1998-11-10 Rogue Wave Software, Inc. Method and apparatus for generating inline code using template metaprograms
US5815719A (en) 1996-05-07 1998-09-29 Sun Microsystems, Inc. Method and apparatus for easy insertion of assembler code for optimization
DE69911104T2 (de) * 1998-03-24 2004-07-08 Sun Microsystems, Inc., Palo Alto Statische Bindung von dynamisch abgesendeten Anrufen in Anwesenheit von dynamischer Verknüpfung und Ladung
US6161217A (en) * 1998-09-14 2000-12-12 Sun Microsystems, Inc. Accurate method for inlining virtual calls

Also Published As

Publication number Publication date
WO2000022509A2 (en) 2000-04-20
WO2000022509A3 (en) 2000-07-13
EP1145111A2 (de) 2001-10-17
US6223340B1 (en) 2001-04-24
EP1145111B1 (de) 2003-09-17
ATE250239T1 (de) 2003-10-15
JP2002527811A (ja) 2002-08-27
DE69911468D1 (de) 2003-10-23

Similar Documents

Publication Publication Date Title
DE69911468T2 (de) Verfahren zum direkten inlinen von virtuellen anrufen ohne on-stack-vertretung
DE69826700T2 (de) Kompilerorientiertes gerät zur parallelkompilation, simulation und ausführung von rechnerprogrammen und hardwaremodellen
DE19945992B4 (de) Dynamisch optimierender Objektcode-Übersetzer zur Architekturemulation und dynamisches optimierendes Objektcode-Übersetzungsverfahren
DE69723286T2 (de) Echtzeitprogramm-sprachbeschleuniger
DE69938218T2 (de) Vorrichtung und Verfahren zum Laden eines Java Anwendungsprogramms
DE102005045852A1 (de) Verfahren und System zum Schutz von Quellcode
EP1723513B1 (de) Verfahren zur konfiguration eines computerprogramms
DE112013001711T5 (de) Optimieren von Unterroutine-Aufrufen auf der Grundlage der Architekturebene einer aufgerufenen Unterroutine
EP1114366B1 (de) Genaues verfahren zum inlinen von virtuellen anrufen
EP1738257B1 (de) Verfahren zum vermeiden von dateninkonsistenz zwischen zugriffen verschiedener funktionen einer anwendung auf eine globale variable in einer datenverarbeitungsanlage
DE60102694T2 (de) Modulares computersystem und -verfahren
Johnson et al. Stores and partial continuations as first-class objects in a language and its environment
DE69727177T2 (de) Emulation von asynchronen Signalen mit Verzweigungsmechanismus
DE102004057490B4 (de) Vorrichtung und Verfahren zum Verarbeiten eines Programmcodes
DE69911104T2 (de) Statische Bindung von dynamisch abgesendeten Anrufen in Anwesenheit von dynamischer Verknüpfung und Ladung
WO1998001805A1 (de) Verfahren zur migration von programmen mit portierbaren und nicht-portierbaren programmteilen
DE102018127317B3 (de) Verfahren und vorrichtungen zur computerimplementierten erzeugung eines ausführbaren programmcodes und zur ausführung eines ausführbaren programmcodes
DE69731574T2 (de) Kompiliergerät und -verfahren
WO1999012094A1 (de) Verfahren zum umsetzen eines objektcodes in einen programmcode
DE112004002368T5 (de) Prozessor und Verfahren zur Unterstützung eines kompilierergerichteten Managements von Multi-Threading
DE112010003774T5 (de) Kompatibilität auf objektebene und klassenskalierung unter verwendung semantischer werte
DE102020111051A1 (de) Anordnung, softwareprogramm und computerimplementiertes verfahren zum ausführen eines nachladbaren programms auf einem eingebetteten system eines fahrzeugs
DE60030189T2 (de) Befehlsübersetzungsverfahren
DE10300541A1 (de) Erzeugen einer ausführbaren Datei
McKeag Programming languages for operating systems.

Legal Events

Date Code Title Description
8339 Ceased/non-payment of the annual fee