Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15sp/lectures/lec24.pdf ·...
Transcript of Programming)Languages)) and)Techniques) (CIS120))cis120/archive/15sp/lectures/lec24.pdf ·...
Programming Languages and Techniques
(CIS120)
Lecture 24
March 20, 2015
The Java ASM
It was really frustra-ng when li2le issues made everything go wrong... tricky... it was hard Too many links... It's been long queues are kinda confusing and delete was hard delete yourself For some reason I found this assignment excep-onally difficult...I feel that there were many different ways that the problems could have been done, so it wasn't clear what the best method was or how to approach the problem. Everything I think of ends up in a loop now not as bad this -me Much more intuiKve than hw04, and much, much easier to test. We were warned by the TAs that the last homework (nbody) would be extremely -me consuming and that this one would be rela-vely light. However, I think the truth is exactly the opposite. The N-‐body homework was mostly about small details. This homework had many very big ideas that took a very long -me to consider. Easier as I got the hang of units. Drawing the queues out really helped! I was able to understand the ASM more aMer this homework the assignment itself was pre2y fun, but i'm s-ll not sure it helped me understand concepts from class like referen-al/structural equality and using the abstract stack machine really challenging and insighNul! was prePy cool to see the differences between java and ocaml linked lists and how funcKonal programming interacts with mutable state Solid work yo. Cool homework. bueno This one was fun. "Queue is just Q with 4 silent le2ers" -‐ Ron Swanson Q: What do you call a waiKng line of liPle girls' dolls? A: A Barbie-‐queue. Sums up my thoughts while doing this HW. The eureka moment was the best. Thank god for spring break
Homework 5 Feedback
Announcements • Homework 6 due tonight!
• Exam Wednesday – See topics on Monday's slides
– See logisKcs on Wednesday's slides
– Exam study material and room locaKons on course website
• CIS Course Faire: today, 4:30PM in Towne 100 – Covers all courses for academic year 2015-‐2016
The Java Abstract Stack Machine
Objects and Arrays in the heap
Java Abstract Stack Machine • Similar to OCaml Abstract Stack Machine
– Workspace • Contains the currently execuKng code
– Stack • Remembers the values of local variables and "what to do next" aMer funcKon/method calls
– Heap • Stores reference types: objects and arrays
• Key differences: – Everything, including stack slots, is mutable by default
– Objects store what class was used to create them
– Arrays store type informa-on and length
– New component: Class table (coming soon)
Heap Reference Values
Objects
• Name of the class that constructed it
• Values for all of the fields
class Node { private int elt; private Node next; …}
Arrays
• Type of values that it stores • Length • Values for all of the array
elements
int [] a = { 0, 0, 7, 0 };
Nodeelt 1
next null
fields marked final are not mutable, all others are. public/private is not tracked by ASM.
int[]length 4
0 0 7 0
length never mutable; elements always mutable
What does the following program print?
public class Node { public int elt; public Node next; public Node(int e0, Node n0) { elt = e0; next = n0; }}
public static void main(String[] args) {Node n1 = new Node(1,null);Node n2 = new Node(2,n1);Node n3 = n2;n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
System.out.println(n1.elt);}
Workspace Stack Heap
Node n1 = new Node(1,null);Node n2 = new Node(2,n1);Node n3 = n2;n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Workspace Stack Heap
Node n1 = ;Node n2 = new Node(2,n1);Node n3 = n2;n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next null
Note: we’re skipping details here about how the constructor works. For now, assume the constructor allocates and ini-alizes the object in one step.
Workspace Stack Heap
Node n2 = new Node(2,n1);Node n3 = n2;n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next null
n1
Workspace Stack Heap
Node n2 = ;Node n3 = n2;n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next null
n1
Nodeelt 2
next
Workspace Stack Heap
Node n3 = n2;n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next null
n1
Nodeelt 2
next
n2
Workspace Stack Heap
n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next null
n1
Nodeelt 2
next
n2
n3
Workspace Stack Heap
n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next null
n1
Nodeelt 2
next
n2
n3
Workspace Stack Heap
n3.next.next = n2;Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next
n1
Nodeelt 2
next
n2
n3
Workspace Stack Heap
Node n4 = new Node(4,n1.next);n2.next.elt = 9;
Nodeelt 1
next
n1
Nodeelt 2
next
n2
n3
Workspace Stack Heap
Node n4 = ;n2.next.elt = 9;
Nodeelt 1
next
n1
Nodeelt 2
next
n2
n3
Nodeelt 4
next
Workspace Stack Heap
n2.next.elt = 9; Nodeelt 1
next
n1
Nodeelt 2
next
n2
n3
Nodeelt 4
next
n4
Workspace Stack Heap
n2.next.elt = 9; Nodeelt 1
next
n1
Nodeelt 2
next
n2
n3
Nodeelt 4
next
n4
Workspace Stack Heap
n2.next.elt = 9; Nodeelt 9
next
n1
Nodeelt 2
next
n2
n3
Nodeelt 4
next
n4
In the OCaml ASM, bindings of variables to values in the stack are immutable, while in Java they are mutable (by default).
1. True2. False
In the Java ASM, large data structures such as object values are stored in the stack, not the heap
1. True2. False
A Java array can be resized by assigning a new value to its length field.
1. True2. False
The == operator in both OCaml and Java tests whether two values have idenKcal structure.
1. True2. False
In the OCaml ASM, first-‐class funcKons are stored in the heap, and may have local copies of variables that were on the stack when they were defined.
1. True2. False
The Java Abstract Stack Machine and the Class Table
1. When do constructors execute? 2. What code runs in a method call?
3. How are fields accessed in methods?
How do method calls work?
• What code gets run in a method invocaKon?
o.move(3,4);
• When that code is running, how does it access the fields of the object that invoked it?
x = x + dx;
• When does the code in a constructor get executed?
ASM refinement: The Class Table
public class Counter { private int x; public Counter () { x = 0; } public void incBy(int d) { x = x + d; } public int get() { return x; }}
Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
The class table contains: • The code for each method • The class’s staKc members (more later!) • Pointers to each class’s parent (more later!)
class C {private int f;
public int copyF(C other) {this.f = other.f;
}
public static void m () { C o1 = new C();
C o2 = new C(); o1.copy(o2); }}
this • Inside a non-‐staKc method, the variable "this" is a
reference to the object on which the method was invoked.
• References to local fields and methods have an implicit “this.” in front of them.
this Cf 0
Stack Heap
… …
…
An Example
public class Counter { private int x; public Counter () { x = 0; } public void incBy(int d) { x = x + d; } public int get() { return x; }}
// … somewhere in main:Counter d = new Counter();d.incBy(3);int x = d.get();
What does the following program print?
…with explicit this
public class Counter { private int x; public Counter () { this.x = 0; } public void incBy(int d) { this.x = this.x + d; } public int get() { return this.x; }}
// … somewhere in main:Counter d = new Counter();d.incBy(3);int x = d.get();
ConstrucKng an Object Workspace Stack Heap
Counter d = new Counter();d.incBy();int x = d.get();
Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Invoking a constructor: • allocates space for a new object in the heap
• slots for fields (here: x) • the class that created the object (here: Counter)
• runs the constructor body aMer saving workspace and pushing parameters and this onto the stack
Counterx 0
Reminder: fields start with a “sensible” default -‐ 0 for numeric values -‐ null for references
ConstrucKng an ObjectWorkspace Stack Heap
this.x = 0;
Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Counter d = _;d.incBy(3);int x = d.get();
this
Reminder: fields start with a “sensible” default -‐ 0 for numeric values -‐ null for references
Invoking a constructor: • allocates space for a new object in the heap
• slots for fields (here: x) • the class that created the object (here: Counter)
• runs the constructor body aMer saving workspace and pushing parameters and this onto the stack
Assigning to a Field Workspace Stack Heap
this.x = 0;
Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Counter d = _;d.decBy(3);int x = d.get();
this
Assignment into the this.x field goes in two steps: -‐ look up the value of this in the stack -‐ write to the “x” slot of that object.
Assigning to a Field Workspace Stack Heap
.x = 0;
Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Counter d = _;d.incBy(3);int x = d.get();
this
Assignment into the this.x field goes in two steps: -‐ look up the value of this in the stack -‐ write to the “x” slot of that object.
Done with the call Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Counter d = _;d.incBy(3);int x = d.get();
this
;
Done with the call to the Counter constructor, so pop the stack and return to the saved workspace, returning the newly allocated object (now in the this pointer).
POP!
Allocate a stack slot for the local variable d. Note that it’s mutable… (bold box in the diagram).
Aside: since, by default, fields and local variables are mutable, we oMen omit the bold boxes and just assume the contents can be modified.
Returning the Newly Constructed Object Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
ConKnue execuKng the program.
Counter d = ;d.incBy(2);int x = d.get();
AllocaKng a local variable Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Decrx 0
Allocate a stack slot for the local variable d. Note that it’s mutable… (bold box in the diagram).
Aside: since, by default, fields and local variables are mutable, we oMen omit the bold boxes and just assume the contents can be modified.
d.incBy(3);int x = d.get();
d
d
Dynamic Dispatch: Finding the Code Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Invoke the incBy method on the object. The code is found by looking up the class in the class table.
This process is called dynamic dispatch: Which code is run depends on the dynamic class of the object in the heap. (In this case, Counter.) More later.
.incBy(3);int x = d.get();
d
Dynamic Dispatch: Finding the Code Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Call the method, remembering the current workspace and pushing the this pointer and any arguments.
this.x = this.x + d;
_;int x = d.get();
this
d 3
d
Reading A Field’s Contents Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Read from the x slot of the object.
this.x = this.x + d;
_;int x = d.get();
this
d 3
d
Reading a local variable Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Read from the x slot of the object.
this.x = 0 + d;
_;int x = d.get();
this
d 3
d
AddiKon Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Read from the x slot of the object.
this.x = 0 + 3;
_;int x = d.get();
this
d 3
d
WriKng to a field Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 0
Use the "this" reference to find the object with the field to be updated.
this.x = 3;
_;int x = d.get();
this
d 3
d
WriKng to a field Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 3
;
_;int x = d.get();
this
d 3
POP! Remove the method parameters and this reference from the stack Restore the workspace
d
AMer the method returns…Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Counterx 3
int x = d.get();
Now use dynamic dispatch to invoke the get method for d.
d
AMer yet a few more steps…Workspace Stack Heap Class Table
Counterextends Object
Counter() { x = 0; }
void incBy(int d){…}
int get() {return x;}
ObjectString toString(){…
boolean equals…
…
Decrx 3
;
Done! (Phew!)
x 3
Summary: this and dynamic dispatch • When object’s method is invoked, as in o.m(), the code that
runs is determined by o’s dynamic class. – The dynamic class, represented as a pointer into the class table, is
included in the object structure in the heap
• Once the code for m has been determined, a binding for this is pushed onto the stack. – The this pointer is used to resolve field accesses and method
invocaKons inside the code.
StaKc members & Java ASM
StaKc Members • Classes in Java can act as containers for code and data. • The modifier static means that the field or method is
associated with the class and not instances of the class.
public class C { public static int x = 23; public static int someMethod(int y) { return C.x + y; } public static void main(String args[]) {
… }}
C.x = C.x + 1;C.someMethod(17);
Access to the staKc member uses the class name C.x or C.foo()
You can do a staKc assignment to iniKalize a staKc field.
Class Table Associated with C• The class table entry for
C has a field slot for x. • Updates to C.x modify
the contents of this slot: C.x = 17;
• A staKc field is a global variable – There is only one heap locaKon for it (in the class table) – ModificaKons to such a field are globally visible (if the field is public)
– Generally not a good idea!
Cextends Object static x 23static int someMethod(int y) { return x + y; }static void main(String args[]) {…}
StaKc Methods (Details)
• StaKc methods called directly from class table – Don't need an object to invoke them. Easy for ASM to find the method
body.
• StaKc methods do not have access to the this pointer – Why? There isn’t an instance to dispatch through. – Therefore, staKc methods may only directly call other staKc methods. – Similarly, staKc methods can only directly read/write staKc fields. – Of course a staKc method can create instance of objects (via new) and
then invoke methods on those objects.
• Gotcha: It is possible (but confusing) to invoke a staKc method as though it belongs to an object instance. – e.g. o.someMethod(17) where someMethod is staKc – Eclipse will issue a warning if you try to do this.