use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class StatementWriter method writeDoWhileLoop.
public void writeDoWhileLoop(DoWhileStatement loop) {
controller.getAcg().onLineNumber(loop, "visitDoWhileLoop");
writeStatementLabel(loop);
MethodVisitor mv = controller.getMethodVisitor();
controller.getCompileStack().pushLoop(loop.getStatementLabels());
Label breakLabel = controller.getCompileStack().getBreakLabel();
Label continueLabel = controller.getCompileStack().getContinueLabel();
mv.visitLabel(continueLabel);
loop.getLoopBlock().visit(controller.getAcg());
loop.getBooleanExpression().visit(controller.getAcg());
controller.getOperandStack().jump(IFEQ, continueLabel);
mv.visitLabel(breakLabel);
controller.getCompileStack().pop();
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class CompileStack method clear.
/**
* Clears the state of the class. This method should be called
* after a MethodNode is visited. Note that a call to init will
* fail if clear is not called before
*/
public void clear() {
if (stateStack.size() > 1) {
int size = stateStack.size() - 1;
throw new GroovyBugError("the compile stack contains " + size + " more push instruction" + (size == 1 ? "" : "s") + " than pops.");
}
if (lhsStack.size() > 1) {
int size = lhsStack.size() - 1;
throw new GroovyBugError("lhs stack is supposed to be empty, but has " + size + " elements left.");
}
if (implicitThisStack.size() > 1) {
int size = implicitThisStack.size() - 1;
throw new GroovyBugError("implicit 'this' stack is supposed to be empty, but has " + size + " elements left.");
}
clear = true;
MethodVisitor mv = controller.getMethodVisitor();
// br experiment with local var table so debuggers can retrieve variable names
if (true) {
//AsmClassGenerator.CREATE_DEBUG_INFO) {
if (thisEndLabel == null)
setEndLabels();
if (!scope.isInStaticContext()) {
// write "this"
mv.visitLocalVariable("this", className, null, thisStartLabel, thisEndLabel, 0);
}
for (Iterator iterator = usedVariables.iterator(); iterator.hasNext(); ) {
BytecodeVariable v = (BytecodeVariable) iterator.next();
ClassNode t = v.getType();
if (v.isHolder())
t = ClassHelper.REFERENCE_TYPE;
String type = BytecodeHelper.getTypeDescription(t);
Label start = v.getStartLabel();
Label end = v.getEndLabel();
mv.visitLocalVariable(v.getName(), type, null, start, end, v.getIndex());
}
}
//exception table writing
for (ExceptionTableEntry ep : typedExceptions) {
mv.visitTryCatchBlock(ep.start, ep.end, ep.goal, ep.sig);
}
//exception table writing
for (ExceptionTableEntry ep : untypedExceptions) {
mv.visitTryCatchBlock(ep.start, ep.end, ep.goal, ep.sig);
}
pop();
typedExceptions.clear();
untypedExceptions.clear();
stackVariables.clear();
usedVariables.clear();
scope = null;
finallyBlocks.clear();
resetVariableIndex(false);
superBlockNamedLabels.clear();
currentBlockNamedLabels.clear();
namedLoopBreakLabel.clear();
namedLoopContinueLabel.clear();
continueLabel = null;
breakLabel = null;
thisStartLabel = null;
thisEndLabel = null;
mv = null;
}
use of org.objectweb.asm.MethodVisitor in project groovy by apache.
the class InvocationWriter method prepareConstructorCall.
protected String prepareConstructorCall(ConstructorNode cn) {
String owner = BytecodeHelper.getClassInternalName(cn.getDeclaringClass());
MethodVisitor mv = controller.getMethodVisitor();
mv.visitTypeInsn(NEW, owner);
mv.visitInsn(DUP);
return owner;
}
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);
}
Aggregations