Lecture 16 - Salisbury University
Download
Report
Transcript Lecture 16 - Salisbury University
CS 432: Compiler Construction
Lecture 16
Department of Computer Science
Salisbury University
Fall 2016
Instructor: Dr. Sophie Wang
http://faculty.salisbury.edu/~xswang
4/8/2017
1
Java Virtual Machine (JVM) Architecture
Java stack
Heap area
code for methods
constants pool
Native method stacks
4/8/2017
dynamically allocated
objects
automatic garbage
collection
Class area
runtime stack
support native methods,
e.g., written in C
(not shown)
2
Java Virtual Machine Architecture, cont’d
The runtime stack
contains stack frames.
Each stack frame
contains
4/8/2017
Stack frame =
activation record.
local variables array
operand stack
program counter
(PC)
3
The JVM’s Java Runtime Stack
Each method invocation pushes a stack frame.
The stack frame currently on top of the runtime stack is the
active stack frame.
A stack frame is popped off when the method returns,
possibly leaving behind a return value on top of the stack.
Contents of a stack frame:
Operand stack
Local variables array
4/8/2017
equivalent to the memory map in our
Pascal interpreter’s activation record
Program counter (PC)
for doing computations
keeps track of the currently executing instruction
Pointers to method area and heap
4
JVM Instructions
Load and store values
Arithmetic operations
Type conversions
Object creation and management
Runtime stack management (push/pop values)
Branching
Method call and return
Throwing exceptions
Concurrency
_
4/8/2017
5
JASMIN
JASMIN is an assembler for the JVM
Takes an ASCII description of a Java class
Input written in a simple assembler like syntax
Outputs binary class file
Suitable for loading by the JVM
Running JASMIN
Using the JVM instruction set
jasmin myfile.j
Produces a .class file with the name specified by the
.class directive in myfile.j
6
4/8/2017
Jasmin file format
Directives
Instructions
.catch .class .end .field .implements .interface
.limit .line .method .source .super .throws .var
JVM instructions
Labels
Any name followed by :
Foo:
7
4/8/2017
Cannot start with = : . *
Labels can only be used within method definitions
Jasmin Assembler
Download from:
http://jasmin.sourceforge.net/
Site also includes:
4/8/2017
User Guide
Instruction set
Sample programs
_
8
Example Jasmin Program
.class public HelloWorld
.super java/lang/Object
hello.j
.method public static main([Ljava/lang/String;)V
.limit stack 2
.limit locals 1
getstatic
java/lang/System/out Ljava/io/PrintStream;
ldc
" Hello World."
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
.end method
Assemble:
java –jar jasmin.jar hello.j
Execute:
4/8/2017
java HelloWorld
9
Jasmin Assembly Instructions
An Jasmin instruction consists of a mnemonic optionally
followed by arguments.
aload 5
fstore 5
; Push a reference to local variable #5
; pop off the floating-point value at the
; top of the stack and store it to
; local variable #5
getstatic Newton/number I
; push integer value of the static field
; number of class Newton to operand stack
Some instructions require operands on the operand
stack.
iadd
_
4/8/2017
; Pop the two integer values on top of the
; stack, add them, and push the result on
; the top of the stack
10
Jasmin Assembly Directives
Directive statements provide info to Jasmin assembler.
They begins with a period immediately followed by the
reserved directive word.
For example, the main method of a Java program
public static void main(String args[])
would have the following equivalent Jasmin directive
.method public static main([Ljava/lang/String;)V
4/8/2017
11
Jasmin Type Descriptors
Java Scalar type
4/8/2017
Jasmin Type Descriptor
int
I
float
F
boolean
Z
char
C
Java Class
Jasmin Type Descriptor
java.lang.String
Ljava/lang/String;
java.util.HashMap
Ljava/util/HashMap;
Newton
LNewton;
Java Array type
Jasmin Type Descriptor
java.lang.String[]
[Ljava/lang/String;
Newton[][]
[[LNewton;
int[][][]
[[[I;
12
Compilation Strategy
A Pascal program is compiled as if it were a
public Java class.
The Pascal program name becomes the Java class name.
The main program becomes the main method of the class.
Each program variable is compiled as if it were a
field of the class.
Fields do have names in a Jasmin program.
A Pascal procedure or function is compiled as if it were
a private static method of the Java class.
4/8/2017
Local variables and formal parameters of the method
do not have names in a Jasmin program.
Jasmin instructions refer to local variables and parameters by
their slot numbers of the local variables array.
13
Pascal, Java and Jasmin Code Example
1. PROGRAM HelloOnce;
2.
3. BEGIN
4.
writeln('Hello, world.')
5. END.
public class HelloOnce
{
private static RunTimer _runTimer;
private static PascalTextIn _standardIn;
public static void main(String[] args)
{
_runTimer = new RunTimer();
_standardIn = new PascalTextIn();
System.out.println("Hello, world.");
_runTimer.printElapsedTime();
}
14
4/8/2017
}
.class public helloonce
.super java/lang/Object
.field private static _runTimer LRunTimer;
.field private static _standardIn LPascalTextIn;
.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.limit locals 1
.limit stack 1
.end method
4/8/2017
.method public static main([Ljava/lang/String;)V
new RunTimer
dup
invokenonvirtual RunTimer/<init>()V
putstatic helloonce/_runTimer LRunTimer;
new PascalTextIn
dup
invokenonvirtual PascalTextIn/<init>()V
putstatic helloonce/_standardIn LPascalTextIn;
.line 4
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Hello, world.\n"
invokevirtual java/io/PrintStream.print(Ljava/lang/String;)V
getstatic helloonce/_runTimer LRunTimer;
invokevirtual RunTimer.printElapsedTime()V
return
.limit locals 1
.limit stack 3
.end method
15
Code Templates
Syntax diagrams
Specify the source language grammar
Help us write the parsers
Code templates
4/8/2017
Specify what object code to generate
Help us write the code emitters
_
16
Code Template for a Pascal Program
4/8/2017
Translate a Pascal
program into a
public class.
Program variables
become class fields.
Must have a
default constructor.
Each procedure or
function becomes a
private static method.
The main program
code becomes the
public static
main method.
17
Program Header
The program header consists of
.class public hellomany
.super java/lang/Object
4/8/2017
18
Class Constructor
The Pascal compiler always generates the same default constructor
<init>.
When the constructor executes, slot 0 of local variables array contains the
address of the class instance (this).
To create an instance of the program class, the ALOAD_0 instruction
pushes this address onto the operand stack and the instruction
invokenonvirtual passes it to the constructor of java.lang.Object
.method public <init>()V
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.limit locals 1
.limit stack 1
.end method
4/8/2017
19
Instruction-set …
Method invocation:
invokevirtual
usual instruction for calling a method on an object.
invokespecial/invokenonvirtual
for calling things such as constructors. These are not dynamically
dispatched
invokestatic
for calling methods that have the “static” modifier (these methods
“belong” to a class, rather an object)
20
invokevirtual
Object x;
...
x.equals("hello");
aload_1
ldc "hello"
; push local variable 1 (i.e. 'x') onto stack
; push the string "hello" onto stack
; invoke the equals method
invokevirtual java/lang/Object/equals(Ljava/lang/Object;)Z
; the boolean result is now on the stack
-the actual method run depends on the runtime type of the object invokevirtual is
used with.
-if x is an instance of a class that overrides Object's equal method, then the
subclasses' overridden version of the equals method will be used.
21
Invokespecial/invokenonvirtual
-invoke an object's instance initialization method, <init>, during the construction
phase for a new object.
new StringBuffer();
==
new java/lang/StringBuffer
; create a new StringBuffer
dup
; make an extra reference to the new instance
; now call an instance initialization method
invokespecial java/lang/StringBuffer/<init>()V
; stack now contains an initialized StringBuffer.
22
Invokespecial/invokenonvirtual
class Example { // override equals
public boolean equals(Object x) { // call Object's version of
// equals return
return super.equals(x);
}
}
-also used to access a superclass's version of a method.
return super.equals(x);
===
aload_0
aload_1
invokespecial
23
; push 'this' onto the stack
; push the first argument (i.e. x) onto the stack
; now invoke Object's equals() method.
java/lang/Object/equals(Ljava/lang/Object;)Z
Program Fields
For example:
PROGRAM test;
VAR
i, j, k :
x, y
:
p, q
:
ch
:
index
:
integer;
real;
boolean;
char;
1..10;
Pascal program variables
Compiles to:
.field
.field
.field
.field
.field
.field
.field
.field
.field
.field
.field
4/8/2017
private
private
private
private
private
private
private
private
private
private
private
static
static
static
static
static
static
static
static
static
static
static
_runTimer LRunTimer;
_standardIn LPascalTextIn;
ch C
i I
Classes RunTimer and PascalTextIn
index I
are defined in the Pascal Runtime Library
j I
PascalRTL.jar containing runtime routines
k I
written in Java.
p Z
q Z
x F
y F
24
Code Template for the Main Method
The main method
prologue initializes the
runtime timer
_runTimer and the
standard input
_standardIn fields.
The main method
epilogue prints the
elapsed run time.
4/8/2017
.limit locals
.limit stack
specify the size of the
local variables array
and the maximum
size of the operand
stack, respectively.
25
Loading a Program Variable’s Value
To load (push) a program variable’s value
onto the operand stack:
getstatic
program-name/variable-name type-descriptor
Examples:
getstatic
getstatic
Test/count I
Test/radius F
Java Scalar type
4/8/2017
Jasmin Type Descriptor
int
I
float
F
boolean
Z
char
C
26
Storing a Program Variable’s Value
To store (pop) a value from the operand stack
into program variable:
putstatic
program-name/variable-name type-descriptor
Examples:
putstatic
putstatic
Test/count I
Test/radius F
Java Scalar type
4/8/2017
Jasmin Type Descriptor
int
I
float
F
boolean
Z
char
C
27
Tips
Write special code emitters for loading (pushing) values
onto the operand stack.
If loading constants:
If loading variables,
Determine whether to you can emit a shortcut instruction.
Determine whether it’s a program variable
(emit a getstatic instruction with the field name)
or a local variable (emit a load instruction with the slot number).
Determine whether you can emit a shortcut instruction
for a local variable.
Similarly, write special code emitters for storing
(popping) values off the operand stack into variables.
4/8/2017
28
Code for Procedures and Functions
Each a private static method.
Method signature:
Routine’s name
Type descriptors of the
formal parameters.
Type descriptors of the return
type
4/8/2017
29
Compiling Local Variables
FUNCTION func(i, j : integer;
x, y : real;
p : boolean;
ch : char;
vector : arr;
length : integer)
: real;
VAR
n : integer;
z : real;
w : arr;
•
•
•
Compiles to:
.method private static func(IIFFZC[FI)F
.var 5 is ch C
.var 0 is i I
.var 1 is j I
.var 7 is length I
.var 8 is n I
.var 4 is p Z
.var 6 is vector [F
.var 10 is w [F
.var 2 is x F
.var 3 is y F
.var 9 is z F
.var 11 is func F
SymTabImpl - add a slot number to each variable’s the
symbol table entry for the local variables array.
DeclaredRoutineParser – parse()
VariableDeclarationParser – parseIdentifier()
4/8/2017
30
Generating Code for Expressions
alpha + 3/(beta - gamma) + 5
Recall that in our
Pascal interpreter,
the expression
executor does a
postorder traversal
of the expression
parse tree.
4/8/2017
Pascal’s operator
precedence rules
are encoded in the
structure of the
parse tree.
31
Generating Code for Expressions, cont’d
A compiler’s expression code generator also does a
postorder traversal to generate code.
Assume that alpha, beta, and gamma are local real variables
alpha local variable slot #0
beta local variable slot #1
gamma local variable slot #2
Generated code:
1
2
3
4
5
6
7
8
9
4/8/2017
fload_0
ldc 3.0
fload_1
fload_2
fsub
fdiv
fadd
ldc 5.0
fadd
alpha + 3/(beta - gamma) + 5
32
Comparing Integer Values
Jasmin has a set of instructions each of which
compares the top two integer values on the operand stack
and then branches if the comparison is true.
Instruction
Action
if_icmpeq label
Branch to label if [TOS-1] == [TOS]
if_icmpne label
Branch to label if [TOS-1] != [TOS]
if_icmpgt label
Branch to label if [TOS-1] > [TOS]
if_icmpge label
Branch to label if [TOS-1] >= [TOS]
if_icmplt label
Branch to label if [TOS-1] < [TOS]
if_icmple label
Branch to label if [TOS-1] <= [TOS]
The two values are popped off the operand stack.
4/8/2017
[TOS] is the value at the top of the stack.
[TOS-1] is the value just under the one at the top of the stack.
33
Comparing Integer Values, cont’d
You can also simply compare the single integer value
at the top of the operand stack to 0 and then branch if
the comparison is true.
Instruction
Action
ifeq label
Branch to label if [TOS] == 0
ifne label
Branch to label if [TOS] != 0
ifgt label
Branch to label if [TOS] > 0
ifge label
Branch to label if [TOS] >= 0
iflt label
Branch to label if [TOS1] < 0
ifle label
Branch to label if [TOS] <= 0
The top value is popped off the stack.
_
4/8/2017
34
Comparing Other Values
Instructions lcmp, fcmp, and dcmp compare two long,
float, or double values at the top of the operand stack.
Each pops the top two values off the operand stack and
then pushes the integer value -1, 0, or 1 onto the stack.
If [TOS-1] < [TOS], push -1 onto the stack.
If [TOS-1] = [TOS], push 0 onto the stack.
If [TOS-1] > [TOS], push 1 onto the stack.
Use instructions iflt, ifeq, or ifgt
to test for the -1, 0, or 1.
_
4/8/2017
35
Relational Expressions
Suppose i and j are local integer variables, and that:
i slot #0
j slot #1
0 represents false and
1 represents true.
For the expression i < j leave either 0 or 1
on top of the operand stack:
The code in red
are the only parts
that change based
on the expression.
4/8/2017
iload_0
iload_1
if_icmplt L003
iconst_0
goto L004
L003:
iconst_1
L004:
;
;
;
;
;
push the value of i (slot #0)
push the value of j (slot #1)
branch if i < j
push false
go to next statement
; push true
Your code generator
also needs to emit labels.
36
Relational Expression Code Template
iload_0
iload_1
if_icmplt L003
iconst_0
goto L004
L003:
iconst_1
L004:
4/8/2017
37
Assignment Statement Code Template
The code template for an assignment statement to a
local variable <variable> := <expression>
code for
<expression>
xstore
n
Where x is i, l, f, or d
depending on the type
of the computed value
of <expression>.
You can generate a shortcut store instruction such as
istore_3 (3 is a slot number) whenever possible.
_
4/8/2017
38
Pascal Procedures and Functions
Analogous to Java methods.
Two major simplifications for our Pascal compiler:
Standard Pascal is not object-oriented.
Java does not have nested methods.
4/8/2017
Therefore, Pascal procedures and functions are more like the
private static methods of a Java class.
The JVM does not easily implement nested methods.
Therefore, we will compile only “top level” (level 1)
Pascal procedures and functions.
_
39
Procedures and Functions, cont’d
A Pascal program:
The roughly equivalent Java class:
Fields and methods are
private static.
PROGRAM ADDER;
VAR
i, j, sum : integer;
FUNCTION add(n1, n2 : integer) : integer;
public class Adder
{
private static int i, j, sum;
private static int add(int n1, int n2)
{
int s = i + j + n1 + n2;
return s;
}
VAR
s : integer;
BEGIN
s := i + j + n1 + n2;
add := s;
END;
public static void main(String args[])
{
i = 10;
j = 20;
BEGIN
i := 10;
j := 20;
sum := add(100, 200);
writeln('Sum = ', sum)
END.
4/8/2017
sum = add(100, 200);
System.out.println("Sum = " + sum);
}
}
40
Code for a Pascal Main Program
PROGRAM ADDER;
.class public super Adder
.super java/lang/Object
VAR
i, j, sum : integer;
FUNCTION add(n1, n2 : integer) : integer;
VAR
s : integer;
.private field static i I
.private field static j I
.private field static sum I
.method public <init>()V
BEGIN
s := i + j + n1 + n2;
add := s;
END;
Private static
class fields.
Void method.
No parameters.
aload_0
invokenonvirtual java/lang/Object/<init>()V
return
.limit stack 1
.limit locals 1
.end method
BEGIN
i := 10;
j := 20;
...
sum := add(100, 200);
writeln('Sum = ', sum)
END.
Each Jasmin class must have a
constructor named <init>.
4/8/2017
The local variable in slot #0 contains the value of “this”.
Each constructor must call the superclass constructor.
41
Code for a Pascal Function
PROGRAM ADDER;
VAR
i, j, sum : integer;
FUNCTION add(n1, n2 : integer) : integer;
VAR
s : integer;
BEGIN
s := i + j + n1 + n2;
add := s;
END;
BEGIN
i := 10;
j := 20;
iload_2
ireturn
sum := add(100, 200);
writeln('Sum = ', sum)
END.
4/8/2017
.method static add(II)I
.var 0 is n1 I
.var 1 is n2 I
.var 2 is s I
.var 3 is add I
getstatic Adder/i I
getstatic Adder/j I
iadd
iload_0
; n1 (slot #0)
iadd
iload_1
; n2 (slot #1)
iadd
istore_2 ; s (slot #2)
; load s to stack top
; (see below)
.limit stack 2
.limit locals 3
.end method
getstatic with a fully qualified name and type to push the value
of a static field onto the operand stack.
ireturn pops an integer from the top of the callee’s stack and
pushes it onto the caller’s stack
42
Code to Call a Function (Static Method)
PROGRAM ADDER;
.method public static main([Ljava/lang/String;)V
.limit stack 4
.limit locals 1
VAR
i, j, sum : integer;
FUNCTION add(n1, n2 : integer) : integer;
bipush 10
putstatic Adder/i I
VAR
s : integer;
bipush 20
putstatic Adder/j I
BEGIN
s := i + j + n1 + n2;
add := s;
END;
bipush 100
sipush 200
invokestatic Adder/add(II)I
putstatic Adder/sum I
BEGIN
i := 10;
j := 20;
sum := add(100, 200);
writeln('Sum = ', sum)
END.
...
4/8/2017
A function call leaves its
return value on top of the
operand stack of the caller.
Use putstatic with a fully qualified field
name and type signature to pop a value off the
operand stack and store it into a static field.
Use invokestatic with a fully-qualified
method name and a type signature
to call a static method.
43
Code to Call a Function (Static Method)
PROGRAM ADDER;
.method public static main([Ljava/lang/String;)V
.limit stack 4
.limit locals 1
VAR
i, j, sum : integer;
FUNCTION add(n1, n2 : integer) : integer;
bipush 10
putstatic Adder/i I
VAR
s : integer;
bipush 20
putstatic Adder/j I
BEGIN
s := i + j + n1 + n2;
add := s;
END;
bipush 100
sipush 200
invokestatic Adder/add(II)I
putstatic Adder/sum I
BEGIN
i := 10;
j := 20;
sum := add(100, 200);
writeln('Sum = ', sum)
END.
...
4/8/2017
Use putstatic with a fully qualified field
name and type signature to pop a value off the
operand stack and store it into a static field.
Use invokestatic with a fully-qualified
method name and a type signature
to call a static method.
44
Code to Call System.out.println()
What does the method call
System.out.println("Hello, world!")
require on the operand stack?
A reference to the java.io.PrintStream object System.out.
A reference to the java.lang.String object "Hello, world!"
object
type descriptor of object
getstatic
java/lang/System/out Ljava/io/PrintStream;
ldc
"Hello, world!"
invokevirtual java/io/PrintStream.println(Ljava/lang/String;)V
method
parm type descriptor
no return type (void)
4/8/2017
45
System.out.println(), cont’d
Compile the Pascal call
writeln('Sum = ', sum)
as if it were the Java
System.out.println(
new StringBuilder(" Sum = ")
.append(sum)
.toString()
);
Each call to invokevirtual
requires an object reference
and then any required
actual parameter values
on the operand stack.
getstatic
java/lang/System/out
Ljava/io/PrintStream;
new
java/lang/StringBuilder
Why do we need this dup instruction?
dup
ldc "Sum = "
invokenonvirtual java/lang/StringBuilder/<init>(Ljava/lang/String;)V
getstatic
Adder/sum I
invokevirtual java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder;
invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
4/8/2017
46
A call to the static format() method of the Java String
class has two parameters, the format string and an array of
object values and it returns a string value
String.format(“The square root of %4d is %8.4f”, n, root)
would compile to the Jasmin instruction
invokestatic
java/lang/String/format(Ljava/lang/String;
[Ljava/lang/Object;)Ljava/lang/String;
This instruction requires that the address of the string constant “The square …. “ and the
address of the array containing the values of n, root be at the top of the operand stack.
It pops off the string and array addresses to be used as parameters of the call and the call
pushes the string value result onto the operand stack
4/8/2017
47
String.format()
A more elegant way to compile a call to Pascal’s standard
writeln() procedure is to use Java’s String.format() method.
Compile Pascal
writeln('The square root of ', n:4,
' is ', root:8:4);
as if it were the Java
System.out.print(
String.format(
"The square root of %4d is %8.4f\n",
n, root)
);
4/8/2017
48
String.format(), cont’d
The Java String.format() method has a
variable-length parameter list.
The first parameter is the format string.
Similar to C’s format strings for printf().
The code generator must construct the format string.
Pascal:
('The square root of ', n:4, ' is ', root:8:4)
Equivalent Java: ("The square root of %4d is %8.4f\n", n, root)
The remaining parameters are the values to be formatted, one for
each format specification in the format string.
4/8/2017
Jasmin passes these remaining parameters as a
one-dimensional array of objects.
Therefore, we must emit code to create and initialize the array
and leave its reference on the operand stack.
49
String.format(), cont’d
s = String.format(
"The square root of %4d is %8.4f\n",
n, root);
Instruction aastore
operands on the stack:
ldc
iconst_2
anewarray
dup
iconst_0
getstatic
invokestatic
aastore
dup
iconst_1
getstatic
invokestatic
aastore
invokestatic
putstatic
4/8/2017
Array reference
Index value
Element value
(object reference)
"The square root of %4d is %8.4f\n"
java/lang/Object
Create an array of size 2 and leave the
array reference on the operand stack.
FormatTest/n I
java/lang/Integer.valueOf(I)Ljava/lang/Integer;
Store element 0:
The value of n.
Why the dup
instructions?
FormatTest/root F
java/lang/Float.valueOf(F)Ljava/lang/Float;
Store element 1:
The value of root.
java/lang/String.format(Ljava/lang/String;[Ljava/lang/Object;)
Ljava/lang/String;
FormatTest/s Ljava/lang/String;
50
String.format(), cont’d
System.out.print(
String.format("The square root of %4d is 8.4f\n",
n, root);
);
getstatic
java/lang/System/out Ljava/io/PrintStream;
ldc
"The square root of %4d is %8.4f\n"
iconst_2
anewarray
java/lang/Object
dup
iconst_0
getstatic
FormatTest/n I
invokestatic java/lang/Integer.valueOf(I)Ljava/lang/Integer;
aastore
dup
iconst_1
getstatic
FormatTest/root F
invokestatic java/lang/Float.valueOf(F)Ljava/lang/Float;
aastore
invokestatic java/lang/String.format(Ljava/lang/String;
[Ljava/lang/Object;)Ljava/lang/String;
invokevirtual java/io/PrintStream.print(Ljava/lang/String;)V
4/8/2017
51
Parameter Passing
Java (and Jasmin) always passes parameters by value.
For scalar data type, they are passed by value.
For structured data types (string, array, object), their address
are passed by value (hence indirectly by reference)
Strategies for compiling Pascal parameter passing
4/8/2017
If a parameter is scalar (integer, real, bool, subrange, enum)
without VAR, follow default rule for Java parameter passing.
If a parameter is structured data type with VAR, follow default
rule for Java parameter passing.
If a parameter is scalar (integer, real, bool, subrange, enum)
with VAR, convert this into a wrapper class object.
If a parameter is structured data type without VAR, we create a
clone of the parameter object and pass the clone at the actual
parameter
_
52
Passing Parameters
Pascal can pass parameters
by value and by reference.
VAR parameters =
pass by reference
Java and Jasmin
pass scalar values by value.
To pass a scalar value by
reference, you must first wrap
the value inside an object.
4/8/2017
Pass the object reference
(by value) to the routine.
The routine can modify the
wrapped value.
Upon return, the caller must
unwrap the changed value.
_
53
Passing Parameters, cont’d
Java and Jasmin pass
references to objects
by value.
When a formal parameter to a method
is a reference to an object, the method can
change the value of the object (such as by
modifying the values of the object fields).
But the method cannot change the
parameter’s value to refer to another object
and have the method’s caller see that change.
4/8/2017
To pass an array or record
by value as in Pascal,
first clone the array or
record value and then
pass the reference
to the clone.
54
Passing Parameters, cont’d
The Pascal Runtime Library contains classes for
passing parameters by value or by reference.
Classes BWrap, CWrap, IWrap, and RWrap wrap a boolean,
character, integer, and real scalar value, respectively, to be
passed by reference.
Class Cloner clones
an array or reference
to be passed by value.
public class IWrap
{
public int value;
public IWrap(int value)
{
this.value = value;
}
_
4/8/2017
}
55
Example: Passing Scalars by Reference
PROGRAM parmswrap;
.method public static main([Ljava/lang/String;)V
...
VAR
new
IWrap
Wrap i.
i, j : integer;
dup
getstatic
parmswrap/i I
PROCEDURE swap(VAR parm1, parm2
invokenonvirtual IWrap/<init>(I)V
: integer);
dup
Allocate slots #1 and #2
VAR
astore_1
as temporaries to store the
temp : integer;
new
IWrap
Wrap
j.
wrapped i and j.
dup
BEGIN
getstatic
parmswrap/j I
temp := parm1;
invokenonvirtual IWrap/<init>(I)V
parm1 := parm2;
dup
parm2 := temp;
astore_2
Call method.
END;
invokestatic parmswrap/swap(LIWrap;LIWrap;)V
BEGIN
i := 10;
aload_1
j := 20;
getfield
IWrap/value I
Unwrap i.
swap(i, j);
putstatic
parmswrap/i I
writeln('Result: i = ', i:0,
aload_2
', j = ', j:0);
getfield
IWrap/value I
Unwrap j.
END.
putstatic
parmswrap/j I
4/8/2017
56
Example: Passing Scalars by Reference, cont’d
PROGRAM parmswrap;
.method private static swap(LIWrap;LIWrap;)V
VAR
i, j : integer;
#0
#1
PROCEDURE swap(VAR parm1, parm2
: integer);
VAR
#2 temp : integer;
BEGIN
temp := parm1;
parm1 := parm2;
parm2 := temp;
END;
BEGIN
i := 10;
j := 20;
swap(i, j);
writeln('Result: i = ', i:0,
', j = ', j:0);
END.
4/8/2017
.var 2 is temp I
.var 0 is parm1 LIWrap;
.var 1 is parm2 LIWrap;
aload_0
getfield
istore_2
IWrap/value I
Access the wrapped values of
aload_0 parm1 and parm2 and swap them.
aload_1
getfield IWrap/value I
putfield IWrap/value I
aload_1
iload_2
putfield
IWrap/value I
return
.limit locals 3
.limit stack 2
.end method
57
Example: Passing an Array by Value
PROGRAM parmsclone;
TYPE
cube = ARRAY [0..1, 0..2, 0..3] OF integer;
VAR
vvv : cube;
PROCEDURE printCube(VAR c : cube);
...
PROCEDURE doCubeValue(c : cube);
VAR
i, j, k : integer;
4/8/2017
BEGIN
doCubeRef(vvv);
writeln('In main:');
printCube(vvv);
BEGIN
FOR i := 0 TO 1 DO BEGIN
FOR j := 0 TO 2 DO BEGIN
FOR k := 0 TO 3 DO BEGIN
c[i,j][k] := 200*i + 10*j +k;
END;
END;
getstatic
END;
invokestatic
writeln('In doCubeValue:');
printCube(c);
END;
PROCEDURE doCubeRef(VAR c : cube);
...
BEGIN
...
c[i,j][k] := 100*i + 10*j +k;
...
END;
checkcast
invokestatic
doCubeValue(vvv);
writeln('In main:');
printCube(vvv);
END.
parmsclone/vvv [[[I
Cloner.deepClone(Ljava/lang/Object;)
Ljava/lang/Object;
[[[I
parmsclone/docubevalue([[[I)V
58
Class Cloner
In the Pascal Runtime Library:
public class Cloner
{
public static Object deepClone(Object original)
throws PascalRuntimeException
{
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); Write the original
object to a byte
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(original);
array stream.
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
Construct a copy
from the stream.
Return the copy as the deep clone.
}
catch (Exception ex) {
throw new PascalRuntimeException("Deep clone failed.");
}
}
}
4/8/2017
59
Arrays and Subscripted Variables
Code generation for arrays:
Allocate memory for single-dimensional arrays
Code to allocate memory for an array variable.
Code to allocate memory for each non-scalar array element.
Code for a subscripted variable in an expression.
Code for a subscripted variable that is an assignment target.
Instruction newarray for scalar elements.
Instruction anewarray for non-scalar elements.
Allocate memory for multidimensional arrays.
4/8/2017
Instruction multianewarray.
_
60
Allocating Memory for Arrays
Recall the code template for
a Jasmin method.
Code to allocate arrays here!
Pascal automatically allocates
memory for arrays declared in
the main program or locally in a
procedure or function.
The memory allocation occurs
whenever the routine is called.
This is separate from
dynamically allocated data
Therefore, our generated Jasmin code
using pointers and new.
must implement this automatic runtime behavior.
4/8/2017
61
Example: Allocate Memory for Scalar Arrays
PROGRAM ArrayTest;
TYPE
vector = ARRAY[0..9] OF integer;
matrix = ARRAY[0..4, 0..4] OF integer;
cube
= ARRAY[0..1, 0..2, 0..3] OF integer;
VAR
i, j, k, n : integer;
a1
: vector;
a2
: matrix;
a3
: cube;
BEGIN
...
END.
4/8/2017
bipush
10
newarray int
putstatic
arraytest/a1 [I
iconst_5
iconst_5
multianewarray
putstatic
[[I 2
arraytest/a2 [[I
iconst_2
iconst_3
iconst_4
multianewarray
putstatic
[[[I 3
arraytest/a3 [[[I
62
Access an Array Element of a 2-D Array
PROGRAM ArrayTest;
a2
TYPE
matrix = ARRAY[0..2, 0..3]
OF integer;
0
0
VAR
i, j, k : integer;
a2
: matrix;
1
BEGIN
...
i := 1;
j := 2;
k := a2[i, j];
...
END.
k
1
2
3
1
2
3
4
5
6
7
8
2
9 10 11 12
1
2
3
4
5
6
7
8
7
getstatic
getstatic
aaload
getstatic
iaload
putstatic
arraytest/a2 [[I
arraytest/i I
arraytest/j I
arraytest/k I
9 10 11 12
4/8/2017
63
Subscripted Variables in Expressions
PROGRAM ArrayTest;
TYPE
vector = ARRAY[0..9] OF integer;
matrix = ARRAY[0..4, 0..4] OF integer;
cube
= ARRAY[0..1, 0..2, 0..3] OF integer;
VAR
i, j, k, n : integer;
a1
: vector;
a2
: matrix;
a3
: cube;
BEGIN
...
j := a1[i];
k := a2[i, j];
n := a3[i, j, k];
...
END.
getstatic
getstatic
iaload
putstatic
arraytest/a1 [I
arraytest/i I
getstatic
getstatic
aaload
getstatic
iaload
putstatic
arraytest/a2 [[I
arraytest/i I
getstatic
getstatic
aaload
getstatic
aaload
getstatic
iaload
putstatic
arraytest/a3 [[[I
arraytest/i I
arraytest/j I
arraytest/j I
arraytest/k I
arraytest/j I
arraytest/k I
arraytest/n I
Instructions iaload (push a scalar value from an array element value)
and aaload (push an array element address)
4/8/2017
64
Set an Array Element of a 2-D Array
PROGRAM ArrayTest;
a2
TYPE
matrix = ARRAY[0..2, 0..3]
OF integer;
0
0
VAR
i, j, k : integer;
a2
: matrix;
1
BEGIN
...
i := 1;
j := 2;
k := 0;
a2[i, j] := k;
...
END.
k
1
2
3
1
2
3
4
5
6
7
0
8
2
9 10 11 12
1
2
3
4
5
6
7
8
0
getstatic
getstatic
aaload
getstatic
getstatic
iastore
arraytest/a2 [[I
arraytest/i I
arraytest/j I
arraytest/k I
9 10 11 12
4/8/2017
65
Subscripted Variables as Assignment Targets
PROGRAM ArrayTest;
TYPE
vector = ARRAY[0..9] OF integer;
matrix = ARRAY[0..4, 0..4] OF integer;
cube
= ARRAY[0..1, 0..2, 0..3] OF integer;
VAR
i, j, k, n : integer;
a1
: vector;
a2
: matrix;
a3
: cube;
BEGIN
...
a1[i] := j;
a2[i, j] := k;
a3[i, j, k] := n;
...
END.
getstatic
getstatic
getstatic
iastore
arraytest/a1 [I
arraytest/i I
arraytest/j I
getstatic
getstatic
aaload
getstatic
getstatic
iastore
arraytest/a2 [[I
arraytest/i I
getstatic
getstatic
aaload
getstatic
aaload
getstatic
getstatic
iastore
arraytest/a3 [[[I
arraytest/i I
arraytest/j I
arraytest/k I
arraytest/j I
arraytest/k I
arraytest/n I
Instructions iastore (pop and store a scalar value
into an array element) and aaload (push an array element address)
4/8/2017
66
More Subscripted Variables
PROGRAM ArrayTest;
TYPE
vector = ARRAY[0..9] OF integer;
matrix = ARRAY[0..4, 0..4] OF integer;
cube
= ARRAY[0..1, 0..2, 0..3] OF integer;
VAR
i, j, k, n : integer;
a1
: vector;
a2
: matrix;
a3
: cube;
BEGIN
...
a3[i][a1[j]][k] := a2[i][j] - a3[k, 2*n][k+1];
...
END.
Instruction aaload pushes the
address of one dimension of an array.
Instruction iaload pushes the
integer value of an array element.
4/8/2017
getstatic
getstatic
aaload
getstatic
getstatic
iaload
aaload
getstatic
arraytest/a3 [[[I
arraytest/i I
arraytest/a1 [I
arraytest/j I
arraytest/k I
getstatic arraytest/a2 [[I
getstatic arraytest/i I
aaload
getstatic arraytest/j I
iaload
getstatic
getstatic
aaload
iconst_2
getstatic
imul
aaload
getstatic
iconst_1
iadd
iaload
isub
iastore
arraytest/a3 [[[I
arraytest/k I
arraytest/n I
arraytest/k I
What’s on the
stack after this
instruction? 67
Allocate Memory for Non-Scalar Arrays
For a non-scalar array, we must generate code to :
Allocate memory for the array itself.
4/8/2017
Similar to a scalar array, except that each element
will contain a reference to its data.
Allocate memory for the data of each array element
and initialize each element.
_
68
Allocate Memory for a 1-D String Array
PROGRAM AllocArrayTest2;
TYPE
string = ARRAY[1..5] OF char;
vector = ARRAY[0..9] OF string;
a1
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
VAR
a1 : vector;
BEGIN
END.
Each array element
should contain a
reference to a
string object.
_
4/8/2017
69
Memory for a 1-D String Array, con’d
PROGRAM AllocArrayTest2;
a1
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
TYPE
string = ARRAY[1..5] OF char;
vector = ARRAY[0..9] OF string;
VAR
a1 : vector;
bipush
anewarray
BEGIN
END.
10
java/lang/StringBuilder
iconst_0
istore_1
Allocate slot #1
as the temporary
variable i.
L001:
iload_1
bipush
if_icmpge
Like the Java code:
for (int i = 0; i < 10; ++i)
{
a1[i] =
PaddedString.create(5);
}
PaddedString is a
class in the Pascal
Runtime Library.
10
L002
dup
What are we duplicating?
iload_1
iconst_5
invokestatic PaddedString.create(I)
Ljava/lang/StringBuilder;
aastore
iinc
goto
1 1
L001
L002:
4/8/2017
putstatic
allocarraytest2/a1
[Ljava/lang/StringBuilder;
70
Code Template: 1-D Non-Scalar Array
bipush
10
anewarray
java/lang/StringBuilder
iconst_0
istore_1
L001:
iload_1
bipush
10
if_icmpge
dup
iload_1
L002
iconst_5
invokestatic
PaddedString.create(I)Ljava/lang/StringBuilder;
aastore
iinc 1 1
goto L001
L002:
putstatic
4/8/2017
allocarraytest2/a1 [Ljava/lang/StringBuilder;
71
Allocate Memory for a 2-D String Array
a2
PROGRAM AllocArrayTest2;
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
TYPE
string = ARRAY[1..5] OF char;
matrix = ARRAY[0..2, 0..3] OF string;
VAR
a2 : matrix;
BEGIN
END.
4/8/2017
72
Memory for a 2-D String Array, cont’d
iconst_3
iconst_4
multianewarray
PROGRAM AllocArrayTest2;
TYPE
string = ARRAY[1..5] OF char;
matrix = ARRAY[0..2, 0..3] OF string;
VAR
a2 : matrix;
BEGIN
END.
Allocate slots #1
and #2 as the
temporary
variables
i and j.
4/8/2017
iconst_0
istore_1
"
"
iload_1
iconst_3
if_icmpge
"
"
"
"
"
"
L003:
L004
dup
iload_1
aaload
a2
iconst_0
istore_2
ditto
iload_2
iconst_4
if_icmpge
ditto
L005:
Like the Java code:
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 4; ++j)
{
a2[i][j] =
PaddedString.create(5);
}
}
[[Ljava/lang/StringBuilder; 2
L006
dup
iload_2
iconst_5
invokestatic
aastore
iinc
goto
2 1
L005
pop
iinc
goto
1 1
L003
PaddedString.create(I)Ljava/lang/StringBuilder;
L006:
L004:
putstatic
allocarraytest2/a2 [[Ljava/lang/StringBuilder;
73
Code Template:
n-D Non-Scalar Array
iconst_5
iconst_4
multianewarray
[[Ljava/lang/StringBuilder; 2
iconst_0
istore_1
L003:
iload_1
iconst_3
if_icmpge
L004
dup
iload_1
aaload
iconst_0
istore_2
L005:
iload_2
iconst_4
if_icmpge
L006
dup
iload_2
iconst_5
invokestatic
aastore
iinc
goto
2 1
L005
pop
iinc
goto
1 1
L003
PaddedString.create(I)Ljava/lang/StringBuilder;
L006:
4/8/2017
L004:
putstatic
74
allocarraytest2/a2 [[Ljava/lang/StringBuilder;
Records and Fields
Recall the code template for
a Jasmin method.
Code to allocate records here!
Implement the value of each
Pascal record variable as a
java.util.HashMap object.
4/8/2017
Keys: Field names (as strings)
Values: Field values (as objects)
_
75
Pascal Records in the JVM
Each record value is a
separate hash table.
Keys: field names
Values: field values
PROGRAM RecordTest2;
TYPE
String16 =
ARRAY [1..16] OF char;
PersonRec =
RECORD
firstName : String16;
age
: integer;
END;
VAR
john : PersonRec;
BEGIN
...
END.
4/8/2017
john
Allocate and initialize each value.
"age"
0
"firstname"
"
"
new java/util/HashMap
dup
invokenonvirtual java/util/HashMap/<init>()V
dup
ldc
"age"
Convert the int value 0 to an Integer object.
iconst_0
invokestatic
java/lang/Integer.valueOf(I)Ljava/lang/Integer;
invokevirtual java/util/HashMap.put(Ljava/lang/Object;
Ljava/lang/Object;)Ljava/lang/Object;
pop
Why pop?
dup
ldc
"firstname"
bipush 16
invokestatic
PaddedString.create(I)Ljava/lang/StringBuilder;
invokevirtual java/util/HashMap.put(Ljava/lang/Object;
Ljava/lang/Object;)Ljava/lang/Object;
pop
putstatic recordtest2/john Ljava/util/HashMap;
76
Set the Values of Record Fields
john
"age"
"firstname"
240
"
""
"John
"John"
""
PROGRAM RecordTest2;
TYPE
String16 = ARRAY [1..16]
OF char;
PersonRec = RECORD
firstName
: String16;
age
: integer;
END;
VAR
john : PersonRec;
age : integer;
BEGIN
john.age := 24;
john.firstName := 'John';
age := john.age;
END.
4/8/2017
getstatic
ldc
bipush
invokestatic
invokevirtual
recordtest2/john Ljava/util/HashMap;
"age"
24
java/lang/Integer.valueOf(I)Ljava/lang/Integer;
java/util/HashMap.put(Ljava/lang/Object;
Ljava/lang/Object;)Ljava/lang/Object;
pop
getstatic
ldc
invokevirtual
checkcast
dup
iconst_0
invokevirtual
ldc
invokevirtual
bipush
iconst_4
invokestatic
invokevirtual
recordtest2/john Ljava/util/HashMap;
"firstname"
java/util/HashMap.get(Ljava/lang/Object;)Ljava/lang/Object;
java/lang/StringBuilder
java/lang/StringBuilder.setLength(I)V
"John"
java/lang/StringBuilder.append(
Ljava/lang/String;)Ljava/lang/StringBuilder;
16
PaddedString.blanks(II)Ljava/lang/StringBuilder;
java/lang/StringBuilder.append(
Ljava/lang/CharSequence;)Ljava/lang/StringBuilder;
pop
77
Access Values of Record Fields
PROGRAM RecordTest2;
john
TYPE
String16 = ARRAY [1..16]
OF char;
PersonRec = RECORD
firstName
: String16;
age
: integer;
END;
VAR
john : PersonRec;
age : integer;
"age"
"firstname"
age
24
"John
"
24
getstatic
ldc
invokevirtual
checkcast
invokevirtual
putstatic
recordtest2/john Ljava/util/HashMap;
"age"
java/util/HashMap.get(Ljava/lang/Object;)
Ljava/lang/Object;
java/lang/Integer
java/lang/Integer.intValue()I
recordtest2/age I
BEGIN
john.age := 24;
john.firstName := 'John';
age := john.age;
END.
4/8/2017
78
IF Statement Code Templates
The code that evaluates the
boolean expression leaves
either 0 (false) or 1 (true) on
top of the operand stack.
4/8/2017
ifeq branches if [TOS] is 0
(the expression is false)
79
Example: IF Statement
getstatic
getstatic
if_icmplt
iconst_0
goto
PROGRAM IfTest;
VAR
i, j, t, f : integer;
iftest/i I
iftest/j I
L002
L003
L002:
BEGIN {IF statements}
...
IF i < j THEN t := 300;
iconst_1
L003:
ifeq
sipush
putstatic
L001
300
iftest/t I
getstatic
getstatic
if_icmpeq
iconst_0
goto
iftest/i I
iftest/j I
L005
L001:
IF i = j THEN t := 200
ELSE f := -200;
...
END.
L006
L005:
iconst_1
L006:
ifeq
sipush
putstatic
goto
L007
200
iftest/t I
L004
sipush
ineg
putstatic
200
L007:
iftest/f I
L004:
4/8/2017
80
Looping Statement Code Template
The code that
evaluates the
boolean expression
leaves either
0 (false) or 1 (true)
on top of the
operand stack.
4/8/2017
ifne branches if
[TOS] is not 0
(the expression
value is true)
There might not be
any code before or
after the test.
_
81
Example: Newton’s Square Root Function
#0
FUNCTION sqrt(x : real) : real;
VAR
#1
#2
i : integer;
root : real;
BEGIN
i := 0;
root := x;
REPEAT
root := (x/root + root)/2;
i := i + 1;
UNTIL i > 10;
sqrt := root;
END;
4/8/2017
iconst_0
istore_1
; i := 0
fload_0
fstore_2
; root := x
L000:
fload_0
; x
fload_2
; root
fdiv
; /
fload_2
; root
fadd
; +
fconst_2
; 2.0
fdiv
; /
fstore_2
; ==> root
iinc 1 1
; i := i + 1;
iload_1
; i
bipush 10 ; 10
if_icmpgt L001 ; if i > 10 goto L001
iconst_0
; false
goto L002
L001:
iconst_1
; true
L002:
ifne L001 ; if true goto L003
goto L000
L003:
fload_2
82
freturn
; return root
Example: FOR Statement
PROGRAM ForTest;
VAR
j, k, n : integer;
fortest/j I
fortest/k I
getstatic
iconst_5
if_icmpgt
iconst_0
goto
L004
fortest/k I
L001:
BEGIN {FOR statements}
...
FOR k := j TO 5 DO BEGIN
n := k;
END;
getstatic
putstatic
L003:
iconst_1
L004:
ifne
...
END.
Remember that program variables
are translated into Jasmin static fields,
and so they have names, not slot numbers.
L002
L003
This is code
emitted for a
general > test.
It can be
improved!
getstatic
putstatic
fortest/k I
fortest/n I
getstatic
iconst_1
iadd
putstatic
goto
L001
fortest/k I
fortest/k I
L002:
4/8/2017
83
SELECT Statement
4/8/2017
84
Example: CASE Statement
#0
#1
VAR i, j : integer;
...
CASE i OF
100,105:
j := 1000;
200,256,282: j := 2000;
END
4/8/2017
iload_0
; i
lookupswitch
100: L010
105: L010
200: L020
256: L020
282: L020
default: L099
L010:
sipush 1000
istore_1 ; j := 1000
goto L099
L020:
sipush 2000
istore_1 ; j := 2000
goto L099
L099:
85
Using Java
Because your compilers will generate .class files to run
on the Java Virtual Machine (JVM) …
You can write Java classes whose methods invoke methods in
your compiled code.
Your compiled code can invoke methods in classes that you
write in Java.
4/8/2017
Create a runtime library.
Example: You invent a new source language with statements that
do regular expression searches on strings. You can write the RE
algorithms in Java and call them from your compiled code.
86
The Pascal Runtime Library
Useful utility classes written in Java that contain methods your
compiled Jasmin code can call.
Create an archive file PascalRTL.jar.
Some utility classes:
PascalTextIn
RunTimer
Error exception thrown while executing compiled code.
PaddedString
4/8/2017
Perform runtime range checking.
PascalRuntimeException
Time the execution of compiled programs and print the elapsed run time.
RangeChecker
Runtime text input based on the scanner.
Pascal string implementation with blank-padding
87
The Pascal Runtime Library, cont’d
The Pascal Runtime Library can
reuse some classes from the front end.
When a Pascal program calls the standard procedure read
to input values at run time, read must scan the input text
for values of various data types (integer, real, string, etc.).
Therefore, reuse the scanner and token classes
by including them in the library.
Include the runtime library on your class path
when you run your compiled program.
java –cp .;PascalRTL.jar ...
Your generated code can call routines in the library.
4/8/2017
88
The Pascal Runtime Library, cont’d
Cloner.class
PaddedString.class
PascalRuntimeException.class
PascalTextIn.class
RangeChecker.class
RunTimer.class
BWrap.class
CWrap.class
IWrap.class
RWrap.class
4/8/2017
89
The Pascal Runtime Library, cont’d
wci/frontend/EofToken.class
wci/frontend/Scanner.class
wci/frontend/Source.class
wci/frontend/Token.class
wci/frontend/TokenType.class
wci/frontend/pascal/PascalScanner.class
wci/frontend/pascal/PascalToken.class
wci/frontend/pascal/PascalTokenType.class
wci/frontend/pascal/tokens/PascalErrorToken.class
wci/frontend/pascal/tokens/PascalNumberToken.class
wci/frontend/pascal/tokens/PascalSpecialSymbolToken.class
wci/frontend/pascal/tokens/PascalStringToken.class
wci/frontend/pascal/tokens/PascalWordToken.class
wci/message/Message.class
wci/message/MessageHandler.class
wci/message/MessageListener.class
wci/message/MessageProducer.class
wci/message/MessageType.class
4/8/2017
90