Problem: Efficient dynamic type checking for Java ƒsingle class inheritance ƒmultiple interface inheritance ƒarray subtyping Solutions ƒLeverage (JIT) compile-time information ƒ3 data structures to handle common cases ƒinline code sequences for common cases Dynamic Type Checking [JVM'01]
Taxonomy of Java Types Proper classes always extend one superclass Proper classes may implement many interfaces There are no interface values null is a typeless value (for reference variables) variable type primitive reference boolean byte short char int long float double proper class java.lang.Object interface array of primitive proper class java.lang.Object interface array of primitive proper class java.lang.Object interface array of primitive proper class java.lang.Object interface array of primitive proper object java.lang.Object interface array of
Type Checking in Java Most operations are statically typed Some operations entail dynamic typechecking ƒ Explicit type tests ( instanceof ) b instanceof A; ƒ Down casts ( checkcast ) (A) b; ƒ Interface method invocation ( invokeinterface ) I i = b; // I an interface type i.foo(); ƒ Exception delivery ( athrow ) try {...} catch (A a) {... } ƒ Object array stores ( aastore ) DeclaredType [] X = X[3] = b;
(Simplified) Jalapeño Object Model All objects have a two word header 1Type Information Block (TIB) pointer 2Status word (locking, hashcode, gc, etc.) All types (primitives, arrays, classes) have unique ƒVM_Type objects ƒinteger ids ƒTIBs (arrays, classes only) TIBs are reachable from JTOC (global TOC for statics)
Type Information Block Truck VMTVMT Implements trits Element's TIB (null) TIB for Truck Superclass Id display VM_Type for Truck TIB for a type is an array of Objects The Virtual Method Table for the type Three dynamic type checking data structures The VM_Type object for the type
Example Hierarchy interface Cargo class java.lang.Object class DurableGood extends java.lang.Object class Vehicle extends DurableGood class Car extends Vehicle class Truck extends Vehicle implements Cargo The depth of a class is the number of its superclasses Object has depth 0 DurableGood has depth 1 Vehicle has depth 2 Truck has depth 3
Testing for a Proper Class A is known to be a proper class checkcast and instanceof bytecodes Most significant case (along with aastore) Superclass Identifier Display (SID) [Cohen '91] A class's display contains its type id and the type ids of its ancestors The display is ordered (indexed) by their depth Dynamic type check: Compare depth SID entry of object to type id of A if A_depth >= minimum (6) then array bounds check required
Object Durable Good Superclass Identifier Display Each type has a depth and a type id SID for a type is an array of shorts Maps superclass depth to superclass type id Padded to a minimum depth with invalid ids Truck TIB for Truck VMTVMT SID for Truck 3 90 VM_Type for Truck depth type id Dynamic type check: l r1, TIBoffset(b) l r1, SIDoffset(r1) l r1, A_depth<<1(r1) cmpi r1, A_id bne NoMatch Dynamic type check: l r1, TIBoffset(b) l r1, SIDoffset(r1) l r2, lengthOffset(r1) cmpi r2, A_depth bge NoMatch l r1, A_depth<<1(r1) cmpi r1, A_id bne NoMatch Truck Vehicle
Testing for an Interface Does an object implement interface I? invokeinterface, checkcast, instanceof Three possible answers: 0 - No, 1 - Yes, 2 - Maybe (don't know yet) Monotonic: Maybe becomes Yes or No Implements Trits Vector (Trit == 3-values) Per class cache indexed by interface id Shared ITV's 1Initial ITV - all Maybe (most classes never ask) 2If a class doesn't explicitly implement an interface then it could share its superclass's ITV
Implements Trits Vector ITV for a type is a array of bytes (could use two bits with rotate/mask) No the type doesn't implement the interface Yes the type implements the interface Maybe no determination has yet been made Truck VMTVMT TIB for Truck VM_Type for Truck ITV for Truck Dynamic type check: l r1, TIBoffset(b) l r1, ITVoffset(r1) array-bounds-check l r1, I_interfaceId(r1) cmpi r1, 1 bne ResolveOrNoMatch Cargo
Testing for an Array Is b a subtype of array type A? Dimension of a type (or value) Number of (possible) subscripts of arrays 0 for classes and interfaces -1 for primitives 1Short-circuit type equality test: A == B ? Definitive, if A's base type is primitive or final 2If A's dimension greater than b's, no match! 3If A's dimension equal to b's Match, if, and only if, b's base type is subtype of A's base type (Special case: if A's base type is Object then match, unless b's base type is primitive) 4If A's dimension less than b's Match, if, and only if, A's base type is Object
Catching Throwables Explicit throws try {... throw b;... } catch (A a) {... } Implicit throws: RuntimeExceptions null pointer, out-of-bounds, divide-by-zero, etc. JVM walks the stack looking for catch ( A ) to match throw ( b ) Both A and B extend Throwable Both are proper classes Proper class test b 's SID[A_depth] == A_typeId Works even if A is not (yet) loaded A_depth is 0, but A_typeId is not the type id of Object The test fails (as it should since B has been loaded)
Object Array Stores Array subtyping is problematic Vehicle [ ] X = makeVehicleArray(); Truck b = makeTruck(); X[0] = b; At compile time, Truck must be a Vehicle But, what if X is an array of Cars? At runtime, aastore throws an ArrayStoreException Short-circuit: array type = declared array type ? If X is Vehicle[], the compile-time test was sufficient! Declared type may be recoverable from bytecodes
Object Array Stores II Vehicle [ ] X = makeVehicleArray(); Truck b = makeTruck(); X[0] = b; A is runtime element type of X Not known at compile time Acquire from Element Type TIB (ETT) slot 1Type equality short-circuit Compare TIB of b and ETT from X 2Proper-class short-circuit (1-D array of proper classes) Get the VM_Type for A from X 's ETT Get A 's type id and depth from its VM_Type A_typeId == b 's SID[A_depth] ?
Element Type TIB ETT is the TIB for the elements of an array null for non arrays Number of subscripts is dimension of type 0 for proper objects, -1 for primitives Truck[] VMTVMT TIB for Truck[] 1 VM_Type for Truck[] TIB for Truck VMTVMT dimension
Basic Optimizations of Dynamic Type Checking Constant ( null ) propagation (JIT compile time) (A) null always succeeds (null instanceof A) == false Type propagation idioms (JIT compile time) Aggressive inlining uncovers opportunities Reaching definition B b = new A();... (A) b similarly for instanceof and invokeinterface Redundant checkcast elimination if (b instanceof A) {... (A) b... }
Basic Optimizations of Dynamic Type Checking Short-circuit tests (runtime) b is null A == B (type equality test) Definitive, if A is A final proper class An array* of primitive An array* of a final proper class
Experimental Evaluation Implemented three dynamic type checking schemes in Jalapeño 1Prior Jalapeño: out-of-line type equality, cache last success 2Inline TE/Cache: inlined type equality and type cache check to approximate technique described in [Ishizaki et al.'00] inline TE/Cache check for instanceof and checkcast 3New Jalapeño All three include same basic optimizations 4final classes & null handled inline 5null and type propagation 6compile time folding of instanceof & checkcast Experimental setup 7AIX/PowerPC, 1 processor 604e with 768MB 8Jalapeño adaptive system 9copying, nongenerational garbage collector
Performance Impact of Dynamic Type Checking
Space Considerations Data Structures (per Type costs) 1Superclass ID Display: expected 7 (or 4) words (when depth < 6) 2Implements Trits Vector: ƒClass does not implement any interfaces, 1 word ƒOtherwise 4 words + Max(min ITV, largest interface ID implemented trits) 3Element Type TIB: 1 word No data structures for aastore declared type short-circuit Code costs highly variable 4Which sequences are inlined? 5Where the sequences are inlined (be selective based on profiling)? 6Some sequences are both definitive and smaller than calls to runtime cType equality test in restricted cases dProper subclass using SID eA few array cases
Conclusions Superclass Id Display (SID) Resolves proper class tests (normal case) Usually, in four instructions Padded to avoid array bounds checks Implements Trits Vector (ITV) Resolves interface implementation tests 3-valued to accommodate dynamic class loading Element Type TIB (ETT) Resolves some common object-array-store tests Short-circuit for object-array-store test ( aastore ) Does runtime array type = declared array type? Declared type may be recoverable from bytecodes Resolves large fraction of object-array-store tests Exploit compile-time knowledge to customize dynamic type checking
Related Work Single inheritance dynamic type checking Superclass display's in Oberon [Cohen '91] Padded to 8 elements [Pfister, et. al. '91] Imposed a maximum inheritance depth on Oberon Multiple inheritance dynamic type checking boolean TypeCheck [*, *] array TypeCheck[B_id, A_id] iff B is a subtype of A Space inefficient Subset type tests A set of small integers is associated with each type B is a subtype of A iff B_set A_set Set coloring algorithm [Krall, et. al. '97] Produces space-efficient TypeCheck array Dynamic class loading may require recomputation Jalapeño implementation by Litvinov, no longer supported Caching schemes Cache most recent success [Ishizaki et. al.'00]