could use a simple peephole optimizer
If you look at what we generate for the FuncFactorial demo:
class(
object("FuncFactorial"),
methods=[
method(
methodDesc(
integer(),
"fact",
[integer()]),
[var(
integer(),
"n")],
[asm([
LABEL("L554752372"),
LINENUMBER(1,"L554752372"),
ILOAD(0),
ICONST_1(),
IF_ICMPGT("L82634714"),
LABEL("L1444851469"),
LINENUMBER(2,"L1444851469"),
ICONST_1(),
GOTO("L1932743161"),
LABEL("L82634714"),
LINENUMBER(4,"L82634714"),
ILOAD(0),
ILOAD(0),
ICONST_1(),
ISUB(),
INVOKESTATIC(
object("FuncFactorial"),
methodDesc(
integer(),
"fact",
[integer()]),
false),
IMUL(),
LABEL("L1932743161"),
LINENUMBER(1,"L1932743161"),
IRETURN(),
LABEL("L1422917010"),
LOCALVARIABLE(
"n",
integer(),
"L554752372",
"L1422917010",
0)
])]),
method(
methodDesc(
integer(),
"main",
[]),
[],
[asm([
LABEL("L939397862"),
LINENUMBER(7,"L939397862"),
ICONST_4(),
INVOKESTATIC(
object("FuncFactorial"),
methodDesc(
integer(),
"fact",
[integer()]),
false),
IRETURN()
])]),
method(
methodDesc(
void(),
"main",
[array(string())]),
[var(
array(string()),
"args")],
[asm([
LABEL("L339453395"),
LINENUMBER(1,"L339453395"),
GETSTATIC(
object("java.lang.System"),
"out",
object("java.io.PrintStream")),
INVOKESTATIC(
object("FuncFactorial"),
methodDesc(
integer(),
"main",
[]),
false),
INVOKESTATIC(
object("java.lang.Integer"),
methodDesc(
string(),
"toString",
[integer()]),
false),
INVOKEVIRTUAL(
object("java.io.PrintStream"),
methodDesc(
void(),
"println",
[object("java.lang.Object")]),
false),
RETURN(),
LABEL("L2104394292"),
LOCALVARIABLE(
"args",
array(string()),
"L339453395",
"L2104394292",
0)
])]),
method(
constructorDesc([]),
[],
[asm([
LABEL("L1449579366"),
ALOAD(0),
INVOKESPECIAL(
object("java.lang.Object"),
constructorDesc([]),
false),
RETURN(),
LABEL("L289964654"),
LOCALVARIABLE(
"this",
object("FuncFactorial"),
"L1449579366",
"L289964654",
0)
])])
],
fields=[],
interfaces=[],
super=object("java.lang.Object"),
modifiers={public()})
You see the consecutive ILOAD(0), ILOAD(0) which is much faster as ILOAD(0), DUP. A simple peephole optimizer in the back-end, written as a ASM visitor wrapper could do the trick.
https://github.com/cwi-swat/flybytes/blob/master/src/lang/flybytes/demo/func/fac.func
As you know I have good experience writing peephole optimizers directly in Rascal. One could give that a try.
I know. Unfortunately I have not made an intermediate step between flybytes asts and the ASM library on the way to bytecode. The reason is performance of the compiler. I think the disassembled example made you think otherwise. Got ya! 😇
On the way back I did use the above data type for bytecode instructions, because I really needed list matching for the decompiler and because some people only need a disassembler.
So we would have to implement the peephole optimizer against the ASM library.