-
HINTERGRUND
DER ERFINDUNG
-
Die vorliegende Erfindung betrifft
eine Laufzeitkompilation von Software. Genauer gesagt betrifft die
Erfindung Techniken zum Durchführen
eines statischen Bindens von dynamisch abgesetzten Aufrufen beim
Vorhandensein eines dynamischen Verbindens und Ladens.
-
Das Dokument US-A-5613120 (Silicon
Graphics) zeigt ein allgemeines System und Verfahren nach dem Stand
der Technik zum Kompilieren und Binden einer Quellendatei.
-
Die grundsätzliche Idee hinter objektorientierten
Sprachen ist die Kombination von sowohl Daten als auch den Verfahren
(oder Fraktionen), die an diesen Daten arbeiten, in eine einzige
Einheit, die Objekt genannt wird. Objektfunktionen liefern typischerweise
die einzige Art zum Zugreifen auf Daten, die durch das Objekt eingekapselt
sind. Auf die Daten wird durch Senden einer Nachricht zum Objekt
zugegriffen, was das Objekt anweist, das durch die Nachricht spezifizierte
Verfahren aufzurufen.
-
Ein effizientes Absetzen einer Nachricht
ist von äußerster
Wichtigkeit bei objektorientierten Sprachen. Dies ist deshalb so,
weil ein Absetzen von einer Nachricht eine sehr häufige Operation
bei objektorientierten Programmen ist und zur Laufzeit durchgeführt wird;
daher sollte es so schnell wie möglich
erfolgen. Ein Absetzen einer Nachricht ist jedoch weit davon entfernt,
eine triviale Operation zu sein. Ungleich von verfahrensmäßigen Programmiersprachen
(z. B. der Programmiersprache C), die eine Funktionsadresse vor
einer Laufzeit bestimmen können,
müssen
objektorientierte Sprachen das Verfahren, das eine Nachricht handhabt,
die zu einem Empfängerobjekt
abgesetzt worden ist, zur Laufzeit dynamisch bestimmen, und dies
kann eine extensive Suche enthalten.
-
Zum besseren Verstehen der Komplexitäten eines
Absetzens einer Nachricht wird ein Beispiel einer Klassenhierarchie
beschrieben. 1 zeigt
eine Klassenhierarchie mit Verfahren für jede Klasse. Eine Klassenhierarchie
1 enthält
an ihrer Wurzel eine Elternklasse A3, die zwei virtuelle Funktionen
foo() und bar() definiert. Virtuelle Funktionen sind Funktionen, die
in einer Elternklasse definiert und in zugehörigen Kinderklassen neu definiert
sein können.
Klassen B5 und eine Klasse C7 enthalten innewohnend die Daten und
Verfahren der Elternklasse A3. Wie es gezeigt ist, definiert eine
Klasse B5 keine der virtuellen Funktionen foo() und bar() neu. Jedoch
definiert eine Klasse C7 die virtuelle Funktion foo() neu. Wenn
ein Objekt der Klasse C7 angefragt wird, das Verfahren foo() aufzurufen,
wird das aufgerufene Verfahren das durch die Klasse C7 definierte
Verfahren und nicht die Elternklasse A3 sein. Klassen D9 und E11
definieren auch das Verfahren foo() neu.
-
Da es allgemein unmöglich ist,
die Klasse eines Objekts statisch zu bestimmen, wird die Suche nach
dem richtigen Verfahren, das zu dem Objekt gehört, während einer Laufzeitausführung oder,
genauer gesagt, während
eines Absetzens einer Nachricht durchgeführt. Beispielsweise soll angenommen
sein, dass ein Verfahren wie folgt ist:
-
-
Wenn alle Klassen A–E zur Laufzeitausführung geladen
sind, wird die Bestimmung diesbezüglich, welche Funktion foo()
aufzurufen ist, davon abhängen,
welche Klasse x ein dringender Fall ist.
-
Weiterhin kann die Testfunktion zur
Laufzeit kompiliert werden, um eine Leistungsfähigkeit zu erhöhen. Bei
einer Laufzeitkompilation ist es möglich, dass nur die Klassen
A3 und B5 geladen werden. Demgemäß erscheint
es aus einer Untersuchung der geladenen Klassen so zu sein, dass
man annehmen kann, dass die Nachricht x.foo() nur A::foo() aufrufen wird.
Natürlich
würde sich
dann, wenn während
einer Laufzeitausführung
die Klasse C7 geladen wird, diese Annahme als falsch erweisen.
-
ZUSAMMENFASSUNG DER ERFINDUNG
-
Allgemein liefern Ausführungsbeispiele
der vorliegenden Erfindung innovative Techniken zum Durchführen eines
statischen Bindens von abgesetzten Aufrufen beim Vorhandensein eines
dynamischen Bindens und Ladens. Gemäß einem Aspekt der vorliegenden
Erfindung enthält
ein Verfahren zum Erhöhen
der Ausführungsleistungsfähigkeit
einer Funktion zur Laufzeit ein Kompilieren der Funktion, die entweder
interpretiert oder zuvor kompiliert werden kann, und ein Identifizieren
eines Aufrufs innerhalb der Funktion zu einem Prozess. Das Verfahren
enthält
auch ein Hinzufügen
bzw. Addieren einer Abhängigkeitsinformation
zu der Funktion. Die Abhängigkeitsinformation
ist angeordnet, um einen Status der Funktion anzuzeigen, und enthält Information, die
zu der Klasse, dem Namen und der Signatur, die zu dem Prozess gehören, gehört.
-
Gemäß einem weiteren Aspekt der
vorliegenden Erfindung enthält
ein computerimplementiertes Verfahren zum Analysieren einer ersten
Klasse, die zu einer Klassenhierarchie eines Systems während einer
Laufzeit gehört,
ein Markieren der ersten Klasse und ein Markieren einer zweiten
Klasse, die eine Superklasse der ersten Klasse ist, um eine zugehörige zwischen
den beiden Klassen anzuzeigen. Dann wird eine zum System gehörende kompilierte Funktion
untersucht. Die kompilierte Funktion enthält eine Abhängigkeitsinformation, die eingerichtet
ist, um einen Gültigkeitsstatus
der kompilierten Funktion sowie den Optimierungsstatus der kompilierten Funktion
anzuzeigen. Ein Untersuchen der kompilierten Funktion enthält ein Bestimmen,
wann wenigstens eine der ersten Klasse und der zweiten Klasse in
der Abhängigkeitsinformation
identifiziert wird. Wenn bestimmt wird, dass entweder die erste
Klasse oder sowohl die erste Klasse als auch die zweite Klasse in
der Abhängigkeitsinformation
identifiziert wird, wird eine Bestimmung diesbezüglich durchgeführt, ob
die kompilierte Funktion ungültig
ist. Bei einem Ausführungsbeispiel
kann das Verfahren ein Entkompilieren der kompilierten Funktion
enthalten, wenn bestimmt wird, dass die kompilierte Funktion ungültig ist.
Ein Entkompilieren der kompilierten Funktion kann die Funktion zu
einem interpretierten Zustand zurückbringen.
-
Andere Merkmale und Vorteile der
Erfindung werden ohne weiteres beim Betrachten der folgenden detaillierten
Beschreibung in Zusammenhang mit den beigefügten Zeichnungen offensichtlich
werden.
-
KURZE BESCHREIBUNG
DER ZEICHNUNGEN
-
Die vorliegende Erfindung kann in
spezifischen Ausführungsbeispielen
durch Bezugnahme auf die folgende Beschreibung verstanden werden, genommen
im Zusammenhang mit den beigefügten Zeichnungen,
wobei:
-
1 eine
Klassenhierarchie von Klassen einschließlich virtueller Funktionen
in einer objektorientierten Umgebung darstellt.
-
2 ein
Beispiel eines Computersystems darstellt, das zum Ausführen der
Software eines Ausführungsbeispiels
der Erfindung verwendet werden kann.
-
3 ein
Systemblockdiagramm des Computersystems der 1 zeigt.
-
4 eine
Diagramm-Darstellung einer virtuellen Maschine gemäß einem
Ausführungsbeispiel der
vorliegenden Erfindung.
-
5 ein
Ablaufdiagramm eines Ausführungsbeispiels
der Erfindung darstellt, das ein Verfahren zur Laufzeit kompiliert.
-
6 ein
Ausführungsbeispiel
eines kompilierten Verfahrens einschließlich einer Abhängigkeitsinformation
zeigt.
-
7 ein
Ablaufdiagramm eines Prozesses eines Ladens einer Klasse während einer
Laufzeitausführung
gemäß einem
Ausführungsbeispiel
der vorliegenden Erfindung darstellt.
-
8 eine
Darstellung einer Klassenhierarchie in einem Speicher gemäß einem
Ausführungsbeispiel
der vorliegenden Erfindung zeigt.
-
DETAILLIERTE BESCHREIBUNG
BEVORZUGTER AUSFÜHRUNGSBEISPIELE
-
Definitionen
-
Maschinenanweisung (oder Anweisung) – Eine Anweisung,
die eine Rechenvorrichtung dirigiert, eine Operation durchzuführen, die
durch einen Operationscode (OP-Code), und optional durch einen oder
mehrere Operanden, spezifiziert ist.
-
Virtuelle Maschinenanweisung – Eine Anweisung
für einen
mittels Software emulierten Mikroprozessor oder eine Computerarchitektur
(auch virtueller Code genannt).
-
Maschinenspezifische Anweisung – Eine Anweisung,
die für
einen spezifischen Mikroprozessor oder eine spezifische Computerarchitektur
entwickelt ist (auch maschinenspezifischer Code genannt).
-
Verfahren bzw. Methode – Eine Softwareroutine
(die auch Funktion, Unterroutine bzw. Unterprogramm, Prozedur und
Teilnehmerfunktion genannt wird).
-
Laufzeitkompilation – Kompilation
eines Codes, die zur Laufzeit durchgeführt wird.
-
Laufzeitausführung – Ausführung eines Codes, die zur
Laufzeit durchgeführt
wird.
-
Detaillierte
Beschreibung
-
In der Beschreibung, die folgt, wird
die vorliegende Erfindung unter Bezugnahme auf bevorzugte Ausführungsbeispiele
beschrieben, die dynamisch abgesetzte Aufrufe in virtuellen JAVA-Maschinenanweisungen
(oder Bytecodes) statisch binden. Jedoch ist die Erfindung nicht auf
irgendeine bestimmte Sprache, eine bestimmte Computerarchitektur
oder eine spezifische Implementierung beschränkt. Daher dient die Beschreibung
der Ausführungsbeispiele, die
folgen, zu Zwecken einer Darstellung und nicht zur Beschränkung.
-
Die JAVATM-Programmiersprache
ist eine objektorientierte problemorientierte Programmiersprache,
die von Sun Microsystems entwickelt und entworfen ist, um ausreichend
portierbar zu sein, um in einem weiten Bereich von Computern ausgeführt zu werden,
der von kleinen Vorrichtungen (z. B. Pager, Zellulartelefonen bzw.
Mobilfunktelefonen und Smartcards bzw. Chip-Karten) bis zu Supercomputern
reicht. Computerprogramme, die in JAVA (und anderen Sprachen) geschrieben
sind, können
zur Ausführung
durch eine virtuelle JAVA-Maschine in virtuelle Maschinenanweisungen
kompiliert werden. Allgemein ist die virtuelle JAVA-Maschine ein
Interpretierer, der die virtuellen Maschinenanweisungen decodiert
und ausführt.
-
Die virtuellen Maschinenanweisungen
für die virtuelle
JAVA-Maschine sind
Bytecodes, was bedeutet, dass sie eines oder mehrere Bytes enthalten.
Die Bytecodes werden in einem bestimmten Dateienformat gespeichert,
das "Klassendatei" genannt wird, die
Bytecodes für
Verfahren einer Klasse enthält.
Zusätzlich
zu den Bytecodes für
Verfahren einer Klasse enthält
die Klassendatei eine Symboltabelle sowie andere Hilfsinformationen.
-
Ein Computerprogramm, das als JAVA-Bytecodes
in einer oder mehreren Klassendateien verkörpert ist, ist plattformunabhängig. Das
Computerprogramm kann unmodifiziert auf irgendeinem Computer ausgeführt werden,
der dazu fähig
ist, eine Implementierung der virtuellen JAVA-Maschine laufen zu lassen.
Die virtuelle JAVA-Maschine ist ein Software-Emulator eines "allgemeinen" Computers, der ein Hauptfaktor dabei
ist, zuzulassen, dass Computerprogramme für die virtuelle JAVA-Maschine
plattformunabhängig
sind.
-
Die virtuelle JAVA-Maschine kann
als Software-Interpretierer implementiert sein. Herkömmliche
Interpretierer decodieren die virtuellen Maschinenanweisungen eines
interpretierten Programms mit einer Anweisung zu einer Zeit während einer
Ausführung
und führen
sie aus, was gegensätzlich
zu Kompilierern ist, die einen Quellencode vor einer Ausführung in
maschinenabhängige
Anweisungen decodieren, so dass während einer Ausführung kein Decodieren
durchgeführt
wird. Die virtuelle JAVA-Maschine kann sowohl einen Interpretierer
als auch einen Kompilierer für
eine Laufzeitkompilation enthalten. Typischerweise wird die virtuelle
JAVA-Maschine in einer Programmiersprache geschrieben sein, die eine
andere als die JAVA-Programmiersprache ist (z. B. die Programmiersprache
C++).
-
2 stellt
ein Beispiel eines Computersystems dar, das dazu verwendet werden
kann, die Software eines Ausführungsbeispiels
der Erfindung auszuführen. 2 zeigt ein Computersystem 301,
das eine Anzeige 303, einen Bildschirm 305, ein
Gehäuse 307,
eine Tastatur 309 und eine Maus 311 enthält. Die
Maus 311 kann eine oder mehrere Tasten zum Interagieren
mit einer graphischen Anwenderschnittstelle haben. Das Gehäuse 307 umgibt
ein CD-ROM-Laufwerk 313, einen Systemspeicher und ein Festplattenlaufwerk
(siehe 3), die dazu
verwendet werden können,
Softwareprogramme zu speichern und wiederzugewinnen, die einen Computercode,
der die Erfindung implementiert, Daten zur Verwendung mit der Erfindung
und ähnliches
enthalten. Obwohl der CD-ROM 315 als beispielhaftes computerlesbares
Speichermedium gezeigt ist, können
andere computerlesbare Speichermedien einschließlich einer Floppy-Disk, eines
Bandes, eines Flash-Speichers, eines Systemspeichers und eines Festplattenlaufwerks
verwendet werden. Zusätzlich kann
ein Datensignal, das in einer Trägerwelle
verkörpert
ist (z. B. in einem Netzwerk einschließlich des Internets) das computerlesbare
Speichermedium sein.
-
3 zeigt
ein System-Blockdiagramm eines Computersystems 301, das
dazu verwendet wird, die Software eines Ausführungsführungsbeispiels der Erfindung
auszuführen.
Wie in 2 enthält das Computersystem 301 einen
Monitor 303 und eine Tastatur 309 und eine Maus 311.
Das Computersystem 301 enthält weiterhin Untersysteme,
wie beispielsweise einen Zentralprozessor 351, einen Systemspeicher 353,
einen festen Speicher 355 (z. B. ein Festplattenlaufwerk),
einen entfernbaren Speicher 357 (z. B. ein CD-ROM-Laufwerk),
einen Anzeigenadapter 359, eine Klangkarte bzw. Soundkarte 361, Lautsprecher 363 und
eine Netzwerkschnittstelle 365. Andere Computersysteme,
die zur Verwendung bei der Erfindung geeignet sind, können zusätzliche oder
weniger Untersysteme enthalten. Beispielsweise könnte ein weiteres Computersystem
mehr als einen Prozessor 351 (d. h. ein Mehrfachprozessorsystem)
oder einen Cache-Speicher enthalten.
-
Die Systembusarchitektur des Computersystems 301 ist
durch Pfeile 367 dargestellt. Jedoch sind diese Pfeile
für irgendein
Verbindungsschema illustrativ, das zum Verbinden der Untersysteme
dient. Beispielsweise könnte
ein lokaler Bus dazu verwendet werden, den Zentralprozessor mit
dem Systemspeicher und dem Anzeigenadapter zu verbinden. Das in 3 gezeigte Computersystem 301 ist
aber ein Beispiel eines Computersystems, das zur Verwendung bei
der Erfindung geeignet ist. Andere Computerarchitekturen mit anderen
Konfigurationen von Untersystemen können auch verwendet werden.
-
Typischerweise werden in der JAVA-Programmiersprache
geschriebene Computerprogramme in Bytecodes oder virtuelle JAVA-Maschinenanweisungen
kompiliert, die dann durch eine virtuelle JAVA-Maschine ausgeführt werden.
Die Bytecodes werden in Klassendateien gespeichert, die zur Interpretation
in die virtuelle JAVA-Maschine eingegeben werden. Eine virtuelle
Maschine kann auf einem Computersystem, wie beispielsweise dem zuvor
unter Bezugnahme auf die 2 und 3 diskutierten Computersystem,
ausführen. 4 ist eine Diagramm-Darstellung
einer virtuellen Maschine, die durch das Computersystem 301 der 2 und 3 unterstützt wird, und ist zum Implementieren
der vorliegenden Erfindung geeignet. Wenn ein Computerprogramm,
z. B. ein in der JAVATM-Programmiersprache geschriebenes Computerprogramm,
ausgeführt
wird, wird ein Quellencode 410 zu einem Compiler bzw. Kompilierer 420 innerhalb
einer Kompilierzeitumgebung 405 geliefert. Der Kompilierer 420 setzt
den Quellencode 410 in Bytecodes 430 um. Allgemein wird
der Quellencode 410 zu der Zeit in Bytecodes 430 übersetzt,
zu welcher der Quellencode 410 durch einen Software-Entwickler
erzeugt wird.
-
Bytecodes 430 können allgemein über ein Netzwerk,
z. B. die Netzwerkschnittstelle 365 der 3, reproduziert, heruntergeladen oder
auf andere Weise verteilt werden, oder in einer Speichervorrichtung,
wie beispielsweise der Speichervorrichtung 355 der 3, gespeichert werden. Bei
dem beschriebenen Ausführungsbeispiel
sind die Bytecodes 430 plattformunabhängig. Das bedeutet, dass die Bytecodes 430 auf
im Wesentlichen irgendeinem Computersystem ausgeführt werden
können,
das auf einer geeigneten virtuellen Maschine 440 läuft.
-
Die Bytecodes 430 werden
zu einer Laufzeitumgebung 435 geliefert, die eine virtuelle
Maschine 440 enthält.
Bei einem Ausführungsbeispiel
kann die virtuelle Maschine eine virtuelle JAVATM-Maschine sein.
Die Laufzeitumgebung 435 kann allgemein unter Verwendung
eines Prozessors oder von Prozessoren, wie beispielsweise dem Prozessor 351 der 3, ausgeführt werden.
Die virtuelle Maschine 440 enthält einen Kompilierer 442,
einen Interpretierer 444 und ein Laufzeitsystem 446.
Die Bytecodes 430 können
entweder zum Kompilierer 442 oder zum Interpretierer 444 geliefert
werden.
-
Wenn die Bytecodes 430 zum
Kompilierer 442 geliefert werden, werden in den Bytecodes 430 enthaltene
Verfahren in Maschinenanweisungen kompiliert. Bei einem Ausführungsbeispiel
ist der Kompilierer 442 ein Kompilierer genau für eine Zeit, der
die Kompilation von Verfahren verzögert, die in den Bytecodes 430 enthalten
ist, bis die Verfahren dabei sind, ausgeführt zu werden. Wenn die Bytecodes 430 zum
Interpretierer 444 geliefert werden, werden die Bytecodes 430 mit
einem Bytecode zu einer Zeit in den Interpretierer 444 gelesen.
Der Interpretierer 444 führt dann die durch einen jeweiligen Bytecode
definierte Operation durch, wenn jedes Bytecode in den Interpretierer 444 gelesen
ist. Das bedeutet, dass der Interpretierer 444 die Bytecodes 430 "interpretiert", wie es von Fachleuten
auf dem Gebiet erkannt werden wird. Allgemein verarbeitet der Interpretierer 444 die
Bytecodes 430 und führt Operationen
durch, die zu den Bytecodes 430 gehören, und zwar im Wesentlichen
kontinuierlich.
-
Wenn ein Verfahren durch ein anderes
Verfahren aufgerufen wird oder von der Laufzeitumgebung 435 aufgerufen
wird, wenn das Verfahren interpretiert ist, kann das Laufzeitsystem 446 das
Verfahren von der Laufzeitumgebung 435 in der Form einer Sequenz
von Bytecodes 430 erhalten, welche durch den Interpretierer 444 direkt
ausgeführt
werden können.
Wenn andererseits das Verfahren, das aufgerufen wird, ein kompiliertes
Verfahren ist, das nicht kompiliert worden ist, erhält das Laufzeitsystem 446 auch
das Verfahren von der Laufzeitumgebung 435 in der Form
einer Sequenz von Bytecodes 430, und kann dann dazu übergehen,
den Kompilierer 442 zu aktivieren. Der Kompilierer 442 erzeugt
dann Maschinenanweisungen aus den Bytecodes 430, und die resultierenden
Maschinensprachenanweisungen können
durch den Prozessor 351 der 3 direkt
ausgeführt
werden. Allgemein werden die Maschinensprachenanweisungen weggeworfen,
wenn die virtuelle Maschine 440 beendet.
-
JAVA-Klassen (und -Schnittstellen)
werden dynamisch geladen, gebunden und initialisiert. Ein Laden
ist der Prozess des Systems, der die binäre Form der Klasse (z. B. die
Klassendatei) findet und aus der binären Form ein Klassenobjekt
bildet, um die Klasse darzustellen. Die Klassenklasse ist eine Klasse
zum Speichern oder Darstellen der Strukturen von Klassen. Ein Binden
ist der Prozess zum Annehmen einer binären Form der Klasse und zum
Kombinieren von ihr in den Laufzeitzustand des Systems, so dass
sie ausgeführt
werden kann. Eine Initialisierung einer Klasse enthält ein Ausführen der
statischen Initialisierer der Klasse und der Initialisierer für statische
Felder, die in der Klasse erklärt
sind.
-
Jede JAVA-Klasse hat einen konstanten Pool,
der ihr zugeordnet ist. Der konstante Pool ist in der JAVA-Klassendatei gespeichert
und dient als Funktion, die gleich Symboltabellen ist. Typischerweise
wird jeder Eintrag im konstanten Pool durch eine Zahl indiziert,
die mit Eins beginnt und mit der Zahl von Einträgen im konstanten Pool endet.
Ein Verfahren für
Klassenzugriffe tritt in den konstanten Pool durch den Index ein,
und ein Verfahren für
eine Klasse kann für
eine andere Klasse nicht auf einen konstanten Pool zugreifen.
-
Zusätzlich zu dem konstanten Pool,
der literale Konstanten speichert, speichert der konstante Pool
Klassen, Verfahren, Felder und Schnittstellen symbolisch. Mit einem
symbolischen Speichern dieser Einträge ist gemeint, dass der Name,
der den Eintrag identifiziert, gespeichert wird, und nicht die physikalische
Adresse. Anders ausgedrückt
können dann,
wenn eine Klasse A ein Feld F hat, beide Namen von A und F (zusammen
mit einer Typensignatur für
F) im konstanten Pool gespeichert werden. Durch Speichern von Namen
und nicht von Adressen löst das
JAVA-Laufzeitsystem die symbolische Referenz in eine physikalische
Adresse zur Laufzeit dynamisch auf.
-
5 stellt
ein Ablaufdiagramm eines Ausführungsbeispiels
der Erfindung dar, das ein Verfahren zur Laufzeit kompiliert. Bei
einem Schritt 501 bestimmt das System, dass es vorteilhaft
ist, ein Verfahren zu kompilieren. Allgemein erhöht ein Kompilieren eines Verfahrens
die Ausführungsleistung
des Verfahrens. Jedoch gibt es viele Fälle, in welchen Verfahren nicht
kompiliert werden. Beispielsweise können kompilierte Verfahren
mehr Speicherplatz als Verfahren, die nicht kompiliert sind, erfordern.
In jedem Fall wird dann, wenn einmal bestimmt wird, dass ein bestimmtes
Verfahren kompiliert werden sollte, dieses Verfahren bei einem Schritt 503 kompiliert.
-
Bei einem Schritt 505 identifiziert
das System einen Aufruf zu einer virtuellen Funktion in dem Verfahren,
das kompiliert wird. Wie es oben diskutiert ist, wird eine Auflösung eines
Aufrufs einer virtuellen Funktion dynamisch zur Laufzeit durchgeführt. Bei den
virtuellen JAVA-Maschinenanweisungen ist der Aufruf eine virtuelle
Aufrufanweisung.
-
Das System analysiert die Klassenhierarchie zur
Laufzeitkompiliation bei einem Schritt 507. Die Klassenhierarchie
kann diese gegenwärtig
nur eine Funktion einer geladenen Klasse anzeigen, die der Empfänger des
Aufrufs der virtuellen Funktion sein würde. Wenn nur eine Funktion
der geladenen Klasse der Empfänger
des Aufrufs für
die virtuelle Funktion sein würde,
kann das System einen direkten Aufruf zu dieser Funktion im kompilierten
Verfahren absetzen. Zusätzlich
kann das System die gesamte Funktion in das kompilierte Verfahren
einreihen. Ein Einreihen der gesamten Funktion erfordert mehr Speicherraum
für das
kompilierte Verfahren, resultiert aber in einer schnelleren Durchführbarkeit.
-
In einigen Fällen gibt es mehr als eine
Funktion von geladenen Klassen, die der Empfänger des Aufrufs für eine virtuelle
Funktion sein könnten.
Wenn dies der Fall ist, kann das System einen Entscheidungsbaum
oder eine Hash-Tabelle einreihen, die direkte Aufrufe zu den Funktionen
enthält,
und/oder Funktionen einreihen. Das bedeutet, dass der Aufruf zu
der virtuellen Funktion, wie es in Bezug auf den Schritt 505 diskutiert
ist, bei einem Schritt 909 optimiert werden kann. Techniken
zum Durchführen
von Aufrufen für
eine virtuelle Funktion sind in der Anmeldung Nr. 08/944,332, eingereicht
am 06. Oktober 1997, beschrieben.
-
Bei einem Schritt 511 fügt das System
eine Abhängigkeitsinformation
zum kompilierten Verfahren hinzu. Die Abhängigkeitsinformation kann die Klasse,
den Funktionsnamen und eine Signatur (d. h. Parametertypen) einer
jeweiligen virtuellen Funktion enthalten, die beim Schritt 509 optimiert
worden ist. Auf diese Weise kann dann, wenn Klassen zur Laufzeitausführung geladen
werden, die Abhängigkeitsinformation
für ein
kompiliertes Verfahren geprüft
werden, um zu bestimmen, ob das kompilierte Verfahren noch gültig ist,
deoptimiert werden sollte oder neu optimiert werden sollte. Dieser
Prozess wird nachfolgend unter Bezugnahme auf 7 detaillierter beschrieben.
-
6 zeigt
ein Ausführungsbeispiel
eines kompilierten Verfahrens mit einer Abhängigkeitsinformation. Ein kompiliertes
Verfahren 609 enthält
einen Anfangsblock 603 und einen kompilierten Code 605. Der
Anfangsblock 603 enthält
u. a. eine Abhängigkeitsinformation 607.
Die Abhängigkeitsinformation 607 ist
beim beschriebenen Ausführungsbeispiel eine
Liste aus der Klasse, dem Namen und der Signatur von allen Aufrufen
für eine
virtuelle Funktion, die im kompilierten Verfahren 609 optimiert
wurden. Obwohl diese Information als einfache Liste gespeichert
werden kann, kann eine Vielfalt von anderen Speichertechniken verwendet
werden.
-
7 stellt
ein Ablaufdiagramm eines Prozesses eines Ladens einer Klasse während einer Laufzeitausführung dar.
Bei einem Schritt 701 empfängt das System eine zur Laufzeit
zu ladende Klasse. Das System markiert dann die Klasse und alle ihre
Unterklassen bei einem Schritt 703. Die Klassen können durch
Einstellen eines Bool'schen
Felds in einer Klassenhierarchiestruktur (siehe 8) markiert werden.
-
Bei einem Schritt 705 untersucht
das System alle kompilierten Verfahren, um zu bestimmen, ob sie irgendeine
der markierten Klassen in ihrer Abhängigkeitsinformation enthalten.
Wie es oben diskutiert ist, kann die Abhängigkeitsinformation in einem
Anfangsblock des kompilierten Verfahren gespeichert sein. Wenn irgendeine
der markierten Klassen in einer Abhängigkeitsinformation des kompilierten
Verfahrens enthalten ist, bestimmt das System, ob es einen Funktionsnamen
und eine Signaturanpassung gibt, bei einem Schritt 707.
-
Durch Bestimmen, ob es einen Funktionsnamen
und eine Signaturanpassung gibt, stellt das System fest, ob ein
Laden der Klasse veranlasst, dass irgendeines der kompilierten Verfahren
effektiv für
ungültig
erklärt
wird. Anders ausgedrückt
bestimmt die Bestimmung diesbezüglich,
dass es einen Funktionsnamen und eine Signaturanpassung gibt, ob
ein Laden der Klasse einen neuen und zuvor nicht berücksichtigten
Empfänger
für einen
Aufruf für
eine virtuelle Funktion, der optimiert worden ist, erzeugt.
-
Nimmt man wiederum Bezug auf 1 kann beispielsweise dann,
wenn nur Klassen A3 und B5 zur Laufzeitkompilation geladen werden,
das System einen direkten Aufruf zu A::foo() (oder sogar die gesamte
Funktion einreihen) in einem kompilierten Verfahren anordnen, da
es nur eine Funktion gibt, die der Empfänger des Aufrufs für die virtuelle
Funktion sein könnte.
Jedoch dann, wenn während
einer Laufzeitausführung
eine Klasse C7 geladen wird, gibt es einen weiteren möglichen
Empfänger
für den
Aufruf für eine
virtuelle Funktion (d. h. C::foo()). Somit sollte das kompilierte
Verfahren entweder deoptimiert oder neu optimiert werden. Techniken
zur Deoptimierung von kompilierten Verfahren sind in der Anmeldung
Nr. 08/944,330, eingereicht am 06. Oktober 1997, beschrieben.
-
Wenn es beim Schritt 707 eine
Anpassung für
ein kompiliertes Verfahren gibt, kann das kompilierte Verfahren
bei einem Schritt 709 deoptimiert werden. Ein Deoptimieren
des kompilierten Verfahrens kann ein Umkehren oder auf andere Weise
ein "Entkompilieren" des Verfahrens in
seine interpretierte Form enthalten. Zusätzlich kann das System das kompilierte
Verfahren so neu optimieren, dass es nun die neu geladene Klasse
berücksichtigt.
-
8 zeigt
eine Darstellung einer Klassenhierarchie in einem Speicher. Eine
Klasse 801 ist bei der Wurzel gezeigt, die anzeigt, dass
sie eine Superklasse für
Klassen unter ihr ist. Wie es gezeigt ist, sind Klassen 803 und 805 Unterklassen
der Klasse 801. Die Klasseninformation für jede Klasse
kann ein Bool'sches
Feld enthalten, das dazu verwendet wird, die Klassen zu markieren,
und zwar wie im Schritt 703 der 7.
-
Zusätzlich kann die Klasseninformation
für jede
Klasse einen Unterklassenzeiger und einen Nachkommenschaftszeiger
enthalten. Der Unterklassenzeiger zeigt zu einer ersten Unterklasse,
die bei diesem Beispiel die Klasse 803 ist. Der Nachkommenschaftszeiger
bildet eine verbundene Liste der Klassen, die Nachkommenschaften
sind. Wie es gezeigt ist, zeigt der Nachkommenschaftszeiger der Klasse 803 zur
Klasse 805. Unter Verwendung der Unterklassen- und Nachkommenschaftszeiger
kann das System bei einem Ausführungsbeispiel
der Erfindung auf einfache Weise die Klassenhierarchie durchqueren.
-
Schluss
-
Während
das obige eine vollständige
Beschreibung bevorzugter Ausführungsbeispiele
der Erfindung ist, können
verschiedene Alternativen, Modifikationen und Äquivalente verwendet werden.
Es sollte offensichtlich sein, dass die Erfindung gleichermaßen durch
Durchführen
geeigneter Modifikationen an den oben beschriebenen Ausführungsbeispielen anwendbar
ist. Beispielsweise können,
obwohl die beschriebenen Ausführungsbeispiele
unter Bezugnahme auf virtuelle JAVA-Maschinenanweisungen erfolgt sind, die
Prinzipien der vorliegenden Erfindung ohne weiteres auf andere Anweisungen
angewendet werden. Daher sollte die obige Beschreibung nicht als
den Schutzumfang der Erfindung beschränkend angenommen werden.