Read section 10.3 (pg 214)
To invoke a static method, push all of the arguments onto the stack, then execute:
invokestatic METHOD ; <c b a...> -> <d...> where d = METHOD(a, b, c)
Here METHOD is the fully qualified signature of the method to be invoked:
PACKAGE/CLASS/METHOD(PARAM TYPES)TYPE
After this instruction the return value should be on top of the stack.
Executing this instruction pops the arguments off the stack, creates a new stack frame, pushes the arguments onto that stack, and sets the PC to the first instruction of the method.
The following instruction sequence computes Math.sin(pi/4) where pi = 3.1416:
ldc2_w 3.1416
ldc2_w 4.0
ddiv
invokestatic java/lang/Math/sin(D)D
Recall the definition of the static factorial function (n!) given in Functions.java.
The following instruction sequence loads Functions.fact(4) into locals[0]:
ldc 4
invokestatic Functions/fact(I)I
istore 0
Pushing a field onto the stack is done with
getfield Class/Field Type
getstatic Class/Fieeld Type
Storing the top of the stack into a field is done with
putfield Class/Field Type
putstatic Class/Field Type
To invoke a non-static method, push the object that invokes the method onto the stack (this) along with any other explicit arguments, then execute:
invokevirtual METHOD ;<c b a...> -> <d...> where d = a.METHOD(b, c)
After this instruction the return value should be on top of the stack.
Executing this instruction pops the arguments off the stack, creates a new stack frame, pushes the arguments onto that stack, and sets the PC to the first instruction of the method.
The Java method invocation:
System.out.println("Hello World!");
is translated into Jasmin as:
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "Hello World!"
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
The Java method invocation:
Math.sin(Math.PI/4);
is translated into Jasmin as:
getstatic java/lang/Math/PI D
ldc2_w 4.0
ddiv
invokestatic java/lang/Math/sin(D)D
Recall the temperature conversion calculator defined in Calculator.java.
The following sequence assumes a reference to a Calculator object is stored in locals[1] After the call the centigrade value of 98.6 degrees is stored in locals[2]:
aload 1
ldc 98.6
invokevirtual Calculator/f2c(F)F
fstore 2
Invoke special is similar to invokevirtual, but is used in tricky situations such as invoking constructors:
.method public <init>()V
aload_0 ; push this
invokespecial
java/lang/Object/<init>()V ; call super
return
.end method
Until now we have been invoking Jasmin methods in Java. We can reverse this.
Recall Functions.java contained several static methods. In TestFunctions.j we invoke these methods.
Recall the Fahrenheit-Centigrade calculator:
We test these functions in TestCalculator.j.
A recursive function is a function that calls itself!
Why wouldn't this cause an infinite loop? Why wouldn't f(n) call f(n) call f(n) ...?
It would. Normally f(n) calls f(n – 1) calls f(n – 2) ... calls f(0).
But instead of calling f(-1), f(0) terminates the recursion by returning the answer.
For example, here's a recursive definition of the factorial function:
class RecursiveFunctions {
public static int fact(int n) {
if (n <= 0) {
return 1;
} else {
return n * fact(n – 1);
}
}
}
Let's trace a call:
RecursiveFunctions.fact(4)
4 * RecursiveFunctions.fact(3)
4 * 3 * RecursiveFunctions.fact(2)
4 * 3 * 2 * RecursiveFunctions.fact(1)
4 * 3 * 2 * 1 * RecursiveFunctions.fact(0)
4 * 3 * 2 * 1 * 1
4 * 3 * 2 * 1
4 * 3 * 2
4 * 6
24
Sometimes recursive functions are easier to write than non-recurive functions.
In the example above we get to assume fact(n – 1) works properly. We don't need to know how it works. We only need to know how to compute fact(n) from fact(n – 1). The answer: multiply by n!
Of course we also need to know fact(0).
Compilers often depend on recursion. For example, to compile a program n lines long, translate the first line into the the target language, then append to this the result of recursively compiling the remaining n – 1 lines:
Compliler {
Program compile(Program p) {
if (length(p) == 0) {
return null; // nothing to do!
} else {
Instruction q0 = translate(head(p));
Program q = compile(tail(p));
return append(q0, q);
}
}
}
See RecursiveFunctions.j for the recursive Jasmin definition of the factorial function.
recursively compile the first n – 1 lines, then figure out how to translate the last line.