Escape Analysis in the Context of Dynamic Compilation and Deoptimization


Abstract

Escape analysis is used in compilers to identify and optimize the allocation of objects that are accessible only within the allocating method or thread. This thesis presents a new intra- and interprocedural analysis for a dynamic compiler, which has to cope with dynamic class loading and deoptimization.

The analysis was implemented for Sun Microsystems' Java HotSpot™ client compiler. It operates on an intermediate representation in SSA form and introduces equi-escape sets for the efficient propagation of escape information between related objects. Analysis results are used for scalar replacement of fields, stack allocation of objects and synchronization removal. The interprocedural analysis supports the compiler in inlining decisions and allows actual parameters to be allocated in the stack frame of the caller. A lightweight bytecode analysis produces interprocedural escape information for methods that have not been compiled yet.

Dynamic class loading possibly invalidates the generated machine code. In this case, the execution of a method is continued in the interpreter. This is called deoptimization. Since the interpreter does not know about scalar replacement, stack allocation or synchronization removal, the deoptimization framework was extended to reallocate and relock objects on demand.

Kurzfassung

Escape-Analyse identifiziert und optimiert die Allokation von Objekten, auf die nur eine Methode oder ein Thread zugreifen kann. Diese Dissertation präsentiert eine neue intra-und interprozedurale Analyse für einen Just-in-Time-Compiler, der dynamisches Laden von Klassen und Deoptimierung unterstützt.

Die Analyse wurde für den Java HotSpot Client Compiler von Sun Microsystems implementiert. Sie arbeitet auf einer Zwischensprache in SSA-Form und verwaltet voneinander abhängige Objekte effizient in Mengen. Die Ergebnisse werden verwendet, um Felder durch skalare Variablen zu ersetzen, Objekte am Stack anzulegen und Synchronisation zu entfernen. Die interprozedurale Analyse unterstützt den Compiler bei Inline-Entscheidungen und identifiziert Methodenparameter, die am Stack angelegt werden können. Eine schnelle Bytecode-Analyse liefert Informationen für Methoden, die noch nicht compiliert wurden.

Dynamisches Laden von Klassen kann bestehenden Maschinencode invalidieren. In diesem Fall wird die Ausführung der Methode im Interpreter fortgesetzt. Dies nennt man Deoptimierung. Da der Interpreter die Optimierungen des Compilers nicht kennt, wurde das Framework zur Deoptimierung so erweitert, dass es Objekte nachträglich am Heap anlegt und sperrt.


Contact: Thomas Kotzmann

Download als pdf