Implementation
IMPLEMENTATION
Muhammad Adil Raja
Roaming Researchers, Inc.
cbna
April 24, 2015
Implementation
OUTLINE I
1 INTRODUCTION
2 REFERENCES
Implementation
Introduction
INTRODUCTION
Topics covered in this chapter include:
Compilers vs Interpreters.
The Receiver as Argument.
Inherited Methods.
The problem of Multiple Inheritance.
Overridden Methods.
Name Encoding.
Dispatch Tables.
Bytecode Interpreters.
Just in Time Compilation.
Implementation
Introduction
INSPIRATION
Design patterns speed the process of finding a solution, by
eliminating the need to reinvent well-known and proven
solutions.
Just as important, design patterns provide a vocabulary
with which to discuss the space of possible design choices.
This vocabulary is termed a pattern language.
Implementation
Introduction
TWO GENERAL APPROACHES TO IMPLEMENTATION
Compilers - translated into basic machine code, source
code not available at run-time, generally very efficient.
Interpreters - translated into intermediate representation,
source code available for reference at run-time, generally
somewhat less efficient.
Endpoints are clear, but there are lots of grey areas in the
middle.
Java JIT systems are one of those grey areas between
compilers and interpreters.
Implementation
Introduction
A method is eventually invoked just like any other function.
This means that the receiver just be passed as an
argument.
Traditionally, it is passed as the first argument.
This means a method call, such as
aCardPile->addCard (currentCard)
Is translated into
addCard (aCardPile, currentCard)
(This is ignoring the method lookup process, which we will
discuss shortly).
Implementation
Introduction
On the other side, the receiver pseudo-variable is just a
formal argument:
Instead of
EXAMPLE
void CardPile : : addCard ( Card ∗ aCard ) {
. . .
}
We have:
void CardPile : : addCard ( Card ∗ aCard ) {
. . .
}
The first argument can then be used to access data members
and other methods.
Implementation
Introduction
NO-VIRTUAL METHODS
In languages that permit both virtual and non-virtual
methods (such as C++) a non-virtual method is translated
into a simple procedure call.
The receiver is made into the first argument.
The name is encoded to make it unique.
Implementation
Introduction
NAME ENCODING
Different classes are allowed to have functions with the
same name.
Some languages (C++) even permit multiple functions with
the same name within a class.
Yet linkers usually want every function to have a unique
name.
Solution - generate an internal name that encodes both
class name, function name, and argument types.
Example: Foo::Bar_int_float_int
An encoded name is sometimes called a mangled name.
You will sometimes see mangled names in error messages
generated by a linker.
Implementation
Introduction
INHERITED METHODS I
Now consider those methods defined in a parent class, but
used by a child class.
How is it that this mechanism can work?
Normally you cannot change the types of arguments (recall
that the receiver is just an argument).
Solution is that the data associated with an instance of a
child class is an extension of the data associated with the
parent class.
This means that data fields in the parent class will be found
at the same offset in the child class.
Implementation
Introduction
INHERITED METHODS II
FIGURE : Inherited methods.
Implementation
Introduction
A PROBLEM WITH MULTIPLE INHERITANCE
The idea that a child is an extension of the parent explains
one of the most vexing problems in the implementation of
multiple inheritance.
A child can extend one parent, or the other, but not both.
That is the offset of data fields in the child cannot
simultaneously match both parents.
FIGURE : A problem with multiple inheritance.
Implementation
Introduction
SLICING PROBLEM
The idea that a child can extend the data area of the parent
also makes it difficult to support both the following goals.
The goal of keeping memory on the stack, which is laid out
at compile time
The goal of supporting the polymorphic variable, which can
hold an instance of the child class at run time.
Most OO languages uphold (2) and abandon (1), C++ is an
exception in that it upholds (1) and therefore abandons (2).
Implementation
Introduction
OVERRIDEN METHODS
We next consider those methods that are defined in a
parent class, and overridden in a child class.
Problem, how can a polymorphic method invocation find
the right method?
Note that the right method can change during the course of
execution, even for the same method call.
EXAMPLE
CardPile ∗ aCardPile = new DiscardPile ( ) ;
Card ∗ aCard = . . . ;
aCardPile−>addCard ( aCard ) ; / / how to f i n d the r i g h t method
Implementation
Introduction
SOLUTION – A VIRTUAL METHOD
The solution is that every object contains an extra hidden
data field.
This data field points to an array of pointers to functions.
The array is determined by the current dynamic type, and
is shared by all instances of the class.
The offset of each method can be determined at compile
time.
FIGURE : Solution.
Implementation
Introduction
INSTANCES SHARE THE SAME VIRTUAL METHOD
Two instances of a class will share the same virtual
method table.
FIGURE : Example.
Implementation
Introduction
METHOD CALLS BECOME INDEXED OFFSETS
Each object maintains a pointer to a table, called the virtual
method table.
Virtual methods are identified by a fixed address in this
table.
A method call, such as:
A.foo(B, C)
is translated into
(* A.virTable[idx])(A, B, C)
Implementation
Introduction
BUILDING A VIRTUAL TABLE FOR A SUBCLASS
When a subclass is created, a new virtual method table is
generated.
Methods that are inherited point to the same function as
the parent class. (and are found in the same offset in the
virtual method table).
Methods that are overridden occupy the same offset
location, but point to the new function, instead of the
version in the parent class.
FIGURE : Virtual table.
Implementation
Introduction
VIRTUAL METHOD TABLE FOR SUBCLASSES
FIGURE : Virtual method table.
Implementation
Introduction
ELIMINATION OF VIRTUAL CALLS
Even though the overhead of a virtual call is small, it can
still add up.
If the (dynamic) class of the receiver is know, a virtual call
can simply become an ordinary procedure call.
Good optimizing compiles spend a considerable amount of
time tracing possible execution flows to gather this
information.
Sometimes methods can even be expanded in-line at the
point of call.
Implementation
Introduction
DISPATCH TABLES
In languages without static typing it is not practical to use a
virtual table, since such a table would need to encode all
methods, not simply those in a given class hierarchy.
An alternative technique uses a pointer to a list of
selector/method pairs.
When a method is invoked, a run-time search is performed
to match the method being called with the list of known
selectors, until an appropriate method is found.
In Objective-C the messages. is translated into:
objc_msgSend(neighbor, “checkrow:column:”, row,
column)
Implementation
Introduction
AN OBJECT AND ITS DISPATCH TABLE
FIGURE : Dispatch table.
An important difference is that the dispatch table is
searched at run-time, not at compile time.
Objective-C uses a linear list for the table, Smalltalk
generally uses a balanced search tree, but the idea is
similar.
Implementation
Introduction
METHOD CACHE
In order to avoid the cost of a dynamic search of dispatch
tables, a single global cache can be used to hold
frequently invoked methods.
The cache is used as a large hash table.
Prior to searching a dispatch table, the a single hashed
entry is examined - if it matches the selector being sought,
the method is used, if not the dispatch table is searched
and the new entry replaces the value in the hash table.
Assuming a good hash function is used, efficiency can be
very high.
Implementation
Introduction
THE MESSAGING FUNCTION CHECKING THE CACHE
FIGURE : The messaging funciton checking the cache.
Implementation
Introduction
BYTECODE INTERPRETERS
An implementation technique that is widely used
(Smalltalk, Java)
Program is compiled into an “assembly language” for an
imaginary machine.
Since this assembly code is often represented by a string
of bytes, it is called bytecode.
Since the machine is imaginary, can run on any platform.
But it must be simulated (by a virtual machine) and hence
you pay an execution time cost.
Implementation
Introduction
BYTES IN LITTLE SMALLTALK SYSTEM
FIGURE : The bytes in little Smalltalk system.
Implementation
Introduction
JUST IN TIME COMPILERS
A currently popular mix between compilers and
interpreters.
Key idea, first time a method is executed, translate the
bytecode into native machine code.
Gives fast execution time, pay penalty for translation (and
analysis if you want to do a good job).
Currently very popular with Java systems.
Implementation
References
REFERENCES
Images and content for developing these slides have been
taken from the follwoing book with the permission of the
author.
An Introduction to Object Oriented Programming, Timothy
A. Budd.
This presentation is developed with Beamer:
JuanLesPins, spruce.

Implementation

  • 1.
    Implementation IMPLEMENTATION Muhammad Adil Raja RoamingResearchers, Inc. cbna April 24, 2015
  • 2.
  • 3.
    Implementation Introduction INTRODUCTION Topics covered inthis chapter include: Compilers vs Interpreters. The Receiver as Argument. Inherited Methods. The problem of Multiple Inheritance. Overridden Methods. Name Encoding. Dispatch Tables. Bytecode Interpreters. Just in Time Compilation.
  • 4.
    Implementation Introduction INSPIRATION Design patterns speedthe process of finding a solution, by eliminating the need to reinvent well-known and proven solutions. Just as important, design patterns provide a vocabulary with which to discuss the space of possible design choices. This vocabulary is termed a pattern language.
  • 5.
    Implementation Introduction TWO GENERAL APPROACHESTO IMPLEMENTATION Compilers - translated into basic machine code, source code not available at run-time, generally very efficient. Interpreters - translated into intermediate representation, source code available for reference at run-time, generally somewhat less efficient. Endpoints are clear, but there are lots of grey areas in the middle. Java JIT systems are one of those grey areas between compilers and interpreters.
  • 6.
    Implementation Introduction A method iseventually invoked just like any other function. This means that the receiver just be passed as an argument. Traditionally, it is passed as the first argument. This means a method call, such as aCardPile->addCard (currentCard) Is translated into addCard (aCardPile, currentCard) (This is ignoring the method lookup process, which we will discuss shortly).
  • 7.
    Implementation Introduction On the otherside, the receiver pseudo-variable is just a formal argument: Instead of EXAMPLE void CardPile : : addCard ( Card ∗ aCard ) { . . . } We have: void CardPile : : addCard ( Card ∗ aCard ) { . . . } The first argument can then be used to access data members and other methods.
  • 8.
    Implementation Introduction NO-VIRTUAL METHODS In languagesthat permit both virtual and non-virtual methods (such as C++) a non-virtual method is translated into a simple procedure call. The receiver is made into the first argument. The name is encoded to make it unique.
  • 9.
    Implementation Introduction NAME ENCODING Different classesare allowed to have functions with the same name. Some languages (C++) even permit multiple functions with the same name within a class. Yet linkers usually want every function to have a unique name. Solution - generate an internal name that encodes both class name, function name, and argument types. Example: Foo::Bar_int_float_int An encoded name is sometimes called a mangled name. You will sometimes see mangled names in error messages generated by a linker.
  • 10.
    Implementation Introduction INHERITED METHODS I Nowconsider those methods defined in a parent class, but used by a child class. How is it that this mechanism can work? Normally you cannot change the types of arguments (recall that the receiver is just an argument). Solution is that the data associated with an instance of a child class is an extension of the data associated with the parent class. This means that data fields in the parent class will be found at the same offset in the child class.
  • 11.
  • 12.
    Implementation Introduction A PROBLEM WITHMULTIPLE INHERITANCE The idea that a child is an extension of the parent explains one of the most vexing problems in the implementation of multiple inheritance. A child can extend one parent, or the other, but not both. That is the offset of data fields in the child cannot simultaneously match both parents. FIGURE : A problem with multiple inheritance.
  • 13.
    Implementation Introduction SLICING PROBLEM The ideathat a child can extend the data area of the parent also makes it difficult to support both the following goals. The goal of keeping memory on the stack, which is laid out at compile time The goal of supporting the polymorphic variable, which can hold an instance of the child class at run time. Most OO languages uphold (2) and abandon (1), C++ is an exception in that it upholds (1) and therefore abandons (2).
  • 14.
    Implementation Introduction OVERRIDEN METHODS We nextconsider those methods that are defined in a parent class, and overridden in a child class. Problem, how can a polymorphic method invocation find the right method? Note that the right method can change during the course of execution, even for the same method call. EXAMPLE CardPile ∗ aCardPile = new DiscardPile ( ) ; Card ∗ aCard = . . . ; aCardPile−>addCard ( aCard ) ; / / how to f i n d the r i g h t method
  • 15.
    Implementation Introduction SOLUTION – AVIRTUAL METHOD The solution is that every object contains an extra hidden data field. This data field points to an array of pointers to functions. The array is determined by the current dynamic type, and is shared by all instances of the class. The offset of each method can be determined at compile time. FIGURE : Solution.
  • 16.
    Implementation Introduction INSTANCES SHARE THESAME VIRTUAL METHOD Two instances of a class will share the same virtual method table. FIGURE : Example.
  • 17.
    Implementation Introduction METHOD CALLS BECOMEINDEXED OFFSETS Each object maintains a pointer to a table, called the virtual method table. Virtual methods are identified by a fixed address in this table. A method call, such as: A.foo(B, C) is translated into (* A.virTable[idx])(A, B, C)
  • 18.
    Implementation Introduction BUILDING A VIRTUALTABLE FOR A SUBCLASS When a subclass is created, a new virtual method table is generated. Methods that are inherited point to the same function as the parent class. (and are found in the same offset in the virtual method table). Methods that are overridden occupy the same offset location, but point to the new function, instead of the version in the parent class. FIGURE : Virtual table.
  • 19.
    Implementation Introduction VIRTUAL METHOD TABLEFOR SUBCLASSES FIGURE : Virtual method table.
  • 20.
    Implementation Introduction ELIMINATION OF VIRTUALCALLS Even though the overhead of a virtual call is small, it can still add up. If the (dynamic) class of the receiver is know, a virtual call can simply become an ordinary procedure call. Good optimizing compiles spend a considerable amount of time tracing possible execution flows to gather this information. Sometimes methods can even be expanded in-line at the point of call.
  • 21.
    Implementation Introduction DISPATCH TABLES In languageswithout static typing it is not practical to use a virtual table, since such a table would need to encode all methods, not simply those in a given class hierarchy. An alternative technique uses a pointer to a list of selector/method pairs. When a method is invoked, a run-time search is performed to match the method being called with the list of known selectors, until an appropriate method is found. In Objective-C the messages. is translated into: objc_msgSend(neighbor, “checkrow:column:”, row, column)
  • 22.
    Implementation Introduction AN OBJECT ANDITS DISPATCH TABLE FIGURE : Dispatch table. An important difference is that the dispatch table is searched at run-time, not at compile time. Objective-C uses a linear list for the table, Smalltalk generally uses a balanced search tree, but the idea is similar.
  • 23.
    Implementation Introduction METHOD CACHE In orderto avoid the cost of a dynamic search of dispatch tables, a single global cache can be used to hold frequently invoked methods. The cache is used as a large hash table. Prior to searching a dispatch table, the a single hashed entry is examined - if it matches the selector being sought, the method is used, if not the dispatch table is searched and the new entry replaces the value in the hash table. Assuming a good hash function is used, efficiency can be very high.
  • 24.
    Implementation Introduction THE MESSAGING FUNCTIONCHECKING THE CACHE FIGURE : The messaging funciton checking the cache.
  • 25.
    Implementation Introduction BYTECODE INTERPRETERS An implementationtechnique that is widely used (Smalltalk, Java) Program is compiled into an “assembly language” for an imaginary machine. Since this assembly code is often represented by a string of bytes, it is called bytecode. Since the machine is imaginary, can run on any platform. But it must be simulated (by a virtual machine) and hence you pay an execution time cost.
  • 26.
    Implementation Introduction BYTES IN LITTLESMALLTALK SYSTEM FIGURE : The bytes in little Smalltalk system.
  • 27.
    Implementation Introduction JUST IN TIMECOMPILERS A currently popular mix between compilers and interpreters. Key idea, first time a method is executed, translate the bytecode into native machine code. Gives fast execution time, pay penalty for translation (and analysis if you want to do a good job). Currently very popular with Java systems.
  • 28.
    Implementation References REFERENCES Images and contentfor developing these slides have been taken from the follwoing book with the permission of the author. An Introduction to Object Oriented Programming, Timothy A. Budd. This presentation is developed with Beamer: JuanLesPins, spruce.