4

Ein polymorpher Inline-Cache (PIC) funktioniert, indem die tatsächliche Methode nach dem Objekttyp zwischengespeichert wird, um kostspielige Nachschlagevorgänge (in der Regel eine Hashtabellensuche) zu vermeiden.Wie funktionieren polymorphe Inline-Caches mit veränderbaren Typen?

Wie behandelt man den Typvergleich, wenn die Typobjekte veränderbar sind (d. H., Die Methode könnte zur Laufzeit in etwas anderes gepatcht werden)? Die einzige Idee, die ich mir ausgedacht habe, wäre ein "Klassenzähler", der jedes Mal um eins erhöht wird, wenn eine Methode angepasst wird, aber dies scheint in einer schwer monkey-gepatchten Umgebung außergewöhnlich teuer zu sein, da es töten würde alle PICs für diese Klasse, auch wenn die Methoden für sie nicht geändert wurden.

Ich bin mir sicher, dass es eine gute Lösung dafür geben muss, da dieses Problem direkt auf JavaScript anwendbar ist, und AFAIK alle drei der großen virtuellen JavaScript-Maschinen PICs haben.

+0

Das klingt wie ein Rezept für eine Katastrophe. –

Antwort

1

In V8 würde ich annehmen, dass monkeypatching die "versteckte Klasse" ("Karte" ist SELF-Terminologie) des Objekts ändern würde. Das würde in dir funktionieren Affe flickte das Objekt selbst.

Wenn Sie Affen die Klasse gepatcht haben (können Sie das JS tun?), Würde ich vermuten, dass es alle PICs ungültig macht, da dies wahrscheinlich selten ist. Alternativ könnte es die alte Methode neu kompilieren, um direkt zu der neuen Methode zu versenden (nach einer Typprüfung, die ich rate)

Nebenbei denke ich nicht, dass die anderen "großen 3" PICs tatsächlich verwenden. Ich nehme an, du meinst Squirrelfish und Traummonkey. Der Erste ist ein Dolmetscher, und der Letztere konzentriert sich auf den Verfolgungs-Ansatz, und ich erinnere mich nicht, etwas über PICs gehört zu haben. In der Tat glaube ich nicht, dass tracemonkey irgendetwas für Objekte cool macht, aber ich könnte falsch liegen.

0

Typ-Inferenz verwendet:

Spider hauptsächlich Inferenz verwendet Typ zu bestimmen, welche Eigenschaften zugegriffen wird; In Fällen, in denen Typinferenz nicht die genaue Form des Objekts findet, auf das zugegriffen wird, verwendet SpiderMonkey einen PIC (polymorphe Inline-Caches), um das Ergebnis der Suche zu speichern.

Eine weitere Form der Profilermittlung sind die polymorphen Inline-Caches des Baseline JIT. Polymorphe Inline-Caches sind eine klassische Technik zur Optimierung des dynamischen Versands, die aus der Smalltalk-Community stammt.

De-Optimierung ist der Name des Prozesses, was geschieht, wenn Typinferenz fehlschlägt:

Natürlich JavaScript eine dynamisch typisierte Sprache ist, ocassionally die Annahme über die versteckte Klasse des Objekts wird falsch, und in diesem Fall wird V8 "de-optimize" und kehrt zurück zur ursprünglichen Version des Methodenaufrufs, in dem die versteckte Klasse der Objekte überprüft wird.

Multiple Compiler ist notwendig, damit dies funktioniert:

Technisch bedeutet dies, dass der Compiler in der Tat zwei Compiler: eine Basis-Compiler und ein „Optimierungsprogramm“. (Oder noch mehr, wenn wir über JSC und SpiderMonkey sprechen). Das Konzept ist ziemlich solide und kann eine unglaubliche Leistung erbringen, aber es gibt eine Nuance: Der optimierte Code kann an verschiedenen Stellen "deoptimiert" werden, nicht nur am Eintrittspunkt, was bedeutet, dass die Umgebung (lokale Variablen, Argumente, Kontext) sein sollte kartiert und bewegt.

Da Ion der optimierende Compiler ist, unterstützt er das Kompilieren im Debug-Modus nicht. In der Tat ist die Implementierung einer solchen Unterstützung von zweifelhaftem Nutzen, da ihre Optimierungen im besten Fall zu unheilvollen Anrufungen führen würden. Um den Debug-Modus zu unterstützen, wird optimierter Code auf dem Stack optimiert und in Baseline gesichert. Das heißt, der Ionenrahmen auf dem Stapel wird mit einem rekonstruierten Grundlinienrahmen überschrieben, der der gleichen Stelle entspricht, an der der Ionenkode gerade ausgeführt wird.

Debugging wird über dynamische Deoptimierung getan:

wir besser machen können. Der Traum der 90er Jahre, verkörpert in der Sprache des Selbst, lebt in JavaScript. Wir können Self's dynamische Optimierung durch On-Stack-Austausch-Technik anpassen, um sogar optimierten Code zu debuggen. Die Kernidee von debug mode OSR ist einfach: Wenn das Debuggen erforderlich ist, optimieren wir den JITed-Code auf dem Stack und kompilieren ihn neu, indem wir die Return-Adressen patchen, während wir fortfahren. Man könnte sagen, dass es fast elegant ist, wenn es nicht für die hohe Gewalt, die es auf Stapelrahmen ausübt, kommt.

Betrachten Sie die folgende JavaScript-Funktion:

function foo(o) { return o.f + o.g; } 

In diesem Beispiel greift die Eigenschaft auf allem von einer einfachen Last von bekannten Orten in der Halde zu Anrufungen von Getter führen kann oder sogar komplizierte DOM-Traps, als wären o ein Dokumentobjekt und f der Name eines Elements auf der Seite. Das Baseline-JIT führt diese Eigenschaftszugriffe anfangs als vollständig polymorphe Verteilung aus. Aber während es dies tut, zeichnet es die Schritte auf, die es benötigt, und modifiziert dann die Heap-Zugriffe als Caches der notwendigen Schritte, um einen ähnlichen Zugriff in der Zukunft zu wiederholen. Wenn das Objekt beispielsweise eine Eigenschaft f bei Offset 16 von der Basis des Objekts hat, wird der Code geändert, um zuerst schnell zu überprüfen, ob das eingehende Objekt aus einer Eigenschaft f bei Offset 16 besteht, und dann die Last auszuführen. Diese Caches werden als inline bezeichnet, da sie vollständig als generierter Maschinencode dargestellt werden. Es wird gesagt, dass sie polymorph sind, da der Maschinencode modifiziert wird, wenn verschiedene Objektstrukturen angetroffen werden, um die zuvor angetroffenen Objekttypen einzuschalten, bevor eine vollständig dynamische Eigenschaftensuche durchgeführt wird. Wenn der DFG diesen Code kompiliert, wird er prüfen, ob der Inline-Cache monomorph ist - optimiert für nur eine Objektstruktur - und wenn ja, wird nur eine Überprüfung für diese Objektstruktur gefolgt von der direkten Belastung ausgegeben. Wenn in diesem Beispiel o immer ein Objekt mit den Eigenschaften f und g bei invarianten Offsets wäre, müsste das DFG nur eine Typprüfung für o gefolgt von zwei direkten Lasten ausgeben.

Data Flow Just-in-Time Compiler (DFG JIT) Optimization Pipeline

Faster-Than-Light Just-in-Time Compiler (FTL JIT) Optimization Pipeline

Referenzen

Verwandte Themen