The JVM is a stack machine, so intermediate code instructions generally begin by pushing operands on the stack, and then do their computation, then pop their result off the stack. Loading or storing to a local variable requires one instruction; loading or storing to a class variable requires two instructions. Since storing to a class variable requires the instance be pushed before the result, intermediate instructions that store to a class variable must either push the instance an extra time before working on their operands, or else swap the instance into position.
intermediate code instruction | Jasmin equivalent | Comment |
---|---|---|
x := y + z (local variables) | iload_y iload_z iadd istore_x | replace _x, _y, _z by slot offsets |
x := y + z (class foo variables) (sandwich method) | aload_0 aload_0 getfield foo/y I aload_0 getfield foo/z I iadd putfield foo/x | aload_0 pushes the "self" object |
x := y + z (class foo variables) (swap method) | aload_0 getfield foo/y I aload_0 getfield foo/z I iadd aload_0 swap putfield foo/x | aload_0 pushes the "self" object |
x := y + z (strings) | new java/lang/StringBuffer dup invokespecial java/lang/StringBuffer/<init>()V aload_y invokevirtual java/lang/StringBuffer/append(java/lang/String;)Ljava/lang/StringBuffer; aload_z invokevirtual java/lang/StringBuffer/append(java/lang/String;)Ljava/lang/StringBuffer; invokevirtual java/lang/StringBuffer/toString()Ljava/lang/String; astore_x | the creation of an implicit StringBuffer object, and three subsequent method invocations, in order to accomplish a string concatenation, looks laughably inefficient, but this is what the javacompiler does with string "+". |
x := - y (local variables) | iload_y ineg istore_x | replace _x, _y by slot offsets |
x := y (local variables) | iload_y istore_x | replace _x, _y by slot offsets |
x := &y x := *y *x := y | n/a | These red dragon book instructions not used |
goto L | goto L | |
if x < y then goto L | iload_x iload_y isub iflt L | |
if x then goto L | iload_x ifne L | |
if !x then goto L | iload_x ifeq L | |
param x | iload_x | push object before first parameter for method invocation |
call p,n,x | invokevirtual foo/x(parms)returntype | |
return x | iload_x ireturn | |
global x,n1,n2 | treat globals as class variables | |
proc x,n1,n2 | treat procedures as methods | |
local x,n | .limit locals n | no local declarations needed other than a count of how many |
label Ln | Ln: | |
end | .end method | |
x := y field z | iload_y getfield ysclass/z istore_x | ysclass is the class name for y |
class x,n1,n2 | .class public x .super java/lang/Object | |
field x,n | .field public x type |