/*
* Copyright 2009-2010 MBTE Sweden AB.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mbte.groovypp.compiler.asm;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.mbte.groovypp.compiler.CompilerStack;
public class UneededLoadPopRemoverMethodAdapter extends UneededDupStoreRemoverMethodAdapter {
private Load load;
static abstract class Load {
abstract void execute ();
}
class VarLabel extends Load {
private Label label;
public VarLabel(Label label) {
this.label = label;
}
void execute() {
UneededLoadPopRemoverMethodAdapter.super.visitLabel(label);
}
}
class LoadVar extends Load {
private int opcode;
private int var;
public LoadVar(int opcode, int var) {
this.opcode = opcode;
this.var = var;
}
public void execute() {
UneededLoadPopRemoverMethodAdapter.super.visitVarInsn(opcode, var);
}
}
class Ldc extends Load {
private Object cst;
public Ldc(Object cst) {
this.cst = cst;
}
public void execute() {
UneededLoadPopRemoverMethodAdapter.super.visitLdcInsn(cst);
}
}
class Checkcast extends Load {
private String descr;
public Checkcast(String descr) {
this.descr = descr;
}
public void execute() {
UneededLoadPopRemoverMethodAdapter.super.visitTypeInsn(CHECKCAST, descr);
}
}
public UneededLoadPopRemoverMethodAdapter(MethodVisitor mv) {
super(mv);
}
private void dropLoad() {
if (load != null) {
load.execute();
load = null;
}
}
public void visitInsn(int opcode) {
if (load != null && (opcode == POP || opcode == POP2)) {
if (load instanceof VarLabel) {
super.visitInsn(opcode);
super.visitLabel(((VarLabel)load).label);
}
else
if (load instanceof Checkcast) {
super.visitInsn(opcode);
}
load = null;
return;
}
dropLoad();
switch (opcode) {
case ACONST_NULL: visitLdcInsn(null); break;
case ICONST_M1: visitLdcInsn(-1); break;
case ICONST_0: visitLdcInsn(0); break;
case ICONST_1: visitLdcInsn(1); break;
case ICONST_2: visitLdcInsn(2); break;
case ICONST_3: visitLdcInsn(3); break;
case ICONST_4: visitLdcInsn(4); break;
case ICONST_5: visitLdcInsn(5); break;
case LCONST_0: visitLdcInsn(0L); break;
case LCONST_1: visitLdcInsn(1L); break;
case FCONST_0: visitLdcInsn(0.0f); break;
case FCONST_1: visitLdcInsn(1.0f); break;
case FCONST_2: visitLdcInsn(2.0f); break;
case DCONST_0: visitLdcInsn(0.0d); break;
case DCONST_1: visitLdcInsn(1.0d); break;
default:
super.visitInsn(opcode);
}
}
public void visitIntInsn(int opcode, int operand) {
dropLoad();
switch (opcode) {
case BIPUSH:
case SIPUSH:
visitLdcInsn(operand);
break;
default:
super.visitIntInsn(opcode, operand);
}
}
public void visitVarInsn(int opcode, int var) {
dropLoad();
switch (opcode) {
case ILOAD:
case LLOAD:
case FLOAD:
case DLOAD:
case ALOAD:
load = new LoadVar(opcode, var);
break;
default:
super.visitVarInsn(opcode, var);
}
}
public void visitTypeInsn(int opcode, String desc) {
dropLoad();
switch (opcode) {
case CHECKCAST:
load = new Checkcast(desc);
return;
default:
super.visitTypeInsn(opcode, desc);
break;
}
}
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
dropLoad();
super.visitFieldInsn(opcode, owner, name, desc);
}
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
dropLoad();
super.visitMethodInsn(opcode, owner, name, desc);
}
public void visitJumpInsn(int opcode, Label label) {
dropLoad();
super.visitJumpInsn(opcode, label);
}
public void visitLabel(Label label) {
if (label instanceof CompilerStack.VarStartLabel) {
dropLoad();
load = new VarLabel(label);
}
else {
dropLoad();
super.visitLabel(label);
}
}
public void visitLdcInsn(Object cst) {
dropLoad();
load = new Ldc(cst);
}
public void visitIincInsn(int var, int increment) {
dropLoad();
super.visitIincInsn(var, increment);
}
public void visitTableSwitchInsn(int min, int max, Label dflt, Label labels[]) {
dropLoad();
super.visitTableSwitchInsn(min, max, dflt, labels);
}
public void visitLookupSwitchInsn(Label dflt, int keys[], Label labels[]) {
dropLoad();
super.visitLookupSwitchInsn(dflt, keys, labels);
}
public void visitMultiANewArrayInsn(String desc, int dims) {
dropLoad();
super.visitMultiANewArrayInsn(desc, dims);
}
public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
dropLoad();
super.visitTryCatchBlock(start, end, handler, type);
}
}