use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class InvocationWriter method writeDirectMethodCall.
protected boolean writeDirectMethodCall(MethodNode target, boolean implicitThis, Expression receiver, TupleExpression args) {
if (target == null)
return false;
String methodName = target.getName();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
ClassNode declaringClass = target.getDeclaringClass();
ClassNode classNode = controller.getClassNode();
MethodVisitor mv = controller.getMethodVisitor();
int opcode = INVOKEVIRTUAL;
if (target.isStatic()) {
opcode = INVOKESTATIC;
} else if (target.isPrivate() || ((receiver instanceof VariableExpression && ((VariableExpression) receiver).isSuperExpression()))) {
opcode = INVOKESPECIAL;
} else if (declaringClass.isInterface()) {
opcode = INVOKEINTERFACE;
}
// handle receiver
int argumentsToRemove = 0;
if (opcode != INVOKESTATIC) {
if (receiver != null) {
// todo: fix inner class case
if (implicitThis && !classNode.isDerivedFrom(declaringClass) && !classNode.implementsInterface(declaringClass) && classNode instanceof InnerClassNode) {
// we are calling an outer class method
compileStack.pushImplicitThis(false);
if (controller.isInClosure()) {
new VariableExpression("thisObject").visit(controller.getAcg());
} else {
Expression expr = new PropertyExpression(new ClassExpression(declaringClass), "this");
expr.visit(controller.getAcg());
}
} else {
compileStack.pushImplicitThis(implicitThis);
receiver.visit(controller.getAcg());
}
operandStack.doGroovyCast(declaringClass);
compileStack.popImplicitThis();
argumentsToRemove++;
} else {
mv.visitIntInsn(ALOAD, 0);
operandStack.push(classNode);
argumentsToRemove++;
}
}
int stackSize = operandStack.getStackLength();
String owner = BytecodeHelper.getClassInternalName(declaringClass);
ClassNode receiverType = receiver != null ? controller.getTypeChooser().resolveType(receiver, classNode) : declaringClass;
if (opcode == INVOKEVIRTUAL && ClassHelper.OBJECT_TYPE.equals(declaringClass)) {
// avoid using a narrowed type if the method is defined on object because it can interfere
// with delegate type inference in static compilation mode and trigger a ClassCastException
receiverType = declaringClass;
}
if (opcode == INVOKEVIRTUAL) {
if (!receiverType.equals(declaringClass) && !ClassHelper.OBJECT_TYPE.equals(declaringClass) && !receiverType.isArray() && !receiverType.isInterface() && // e.g int.getClass()
!ClassHelper.isPrimitiveType(receiverType) && receiverType.isDerivedFrom(declaringClass)) {
owner = BytecodeHelper.getClassInternalName(receiverType);
ClassNode top = operandStack.getTopOperand();
if (!receiverType.equals(top)) {
mv.visitTypeInsn(CHECKCAST, owner);
}
} else if (target.isPublic() && (!Modifier.isPublic(declaringClass.getModifiers()) && !receiverType.equals(declaringClass)) && receiverType.isDerivedFrom(declaringClass) && !receiverType.getPackageName().equals(classNode.getPackageName())) {
// package private class, public method
// see GROOVY-6962
owner = BytecodeHelper.getClassInternalName(receiverType);
}
}
loadArguments(args.getExpressions(), target.getParameters());
String desc = BytecodeHelper.getMethodDescriptor(target.getReturnType(), target.getParameters());
mv.visitMethodInsn(opcode, owner, methodName, desc, opcode == INVOKEINTERFACE);
ClassNode ret = target.getReturnType().redirect();
if (ret == ClassHelper.VOID_TYPE) {
ret = ClassHelper.OBJECT_TYPE;
mv.visitInsn(ACONST_NULL);
}
argumentsToRemove += (operandStack.getStackLength() - stackSize);
controller.getOperandStack().remove(argumentsToRemove);
controller.getOperandStack().push(ret);
return true;
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class InvocationWriter method castNonPrimitiveToBool.
public void castNonPrimitiveToBool(ClassNode last) {
MethodVisitor mv = controller.getMethodVisitor();
BytecodeHelper.unbox(mv, ClassHelper.boolean_TYPE);
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class InvocationWriter method finnishConstructorCall.
protected void finnishConstructorCall(ConstructorNode cn, String ownerDescriptor, int argsToRemove) {
String desc = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, cn.getParameters());
MethodVisitor mv = controller.getMethodVisitor();
mv.visitMethodInsn(INVOKESPECIAL, ownerDescriptor, "<init>", desc, false);
controller.getOperandStack().remove(argsToRemove);
controller.getOperandStack().push(cn.getDeclaringClass());
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class InvocationWriter method coerce.
public void coerce(ClassNode from, ClassNode target) {
if (from.isDerivedFrom(target))
return;
MethodVisitor mv = controller.getMethodVisitor();
OperandStack os = controller.getOperandStack();
os.box();
(new ClassExpression(target)).visit(controller.getAcg());
os.remove(1);
asTypeMethod.call(mv);
BytecodeHelper.doCast(mv, target);
os.replace(target);
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class OperandStack method load.
public void load(ClassNode type, int idx) {
MethodVisitor mv = controller.getMethodVisitor();
BytecodeHelper.load(mv, type, idx);
push(type);
}
Aggregations