Compiler Design
105601Module 6: Advanced Topics
Q1i. Dynamic method dispatch is primarily used to implement: (i) Lexical analysis (ii) Constant folding (iii) Runtime polymorphism (iv) Register allocation20262m
Module 6: Advanced Topics
View this question on its own page →Dynamic method dispatch is primarily used to implement:
(i) Lexical analysis
(ii) Constant folding
(iii) Runtime polymorphism
(iv) Register allocationWorked SolutionAnswer: (iii) Runtime polymorphism
Explanation
Dynamic method dispatch selects which overridden method to call based on the actual (run-time) type of the object, not the declared type of the reference.
Compilers implement it with a virtual method table (vtable): each object carries a hidden pointer to its class's vtable, and a virtual call becomes an indirect call through a fixed slot index.
Animal a = new Dog(); a.speak(); // Dog.speak() is chosen at run timeThis is exactly runtime (dynamic) polymorphism. It has nothing to do with lexical analysis, constant folding or register allocation.
Q8a. Discuss the major challenges involved in compiling object-oriented features such as classes, inheritance, and polymorphism.20267m
Module 6: Advanced Topics
View this question on its own page →Discuss the major challenges involved in compiling object-oriented features such as classes, inheritance, and polymorphism.
Worked SolutionCompiling object-oriented features: main challenges
Object-oriented languages add classes, objects, inheritance and polymorphism on top of ordinary procedural features. The compiler must map these to plain memory layouts and jumps.
MermaidDiagramRendering diagram…1. Object layout (classes)
An object is stored as a record of its fields, plus a hidden pointer to its class's method table. The compiler must compute field offsets and the total size.
SVGVector Architecture Diagram (SVG)2. Inheritance
- A subclass object must be usable wherever a superclass object is expected, so the inherited fields keep the same offsets as in the parent (the subclass fields are appended).
- Multiple inheritance breaks this: an object has several parent parts, so the compiler needs several vptrs and must adjust the
thispointer when converting to a base type; shared (virtual) base classes need extra indirection. - Constructors and destructors must run in the right order (base first on construction, derived first on destruction).
3. Polymorphism and dynamic dispatch
The method that runs depends on the object's run-time type, not on the declared type. The compiler builds a virtual method table (vtable) for each class and compiles a virtual call as an indirect call through a fixed slot:
Slot Animal vtable Dog vtable 0 Animal::speak Dog::speak (overrides) A call
a.speak()is compiled to an indirect call through the vptr and the fixed slot ofspeak:MermaidDiagramRendering diagram…This costs an extra memory load and an indirect jump, and prevents simple inlining; optimizers use devirtualization (when the exact type is known) to recover speed.
4. Other challenges
Challenge Why it is hard Type checking with subtyping Assignments are legal from subclass to superclass; overriding rules (parameter and return types) must be checked Overloading and name mangling Several methods share a name; the compiler selects one by argument types and encodes the signature in the symbol name Access control private,protected,publicchecks at compile timethispointerPassed as a hidden first argument to every instance method Run-time type information Needed for casts, instanceof, exceptionsInterfaces and abstract classes Dispatch through interface tables; abstract methods have no body Memory management Allocation on heap, garbage collection or destructors Separate compilation Changing a base class's layout forces recompilation of all subclasses