Section Notes 10/22/2003

 

Layout of Objects

 

Goal of an object data structure in memory:

  • data values for member variables
  • pointers to method code
  • pointer to class object (stores static data information)

 

Objects are stored in memory as two tables:

  • A per-instance table with the object attributes with a link to
  • A per-class table which contains static class attributes and a method dispatch table

 

Class Foo {

     int x;

 

     getX()  { … }

     print() { … }

}

 

Class Bar extends Foo {

     int y;

 

     // override print()

     print() { … }

 

     // new method draw()

     draw()  { … }

}

 

 

Things to note about the object’s dispatch table:

  • What happens when an overridden method is called with a pointer of a super class?
    • Foo f = new Bar(); f.print();

 

Because the offset of the method pointers are the same for the subclasses as the super classes, the code that we generate for the method call can stay the same.

  • We can only extend (or add) fields and methods to a subclass.
  • What happens if the semantic checker doesn’t check for down-casting (casting a super class to an arbitrary subclass?)
    • Potentially using entry that doesn’t exist in the dispatch table
  • What would the code for a method invocation look like? What would we need to pass to a method invocation?
    • Every method has to implicitly receive a pointer to the instance of the object for which the method was called. Otherwise, there would be no way for the method to know which object it is operating on.

 

Code Generation for Short Circuit Evaluation

 

(from notes for cs536 in Univ. Wisconsin)

 

How would we write cgen for Boolean expressions that are used in control flow?

 

One way:

1.        Generate code for evaluation of Boolean expression, and store to the top of the stack.

2.        Pop off top of stack, and see what the value is, and jump either to the true/false label.

 

Problems with this approach?

  • Inefficient, we can generate code that uses the results of the evaluation directly
  • What about short-circuit operators? Not all of the and expression is evaluated:
    • In (f() && g()), g() is not evaluated if f() is false

 

Introduce a new method: condGen(trueLabel, falseLabel)

  • condGen will generate code for evaluating the expression AND jumping to the correct true/false label at the same time.
    • How does this solve the above problems?

 

How does this work? Consider an if-then-else statement:

 

Old Method:

 

< evaluate condition, leaving the value on the stack>

 

pop value into T0

if T0 == false goto falseLabel

 

< code for “then” branch >

goto endLabel

 

falseLabel:

< code for “else” branch >

 

endLabel:

 

New Method:

 

< evaluate condition – if true, jump to trueLabel, else jump to falseLabel >

 

trueLabel:

< code for “then” branch >

goto endLabel

 

falseLabel:

< code for “else” branch >

 

endLabel:

 

 

  • So what would condGen look like for ‘e1 && e2’?

 

Let’s see how we would write the condGen for ‘&&’ operator:

 

We are given the trueLabel1 and falseLabel1 from the arguments to condGen. These are the labels outside the block of code we are generating that we want to jump to if the result is true, or false respectively.

 

Start with two new labels, trueLabel2, falseLabel2, representing where inner calls to condGen should go when they are evaluated:

 

trueLabel2:

jmp end

 

falseLabel2:

end:

 

Now we need to add in code for evaluating e1 by recursively calling condGen on e1. Note that if e1 evaluates to false, then we can simply jump out of the block of code we are generating to falseLabel1. If e1 evaluates to true, then we need to evaluate e2. If e2 evaluates to false, then again we jump to falseLabel1 on the outside. If e2 evaluates to true, then we can jump to trueLabel1, because both e1 and e2 are true. Finally, we note that the rest of the code generated will never be reached, and we can eliminate it:

 

< code generated by e1.condGen(trueLabel2, falseLabel1) >

trueLabel2:

< code generated by e2.condGen(trueLabel1, falseLabel1) >

 

jmp end

falseLabel2:

end: