Objects and Classes

advertisement
Objects and Classes
David Walker
CS 320
Advanced Languages
• advanced programming features
– ML data types, exceptions, modules, objects,
concurrency, ...
– fun to use, but require special techniques to
compile and optimize
– today will be looking at how to compile objects
and classes similar to those found in Java
• Appel chapter 14.1-14.4
Object Fun
• Add class declarations to Fun:
– classes are a collection of
• field (variable) declarations
• method declarations
– every class declaration gives a new name to a
class
– a class may inherit methods and fields from
the class it extends
– the class “object” sits at the top of the class
hierarchy; it has no fields and no methods
An Object Fun Class
class name
field
declaration
superclass that
Vehicle inherits from
let
class Vehicle extends Object {
var position := start
method move (x : int) = (position := position + x)
}
in ... end
method declaration
Another Object Fun Class
new field
declaration
let
class Vehicle extends Object {
var position := start
method move (x:int) = (position := position + x)
}
class Car extends Vehicle {
var passengers := 0
new method
declaration
method await(v:vehicle) =
if (v.position < position) then
v.move(position – v.position)
else
self.move(10)
call to inherited
v’s “position” field
method
current object’s “position” field
in ... end
Yet Another Object Fun Class
let
class Vehicle extends Object {
var position := start
method move (x:int) = position := position + x
}
class Car extends Vehicle { ... }
class Truck extends Vehicle {
method move (x:int) =
if x <= 55 then
position := position * x
in ... end
method override
Using the Classes
let
class Vehicle extends Object { ... }
class Car extends Vehicle { ... }
class Truck extends Vehicle {...}
a car calls
an inherited
method
var t := new Truck
var c := new Car
var v : Vehicle := c
in
c.passengers := 2;
c.move(60);
v.move(70);
c.await(t);
end
new object
created
subtyping allows a
car to be viewed and
used as a generic
vehicle
subtyping allows a
truck to be viewed and
used as a generic
vehicle
Implementing Object Fun
• Some key problems:
– how do we access object fields?
• both inherited fields and fields for the current object?
– how do we access method code?
• if the current class does not define a particular method,
where do we go to get the inherited method code?
• how do we handle method override?
– in both cases, when we generate code, we only know
the static type of the object, not the actual dynamic
type
Class Hierarchy
• The class hierarchy is the graph of inheritence
relationships in a program:
Object
Vehicle
Car
Truck
– In a single-inheritence (SI) language, the graph is a tree
– In a multiple-inheritence (MI) language, the graph is a dag
– Multiple-inheritence languages are much trickier to implement
than single-inheritence languages
Object Layout (SI)
• Objects are laid out somewhat like records
– each variable has a slot in the record
– in order to implement field lookup we need to
have a systematic way to find a given field
• eg: v.position
• v may be a generic vehicle or it may be a car or a
truck
• we need to put “position” in the same place in the
record that implements vehicles, cars and trucks
Object Layout (SI)
• Solution: extension on the right
– lay out the inherited fields first in the same
order as in the parent (SI => only 1 parent)
– lay out the newly declared to the right
Object Layout (SI)
class A extends Object { var a := 0 }
class B extends A
{ var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends B
{ var e := 0 }
Object Layout (SI)
class A extends Object { var a := 0 }
class B extends A
{ var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends B
{ var e := 0 }
A
a
Object Layout (SI)
class A extends Object { var a := 0 }
class B extends A
{ var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends B
{ var e := 0 }
A
B
a
a
b
c
Object Layout (SI)
class A extends Object { var a := 0 }
class B extends A
{ var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends B
{ var e := 0 }
A
B
C
a
a
a
b
d
c
Object Layout (SI)
class A extends Object { var a := 0 }
class B extends A
{ var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends B
{ var e := 0 }
A
B
C
D
a
a
a
a
b
d
b
c
c
e
Static & Dynamic Methods
• The result of compiling a method is some
machine code located at a particular
address
– at a method invocation point, we need to
figure out what code location to jump to
• Java has static & dynamic methods
– to resolve static method calls, we look at the
static type of the calling object
– to resolve dynamic method calls, we need the
dynamic type of the calling object
Static Methods
let
class A extends Object {
static method foo (x:int) = ...
static method bar (x:int) = ...
}
class B extends A {
static method foo (x:int) = ...
}
var a : A = new A
var b : A = new B
var c : B = new B
in
a.foo(3); (* calls foo in class A *)
b.foo(3); (* calls foo in class A *)
c.bar(3); (* calls bar in class A *)
c.foo(3); (* calls foo in class B *)
– during semantic analysis,
the compiler knows:
• static type (class) of the
object calling the method
• the list of methods in each
class
– and determines
• the closest method (up the
class hierarchy) with the
given name
– and inserts
• instructions to pass object
as self parameter
• a direct call to the known
method
Dynamic Methods
let
class A extends Object {
method foo (x:int) = ...
method bar (x:int) = ...
}
class B extends A {
method foo (x:int) = ...
}
var a : A = new A
var b : A = new B
var c : A =
if long-and-tricky-computation
then a
else b
in
c.foo(3)
– Method called depends
on object’s dynamic type
• During semantic analysis,
may be unknown
– At run-time, we determine
which code to jump to
• object stores a pointer to its
method table (v-table) as
well as its object vars
– At compile-time, we
generate code to
• look up v-table in object
• extract method from table
• jump to method body
Object Layout II (SI)
class A extends Object { var a := 0; method f () }
class B extends A
{ method g () }
class C extends B
{ method g () }
class D extends C
{ var b := 0 ; method f () }
Object Layout II (SI)
class A extends Object { var a := 0; method f () }
class B extends A
{ method g () }
class C extends B
{ method g () }
class D extends C
{ var b := 0 ; method f () }
A
a
A_f
Object Layout II (SI)
class A extends Object { var a := 0; method f () }
class B extends A
{ method g () }
class C extends B
{ method g () }
class D extends C
{ var b := 0 ; method f () }
A_f
A
B
a
a
A_f
B_g
Object Layout II (SI)
class A extends Object { var a := 0; method f () }
class B extends A
{ method g () }
class C extends B
{ method g () }
class D extends C
{ var b := 0 ; method f () }
A_f
A
B
C
a
a
a
A_f
A_f
B_g
C_g
Object Layout II (SI)
class A extends Object { var a := 0; method f () }
class B extends A
{ method g () }
class C extends B
{ method g () }
class D extends C
{ var b := 0 ; method f () }
A
B
C
D
a
a
a
a
b
A_f
A_f
A_f
D_f
B_g
C_g
C_g
Object Layout II (SI)
class A extends Object { var a := 0; method f () }
class B extends A
{ method g () }
class C extends B
{ method g () }
class D extends C
{ var b := 0 ; method f () }
A
B
C
D
a
a
a
a
b
A_f
D
A_f
A_f
D_f
a
B_g
C_g
C_g
b
Multiple Inheritence
• Multiple inheritence is trickier to implement
than single inheritence because creating
objects of a subclass from their subclass
by “extension on the right” doesn’t work
– if C inherits from both A and B, we can’t put
A’s variables at the front and put B’s variables
at the front of the object in the same place!
– we need to do a global analysis to determine
object layout
Object Layout (MI)
class A extends Object { var a := 0 }
class B extends Object { var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends A,B,C { var e := 0 }
A
B
a
C
D
a
a
b
b
c
c
d
d
e
Object Layout (MI)
class A extends Object { var a := 0 }
class B extends Object { var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends A,B,C { var e := 0 }
A
B
a
C
a
D
a
b
b
c
c
d
d
e
Determine object layout by:
• global graph coloring!
• a node for each field name
• an interference edge between
names that coexist in the same
class (via inheritence or
otherwise)
Object Layout (MI)
class A extends Object { var a := 0 }
class B extends Object { var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends A,B,C { var e := 0 }
A
B
a
C
D
a
a
b
b
c
c
wasted space in
every object
d
d
e
Object Layout II (MI)
class A extends Object { var a := 0 }
class B extends Object { var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends A,B,C { var e := 0 }
A
B
C
D
a
b
a
a
a:
1
d
b
b:
2
c
c:
3
d
d:
4
e
e:
5
a:
1
c
a:
1
a:
b:
1
2
d:
2
wasted space
per class
Object Layout II (MI)
class A extends Object { var a := 0 }
class B extends Object { var b := 0
var c := 0 }
class C extends A
{ var d := 0 }
class D extends A,B,C { var e := 0 }
A
B
a
b
c
a:
1
a:
b:
To fetch a field using this
representation, we:
• load the first field of the object
to get the class descriptor c
• load M [c + fieldOffset]
1
2
Note: fieldOffset can be
precomputed using global
graph coloring as before
A Problem
• Global analyses are the bane of modern
computing
– many applications use dynamically linked libraries,
mobile code, get patches to fix bugs, etc.
– when we don’t have the whole program at compiletime, we can’t do global analyses!
– solution (most of the time):
• a smart custom linker
• still tricky when new code is linked dynamically to code that is
already running
– hence, Java has single inheritence
Other OO Features
• Down-casts and type tests
– Java has casting mechanism “(C) x” to cast
variable x to class C
• at run time we look up x’s dynamic type and
determine whether it is a subtype of C
• these type casts are currently pervasive and a
source of both inefficiency and errors
• soon, Java and C# will be adding parametric
polymorphism, a la ML, to make many of these
unnecessary casts go away
Other OO Features
• Protection mechanisms
– to encapsulate local state within an object,
Java has “private” “protected” and “public”
qualifiers
• private methods/fields can’t be called/used outside
of the class in which they are defined
– during semantic analysis (type checking), the
compiler maintains this information in the
symbol table for each class
Summary
• Object-oriented languages provide new
challenges for compiler writers
– how to find fields and methods
– how to make field and method access just as
efficient as ordinary function call and variable
lookup
– lots of ongoing research in OO language
implementation tackles these and other
interesting questions
Download