Implementing Object-Oriented Languages - 2 Y.N. Srikant Computer Science and Automation Indian Institute of Science Bangalore 560 012 NPTEL Course on Principles of Compiler Design
Outline of the Lecture n Language requirements (in part 1) n Mapping names to methods (in part 1) n Variable name visibility n Code generation for methods n Simple optimizations n Parts of this lecture are based on the book, Engineering a Compiler, by Keith Cooper and Linda Torczon, Morgan Kaufmann, 2004, sections 6.3.3 and 7.10. Y.N. Srikant 2
Example of Class Hierarchy with Complete Method Tables n: 0 fee fum fum... three two fee... n: 1 fee fum foe fee... foe... one n: 2 fee fum foe fie fee... fie... c x: 5 y: 3 x: 2 y: 0 z: a object method x: 5 y: 3 z: b Y.N. Srikant 3
Mapping Names to Methods n Method invocations are not always static calls n a.fee() invokes one.fee(), a.foe() invokes two.foe(), and a.fum() invokes three.fum() n Conceptually, method lookup behaves as if it performs a search for each procedure call These are called virtual calls Search for the method in the receiver s ; if it fails, move up to the receiver s super, and further To make this search efficient, an implementation places a complete method table in each Or, a to the method table is included (virtual tbl ptr) Y.N. Srikant 4
Rules for Variable Name Visibility n Invoking b.fee() allows fee() to access all of b s instance variables (x,y,z), (since fee and b are both declared by one), and also all variables of es one, two, and three n However, invoking b.foe() allows foe() access only to instance variables x and y of b (not z), since foe() is declared by two, and b by one foe() can also access variables of es two and three, but not variables of one Y.N. Srikant 5
Code Generation for Methods n Methods can access any data member of any object that becomes its receiver receiver - every object that can find the method subject to hierarchy restrictions n Compiler must establish an offset for each data member that applies uniformly to every receiver n The compiler constructs these offsets as it processes the declarations for a Objects contain no code, only data Y.N. Srikant 6
Single Class, No Inheritance Example: method offset Class giant { 0 %giant.new_ int fee() {...} int fie() {...} int foe() {...} int fum() {...} static n; 4 8 12 16 20 %giant.fee_ %giant.fie_ %giant.foe_ %giant.fum_ 2 x y 13 14 15 16 x y fred object layout int x,y; } giant record joe object layout Y.N. Srikant 7
Implementing Single Inheritance sc ptr super ptr %new_ methods... variables %new_ %fee_ %fum_ 1 mc giant ptr x: 15 x: 5 jack %new_ %fee_ %foe_ 1 object x: 5 y: 6 goose %new_ %fee_ %fie_ 2 variables x: 13 { y: 14 z: 20 joe y: 16 z: 30 fred Y.N. Srikant 8
Single Inheritance Object Layout sc data members mc data members giant data members n Now, an instance variable has the same offset in every where it exists up in its super n Method tables also follow a similar sequence as above n When a redefines a method defined in one of its superes the method for that method implementation must be stored at the same offset as the previous implementation of that method in the superes Y.N. Srikant 9
Single Inheritance Object Layout (Complete Method Tables) Object layout for joe/fred (giant) record for giant sc data members super mc data members sc data members (x) %new_ giant data members mc data members (y) %fee_ %fum_ giant data members (z) %foe_ %fie_ 2 Object layout for goose (mc) sc data members (x) mc data members (y) record for mc super %new_ %fee_ %fum_ %foe_ 1 Object layout for jack (sc) sc data members (x) record for sc super %new_ %fee_ %fum_ 1 Y.N. Srikant 10
Single Inheritance Object Layout (including only changed and extra methods) Object layout for joe/fred (giant) record for giant sc data members mc data members sc data members (x) super %new_ giant data members mc data members (y) %fee_ giant data members (z) %fie_ 2 Object layout for goose (mc) record for mc sc data members (x) super %new_ mc data members (y) %fee_ %foe_ 1 Object layout for jack (sc) sc data members (x) record for sc super %new_ %fee_ %fum_ 1 Y.N. Srikant 11
Fast Type Inclusion Tests The need n n n If Y is a sub of X X a = new Y(); //a is of type base of Y, okay // other code omitted Y b = a; // a holds a value of type Y The above assignment is valid, but stmt 2 below is not 1. X a = new X(); // other code omitted 2. Y b = a; // a holds a value of type X Runtime type checking to verify the above is needed Java has an explicit instanceof test that requires a runtime type checking Y.N. Srikant 12
Fast Type Inclusion Tests Searching the Class Hierarchy Graph n Store the hierarchy graph in memory n Search and check if one node is an ancestor of another n Traversal is straight forward to implement only for single inheritance n Cumbersome and slow for multiple inheritance n Execution time increases with depth of hierarchy Y.N. Srikant 13
Class Hierarchy Graph - Example Single inheritance A Multiple inheritance A H B C B C D E F D E F G G Y.N. Srikant 14
Fast Type Inclusion Tests Binary Matrix Class types C1 C2 C3 C4 C5 Class types C1 C2 C3 C4 C5 0 1 0 0 1 0 0 1 0 1 1 0 0 1 0 1 0 0 0 1 0 0 1 0 0 Tests are efficient, but Matrix will be large in practice. The matrix can be compacted, but this increases access time. This can handle multiple inheritance also. BM [C i, C j ] = 1, iff C i is a sub of C j Y.N. Srikant 15
Relative (Schubert s) Numbering { l a, r a } for a node a : r a is the ordinal number of the node a in a postorder traversal of the tree. Let denote subtype of relation. All descendants of a node are subtypes of that node. is reflexive and transitive. l a = min { r p p is a descendant of a }. Now, a b, iff l b < r a < r b. This test is very fast and is O(1). Works only for single inheritance. Extensions to handle multiple inheritance are complex. D {1,1} {1,2} {1,7} A B {3,4} E G {3,3} C {3,6} F {5,5} Y.N. Srikant 16
Devirtualization Class Hierarchy Analysis n Reduces the overhead of virtual method invocation n Statically determines which virtual method calls resolve to a single method n Such calls are either inlined or replaced by static calls n Builds a hierarchy and a call graph Y.N. Srikant 17
Class Hierarchy Analysis object X extends object { void f1() {...} void f2() {...} } Y extends X { void f1() {...} } Z extends X { void f1() {...} public static void main(...) { X a = new X(); Y b = new Y(); Z c = new Z(); if (...) a = c; // other code a.f1(); b.f1(); b.f2(); } } Y f1() X f1(), f2() Z.main() Z f1() a.f1() b.f1() b.f2() X.f1 Y.f1 Z.f1 X.f2 Y.N. Srikant 18
Global Register Allocation - 1 Y N Srikant Computer Science and Automation Indian Institute of Science Bangalore 560012 NPTEL Course on Principles of Compiler Design
Outline n Issues in Global Register Allocation n The Problem n Register Allocation based on Usage Counts n Linear Scan Register allocation n Chaitin s graph colouring based algorithm Y.N. Srikant 20
Some Issues in Register Allocation n Which values in a program reside in registers? (register allocation) n In which register? (register assignment) The two together are usually loosely referred to as register allocation n What is the unit at the level of which register allocation is done? Typical units are basic blocks, functions and regions. RA within basic blocks is called local RA The other two are known as global RA Global RA requires much more time than local RA Y.N. Srikant 21
Some Issues in Register Allocation n Phase ordering between register allocation and instruction scheduling Performing RA first restricts movement of code during scheduling not recommended Scheduling instructions first cannot handle spill code introduced during RA n Requires another pass of scheduling n Tradeoff between speed and quality of allocation In some cases, e.g., in Just-In-Time compilation, cannot afford to spend too much time in register allocation Only local or both local and global allocation? Y.N. Srikant 22
The Problem n Global Register Allocation assumes that allocation is done beyond basic blocks and usually at function level n Decision problem related to register allocation : Given an intermediate language program represented as a control flow graph and a number k, is there an assignment of registers to program variables such that no conflicting variables are assigned the same register, no extra loads or stores are introduced, and at most k registers are used? n This problem has been shown to be NP-hard (Sethi 1970). n Graph colouring is the most popular heuristic used. n However, there are simpler algorithms as well Y.N. Srikant 23