use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class MopWriter method generateMopCalls.
/**
* generates a Meta Object Protocol method, that is used to call a non public
* method, or to make a call to super.
*
* @param mopCalls list of methods a mop call method should be generated for
* @param useThis true if "this" should be used for the naming
*/
protected void generateMopCalls(LinkedList<MethodNode> mopCalls, boolean useThis) {
for (MethodNode method : mopCalls) {
String name = getMopMethodName(method, useThis);
Parameter[] parameters = method.getParameters();
String methodDescriptor = BytecodeHelper.getMethodDescriptor(method.getReturnType(), method.getParameters());
MethodVisitor mv = controller.getClassVisitor().visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, name, methodDescriptor, null, null);
controller.setMethodVisitor(mv);
mv.visitVarInsn(ALOAD, 0);
int newRegister = 1;
OperandStack operandStack = controller.getOperandStack();
for (Parameter parameter : parameters) {
ClassNode type = parameter.getType();
operandStack.load(parameter.getType(), newRegister);
// increment to next register, double/long are using two places
newRegister++;
if (type == ClassHelper.double_TYPE || type == ClassHelper.long_TYPE)
newRegister++;
}
operandStack.remove(parameters.length);
ClassNode declaringClass = method.getDeclaringClass();
// JDK 8 support for default methods in interfaces
// this should probably be strenghtened when we support the A.super.foo() syntax
int opcode = declaringClass.isInterface() ? INVOKEINTERFACE : INVOKESPECIAL;
mv.visitMethodInsn(opcode, BytecodeHelper.getClassInternalName(declaringClass), method.getName(), methodDescriptor, opcode == INVOKEINTERFACE);
BytecodeHelper.doReturn(mv, method.getReturnType());
mv.visitMaxs(0, 0);
mv.visitEnd();
controller.getClassNode().addMethod(name, ACC_PUBLIC | ACC_SYNTHETIC, method.getReturnType(), parameters, null, null);
}
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class OperandStack method popDownTo.
public void popDownTo(int elements) {
int last = stack.size();
MethodVisitor mv = controller.getMethodVisitor();
while (last > elements) {
last--;
ClassNode element = popWithMessage(last);
if (isTwoSlotType(element)) {
mv.visitInsn(POP2);
} else {
mv.visitInsn(POP);
}
}
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class OperandStack method storeVar.
public void storeVar(BytecodeVariable variable) {
MethodVisitor mv = controller.getMethodVisitor();
int idx = variable.getIndex();
ClassNode type = variable.getType();
// value is on stack
if (variable.isHolder()) {
doGroovyCast(type);
box();
mv.visitVarInsn(ALOAD, idx);
mv.visitTypeInsn(CHECKCAST, "groovy/lang/Reference");
mv.visitInsn(SWAP);
mv.visitMethodInsn(INVOKEVIRTUAL, "groovy/lang/Reference", "set", "(Ljava/lang/Object;)V", false);
} else {
doGroovyCast(type);
if (type == ClassHelper.double_TYPE) {
mv.visitVarInsn(DSTORE, idx);
} else if (type == ClassHelper.float_TYPE) {
mv.visitVarInsn(FSTORE, idx);
} else if (type == ClassHelper.long_TYPE) {
mv.visitVarInsn(LSTORE, idx);
} else if (type == ClassHelper.boolean_TYPE || type == ClassHelper.char_TYPE || type == ClassHelper.byte_TYPE || type == ClassHelper.int_TYPE || type == ClassHelper.short_TYPE) {
mv.visitVarInsn(ISTORE, idx);
} else {
mv.visitVarInsn(ASTORE, idx);
}
}
// remove RHS value from operand stack
remove(1);
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class OperandStack method box.
public ClassNode box() {
MethodVisitor mv = controller.getMethodVisitor();
int size = stack.size();
ClassNode type = stack.get(size - 1);
if (ClassHelper.isPrimitiveType(type) && ClassHelper.VOID_TYPE != type) {
ClassNode wrapper = ClassHelper.getWrapper(type);
BytecodeHelper.doCastToWrappedType(mv, type, wrapper);
type = wrapper;
}
// else nothing to box
stack.set(size - 1, type);
return type;
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class OperandStack method pushConstant.
/**
* load the constant on the operand stack.
*/
public void pushConstant(ConstantExpression expression) {
MethodVisitor mv = controller.getMethodVisitor();
Object value = expression.getValue();
ClassNode origType = expression.getType().redirect();
ClassNode type = ClassHelper.getUnwrapper(origType);
boolean boxing = origType != type;
boolean asPrimitive = boxing || ClassHelper.isPrimitiveType(type);
if (value == null) {
mv.visitInsn(ACONST_NULL);
} else if (boxing && value instanceof Boolean) {
// special path for boxed boolean
Boolean bool = (Boolean) value;
String text = bool ? "TRUE" : "FALSE";
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", text, "Ljava/lang/Boolean;");
boxing = false;
type = origType;
} else if (asPrimitive) {
pushPrimitiveConstant(mv, value, type);
} else if (value instanceof BigDecimal) {
String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
mv.visitTypeInsn(NEW, className);
mv.visitInsn(DUP);
mv.visitLdcInsn(value.toString());
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/String;)V", false);
} else if (value instanceof BigInteger) {
String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
mv.visitTypeInsn(NEW, className);
mv.visitInsn(DUP);
mv.visitLdcInsn(value.toString());
mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", "(Ljava/lang/String;)V", false);
} else if (value instanceof String) {
mv.visitLdcInsn(value);
} else {
throw new ClassGeneratorException("Cannot generate bytecode for constant: " + value + " of type: " + type.getName());
}
push(type);
if (boxing)
box();
}
Aggregations