Example usage for org.objectweb.asm Opcodes INVOKESPECIAL

List of usage examples for org.objectweb.asm Opcodes INVOKESPECIAL

Introduction

In this page you can find the example usage for org.objectweb.asm Opcodes INVOKESPECIAL.

Prototype

int INVOKESPECIAL

To view the source code for org.objectweb.asm Opcodes INVOKESPECIAL.

Click Source Link

Usage

From source file:org.jvnet.jax_ws_commons.beans_generator.ambassador.impl.asm.ASMResponseBeanGenerator.java

License:Open Source License

private void generateNoArgsConstructor() {
    MethodVisitor mv = writer.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();/*from  ww  w .j a  va 2 s  . c o m*/
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    mv.visitInsn(Opcodes.RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
}

From source file:org.kantega.notsoserial.CreateBytesIT.java

License:Apache License

private byte[] createTransletBytes() {

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    cw.visit(Opcodes.V1_5, Opcodes.ACC_PUBLIC, "com/example/InvokingTranslet", null,
            Type.getType(AbstractTranslet.class).getInternalName(),
            new String[] { Type.getType(Serializable.class).getInternalName() });

    MethodVisitor init = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
    init.visitCode();/*from  ww w .jav  a 2 s. co m*/
    init.visitVarInsn(Opcodes.ALOAD, 0);
    init.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getType(AbstractTranslet.class).getInternalName(),
            "<init>", "()V");
    init.visitVarInsn(Opcodes.ALOAD, 0);
    init.visitIntInsn(Opcodes.BIPUSH, 101);
    init.visitFieldInsn(Opcodes.PUTFIELD, Type.getType(AbstractTranslet.class).getInternalName(),
            "transletVersion", "I");
    init.visitInsn(Opcodes.RETURN);
    init.visitMaxs(2, 2);
    init.visitEnd();

    MethodVisitor transformMethod = cw.visitMethod(Opcodes.ACC_PUBLIC, "transform",
            Type.getMethodDescriptor(Type.VOID_TYPE,
                    new Type[] { Type.getType(DOM.class), Type.getType(DTMAxisIterator.class) }),
            null, new String[] { Type.getType(TransletException.class).getInternalName() });

    transformMethod.visitCode();
    transformMethod.visitInsn(Opcodes.RETURN);
    transformMethod.visitEnd();

    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
    mv.visitCode();
    mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
    mv.visitLdcInsn("HMM..");
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
    mv.visitLdcInsn("pwned");
    mv.visitLdcInsn("true");
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "setProperty",
            "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
    mv.visitInsn(Opcodes.POP);
    mv.visitInsn(Opcodes.RETURN);
    mv.visitMaxs(2, 0);
    mv.visitEnd();
    cw.visitEnd();

    return cw.toByteArray();
}

From source file:org.lambdamatic.analyzer.ast.LambdaExpressionReader.java

License:Open Source License

/**
 * Reads the bytecode from the given {@link InsnCursor}'s <strong>current position</strong>, until
 * there is no further instruction to proceed. It is the responsability of the caller to set the
 * cursor position.//from w ww  . j a  v a  2 s .c om
 * 
 * @param insnCursor the instruction cursor used to read the bytecode.
 * @param expressionStack the expression stack to put on or pop from.
 * @param localVariables the local variables
 * @return a {@link List} of {@link Statement} containing the {@link Statement}
 */
private List<Statement> readStatements(final InsnCursor insnCursor, final Stack<Expression> expressionStack,
        final List<CapturedArgument> capturedArguments, final LocalVariables localVariables) {
    final List<Statement> statements = new ArrayList<>();
    while (insnCursor.hasCurrent()) {
        final AbstractInsnNode currentInstruction = insnCursor.getCurrent();
        switch (currentInstruction.getType()) {
        case AbstractInsnNode.VAR_INSN:
            final VarInsnNode varInstruction = (VarInsnNode) currentInstruction;
            switch (currentInstruction.getOpcode()) {
            // load a reference onto the stack from a local variable
            case Opcodes.ALOAD:
            case Opcodes.ILOAD:
                // load an int value from a local variable
                // Note: The 'var' operand is the index of a local variable
                // all captured arguments come before the local variable in the method signature,
                // which means that the local variables table is empty on the first slots which are
                // "allocated"
                // for the captured arguments.
                if (varInstruction.var < capturedArguments.size()) {
                    // if the variable index matches a captured argument
                    // note: not using actual captured argument but rather, use a _reference_ to it.
                    final Object capturedArgumentValue = capturedArguments.get(varInstruction.var).getValue();
                    final Class<?> capturedArgumentValueType = capturedArgumentValue != null
                            ? capturedArgumentValue.getClass()
                            : Object.class;
                    final CapturedArgumentRef capturedArgumentRef = new CapturedArgumentRef(varInstruction.var,
                            capturedArgumentValueType);
                    expressionStack.add(capturedArgumentRef);
                } else {
                    // the variable index matches a local variable
                    final LocalVariableNode var = localVariables.load(varInstruction.var);
                    expressionStack.add(new LocalVariable(var.index, var.name, readSignature(var.desc)));
                }
                break;
            case Opcodes.ASTORE:
                // store a reference into a local variable
                localVariables.store(varInstruction.var);
                break;
            default:
                throw new AnalyzeException(
                        "Unexpected Variable instruction code: " + varInstruction.getOpcode());
            }
            break;
        case AbstractInsnNode.LDC_INSN:
            // let's move this instruction on top of the stack until it
            // is used as an argument during a method call
            final LdcInsnNode ldcInsnNode = (LdcInsnNode) currentInstruction;
            final Expression constant = ExpressionFactory.getExpression(ldcInsnNode.cst);
            LOGGER.trace("Stacking constant {}", constant);
            expressionStack.add(constant);
            break;
        case AbstractInsnNode.FIELD_INSN:
            final FieldInsnNode fieldInsnNode = (FieldInsnNode) currentInstruction;
            switch (fieldInsnNode.getOpcode()) {
            case Opcodes.GETSTATIC:
                final Type ownerType = Type.getType(fieldInsnNode.desc);
                final FieldAccess staticFieldAccess = new FieldAccess(new ClassLiteral(getType(ownerType)),
                        fieldInsnNode.name);
                expressionStack.add(staticFieldAccess);
                break;

            case Opcodes.GETFIELD:
                final Expression fieldAccessParent = expressionStack.pop();
                final FieldAccess fieldAccess = new FieldAccess(fieldAccessParent, fieldInsnNode.name);
                expressionStack.add(fieldAccess);
                break;
            case Opcodes.PUTFIELD:
                final Expression fieldAssignationValue = expressionStack.pop();
                final Expression parentSource = expressionStack.pop();
                final FieldAccess source = new FieldAccess(parentSource, fieldInsnNode.name);
                final Assignment assignmentExpression = new Assignment(source, fieldAssignationValue);
                statements.add(new ExpressionStatement(assignmentExpression));
                break;
            default:
                throw new AnalyzeException("Unexpected field instruction type: " + fieldInsnNode.getOpcode());

            }
            break;
        case AbstractInsnNode.METHOD_INSN:
            final MethodInsnNode methodInsnNode = (MethodInsnNode) currentInstruction;
            final Type[] argumentTypes = Type.getArgumentTypes(methodInsnNode.desc);
            final List<Expression> args = new ArrayList<>();
            final List<Class<?>> parameterTypes = new ArrayList<>();
            Stream.of(argumentTypes).forEach(argumentType -> {
                final Expression arg = expressionStack.pop();
                final String argumentClassName = argumentType.getClassName();
                args.add(castOperand(arg, argumentClassName));
                try {
                    parameterTypes.add(ClassUtils.getClass(argumentClassName));
                } catch (Exception e) {
                    throw new AnalyzeException("Failed to find class '" + argumentClassName + "'", e);
                }
            });
            // arguments appear in reverse order in the bytecode
            Collections.reverse(args);
            switch (methodInsnNode.getOpcode()) {
            case Opcodes.INVOKEINTERFACE:
            case Opcodes.INVOKEVIRTUAL:
            case Opcodes.INVOKESPECIAL:
                // object instantiation
                if (methodInsnNode.name.equals("<init>")) {
                    final ObjectInstanciation objectVariable = (ObjectInstanciation) expressionStack.pop();
                    objectVariable.setInitArguments(args);
                } else {
                    final Expression sourceExpression = expressionStack.pop();
                    final Method javaMethod = ReflectionUtils.findJavaMethod(sourceExpression.getJavaType(),
                            methodInsnNode.name, parameterTypes);
                    final Class<?> returnType = findReturnType(insnCursor, javaMethod);
                    final MethodInvocation invokedMethod = new MethodInvocation(sourceExpression, javaMethod,
                            returnType, args);
                    expressionStack.add(invokedMethod);
                }
                break;
            case Opcodes.INVOKESTATIC:
                final Type type = Type.getObjectType(methodInsnNode.owner);
                try {
                    final Class<?> sourceClass = Class.forName(type.getClassName());
                    final Method javaMethod = ReflectionUtils.findJavaMethod(sourceClass, methodInsnNode.name,
                            parameterTypes);
                    final Class<?> returnType = findReturnType(insnCursor, javaMethod);
                    final MethodInvocation invokedStaticMethod = new MethodInvocation(
                            new ClassLiteral(sourceClass), javaMethod, returnType, args);
                    expressionStack.add(invokedStaticMethod);
                } catch (ClassNotFoundException e) {
                    throw new AnalyzeException("Failed to retrieve class for " + methodInsnNode.owner, e);
                }
                break;
            default:
                throw new AnalyzeException("Unexpected method invocation type: " + methodInsnNode.getOpcode());
            }
            break;
        case AbstractInsnNode.INVOKE_DYNAMIC_INSN:
            final InvokeDynamicInsnNode invokeDynamicInsnNode = (InvokeDynamicInsnNode) currentInstruction;
            final Handle handle = (Handle) invokeDynamicInsnNode.bsmArgs[1];
            final int argNumber = Type.getArgumentTypes(invokeDynamicInsnNode.desc).length;
            final List<CapturedArgumentRef> lambdaArgs = new ArrayList<>();
            for (int i = 0; i < argNumber; i++) {
                final Expression expr = expressionStack.pop();
                if (expr.getExpressionType() != ExpressionType.CAPTURED_ARGUMENT_REF) {
                    throw new AnalyzeException("Unexpected argument type when following InvokeDynamic call: "
                            + expr.getExpressionType());
                }
                lambdaArgs.add((CapturedArgumentRef) expr); // , expr.getValue()
            }
            Collections.reverse(lambdaArgs);
            final EmbeddedSerializedLambdaInfo lambdaInfo = new EmbeddedSerializedLambdaInfo(handle.getOwner(),
                    handle.getName(), handle.getDesc(), lambdaArgs, capturedArguments);
            final LambdaExpression lambdaExpression = LambdaExpressionAnalyzer.getInstance()
                    .analyzeExpression(lambdaInfo);
            expressionStack.add(lambdaExpression);
            break;
        case AbstractInsnNode.JUMP_INSN:
            statements.addAll(
                    readJumpInstruction(insnCursor, expressionStack, capturedArguments, localVariables));
            return statements;
        case AbstractInsnNode.INT_INSN:
            readIntInstruction((IntInsnNode) currentInstruction, expressionStack, localVariables);
            break;
        case AbstractInsnNode.INSN:
            final List<Statement> instructionStatement = readInstruction(insnCursor, expressionStack,
                    capturedArguments, localVariables);
            statements.addAll(instructionStatement);
            break;
        case AbstractInsnNode.TYPE_INSN:
            readTypeInstruction((TypeInsnNode) currentInstruction, expressionStack, localVariables);
            break;
        default:
            throw new AnalyzeException(
                    "This is embarrassing... We've reached an unexpected instruction operator: "
                            + currentInstruction.getType());
        }
        insnCursor.next();
    }
    return statements;
}

From source file:org.mbte.groovypp.compiler.bytecode.BytecodeExpr.java

License:Apache License

/**
 * box the primitive value on the stack//from   w  w w.j  a  va 2 s.  co m
 *
 * @param type
 * @param mv
 */
public void quickBoxIfNecessary(ClassNode type, MethodVisitor mv) {
    String descr = getTypeDescription(type);
    if (type == boolean_TYPE) {
        boxBoolean(mv);
    } else if (isPrimitiveType(type) && type != VOID_TYPE) {
        ClassNode wrapper = TypeUtil.wrapSafely(type);
        String internName = getClassInternalName(wrapper);
        mv.visitTypeInsn(Opcodes.NEW, internName);
        mv.visitInsn(Opcodes.DUP);
        if (type == double_TYPE || type == long_TYPE) {
            mv.visitInsn(Opcodes.DUP2_X2);
            mv.visitInsn(Opcodes.POP2);
        } else {
            mv.visitInsn(Opcodes.DUP2_X1);
            mv.visitInsn(Opcodes.POP2);
        }
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internName, "<init>", "(" + descr + ")V");
    }
}

From source file:org.mbte.groovypp.compiler.bytecode.BytecodeExpr.java

License:Apache License

/**
 * load the constant on the operand stack. primitives auto-boxed.
 *///  ww w  . j  a v a2  s .c om
void loadConstant(Object value, MethodVisitor mv) {
    if (value == null) {
        mv.visitInsn(Opcodes.ACONST_NULL);
    } else if (value instanceof String) {
        mv.visitLdcInsn(value);
    } else if (value instanceof Character) {
        String className = "java/lang/Character";
        mv.visitTypeInsn(Opcodes.NEW, className);
        mv.visitInsn(Opcodes.DUP);
        mv.visitLdcInsn(value);
        String methodType = "(C)V";
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", methodType);
    } else if (value instanceof Number) {
        /** todo it would be more efficient to generate class constants */
        Number n = (Number) value;
        String className = BytecodeHelper.getClassInternalName(value.getClass().getName());
        mv.visitTypeInsn(Opcodes.NEW, className);
        mv.visitInsn(Opcodes.DUP);
        String methodType;
        if (n instanceof Integer) {
            //pushConstant(n.intValue());
            mv.visitLdcInsn(n);
            methodType = "(I)V";
        } else if (n instanceof Double) {
            mv.visitLdcInsn(n);
            methodType = "(D)V";
        } else if (n instanceof Float) {
            mv.visitLdcInsn(n);
            methodType = "(F)V";
        } else if (n instanceof Long) {
            mv.visitLdcInsn(n);
            methodType = "(J)V";
        } else if (n instanceof BigDecimal) {
            mv.visitLdcInsn(n.toString());
            methodType = "(Ljava/lang/String;)V";
        } else if (n instanceof BigInteger) {
            mv.visitLdcInsn(n.toString());
            methodType = "(Ljava/lang/String;)V";
        } else if (n instanceof Short) {
            mv.visitLdcInsn(n);
            methodType = "(S)V";
        } else if (n instanceof Byte) {
            mv.visitLdcInsn(n);
            methodType = "(B)V";
        } else {
            throw new ClassGeneratorException("Cannot generate bytecode for constant: " + value + " of type: "
                    + value.getClass().getName() + ".  Numeric constant type not supported.");
        }
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, "<init>", methodType);
    } else if (value instanceof Boolean) {
        Boolean bool = (Boolean) value;
        String text = (bool.booleanValue()) ? "TRUE" : "FALSE";
        mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/Boolean", text, "Ljava/lang/Boolean;");
    } else if (value instanceof Class) {
        Class vc = (Class) value;
        if (vc.getName().equals("java.lang.Void")) {
            // load nothing here for void
        } else {
            throw new ClassGeneratorException("Cannot generate bytecode for constant: " + value + " of type: "
                    + value.getClass().getName());
        }
    } else {
        throw new ClassGeneratorException(
                "Cannot generate bytecode for constant: " + value + " of type: " + value.getClass().getName());
    }
}

From source file:org.mbte.groovypp.compiler.ClosureUtil.java

License:Apache License

public static void instantiateClass(ClassNode type, CompilerTransformer compiler, Parameter[] constrParams,
        Expression superArgs, MethodVisitor mv) {
    TraitASTTransformFinal.improveAbstractMethods(type);
    type.getModule().addClass(type);//from  ww  w. j ava2  s .c o  m

    final String classInternalName = BytecodeHelper.getClassInternalName(type);
    mv.visitTypeInsn(Opcodes.NEW, classInternalName);
    mv.visitInsn(Opcodes.DUP);

    final ConstructorNode constructorNode = type.getDeclaredConstructors().get(0);

    for (int i = 0; i != constrParams.length; i++) {
        String name = constrParams[i].getName();

        if ("this$0".equals(name)) {
            mv.visitVarInsn(Opcodes.ALOAD, 0);
        } else {
            final Register var = compiler.compileStack.getRegister(name, false);
            if (var != null) {
                FieldNode field = type.getDeclaredField(name);
                BytecodeExpr.load(field.getType(), var.getIndex(), mv);
                if (!constrParams[i].getType().equals(var.getType())
                        && !ClassHelper.isPrimitiveType(field.getType())) {
                    BytecodeExpr.checkCast(constrParams[i].getType(), mv);
                }
            } else {
                FieldNode field = compiler.methodNode.getDeclaringClass().getDeclaredField(name);
                mv.visitVarInsn(Opcodes.ALOAD, 0);
                if (field == null) // @Field
                    name = compiler.methodNode.getName() + "$" + name;
                mv.visitFieldInsn(Opcodes.GETFIELD,
                        BytecodeHelper.getClassInternalName(compiler.methodNode.getDeclaringClass()), name,
                        BytecodeHelper.getTypeDescription(constrParams[i].getType()));
            }
        }
    }

    if (superArgs != null) {
        final List<Expression> list = ((ArgumentListExpression) superArgs).getExpressions();
        for (int i = 0; i != list.size(); ++i)
            ((BytecodeExpr) list.get(i)).visit(mv);
    }

    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, classInternalName, "<init>",
            BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, constructorNode.getParameters()));
}

From source file:org.nanocontainer.picometer.PicoMeterMethodVisitor.java

License:Open Source License

public void visitMethodInsn(int opcode, String owner, String name, String desc) {
    boolean isNew = (Opcodes.INVOKESPECIAL == opcode) && owner.equals(lastType) && "<init>".equals(name);
    if (isNew) {// w  w  w. ja va2 s .  c  o m
        String className = owner.replace('/', '.');
        final Instantiation instantiation = new Instantiation(className, picoMeterClass);
        try {
            instantiation.setBytecodeLine(currentLine);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
        instantiations.add(instantiation);
    }
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Add the <init> method for the given constructor. This also includes initializing the non-static fields that 
 *   have initializers.//  www. j a  v  a  2 s .  com
 * @param classRep 
 * @param javaConstructor
 * @param cv
 * @throws JavaGenerationException
 */
private static void encodeConstructor(JavaClassRep classRep, JavaConstructor javaConstructor, ClassVisitor cv)
        throws JavaGenerationException {

    // gather info on the thrown exceptions
    final int nThrownExceptions = javaConstructor.getNThrownExceptions();
    String[] thrownExceptions = new String[nThrownExceptions];
    for (int i = 0; i < nThrownExceptions; ++i) {
        thrownExceptions[i] = javaConstructor.getThrownException(i).getJVMInternalName();
    }

    MethodVisitor mv = cv.visitMethod(javaConstructor.getModifiers(), "<init>",
            javaConstructor.getJVMMethodDescriptor(), null, thrownExceptions);

    final Map<String, JavaTypeName> methodVarToTypeMap = new HashMap<String, JavaTypeName>();
    final Map<String, Integer> methodVarToIndexMap = new HashMap<String, Integer>();
    methodVarToTypeMap.put("this", classRep.getClassName());
    methodVarToIndexMap.put("this", Integer.valueOf(0));
    int indexOfNextSlot = 1;

    for (int i = 0, nParams = javaConstructor.getNParams(); i < nParams; ++i) {
        JavaTypeName varType = javaConstructor.getParamType(i);
        final int typeSize = getTypeSize(varType);
        String varName = javaConstructor.getParamName(i);
        methodVarToTypeMap.put(varName, varType);
        methodVarToIndexMap.put(varName, Integer.valueOf(indexOfNextSlot));
        indexOfNextSlot += typeSize;
    }

    // Start the method's code.
    mv.visitCode();

    // Invoke the superclass initializer.     

    if (javaConstructor.getSuperConstructorParamTypes().length == 0) {
        //push the "this" reference on the stack
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, classRep.getSuperclassName().getJVMInternalName(), "<init>",
                "()V");
    } else {
        GenerationContext context = new GenerationContext(methodVarToTypeMap, methodVarToIndexMap,
                indexOfNextSlot, mv, classRep.getClassName());
        MethodInvocation mi = new MethodInvocation.Instance(null, "<init>", classRep.getSuperclassName(),
                javaConstructor.getSuperConstructorParamValues(),
                javaConstructor.getSuperConstructorParamTypes(), JavaTypeName.VOID,
                MethodInvocation.InvocationType.SPECIAL);
        encodeMethodInvocationExpr(mi, context);
    }

    // Add initializers for the non-statically-initialized fields.        
    final int nFields = classRep.getNFieldDeclarations();
    for (int i = 0; i < nFields; ++i) {

        JavaFieldDeclaration fieldDecl = classRep.getFieldDeclaration(i);
        JavaExpression initializer = fieldDecl.getInitializer();

        if (initializer != null && !Modifier.isStatic(fieldDecl.getModifiers())) {

            GenerationContext context = new GenerationContext(methodVarToTypeMap, methodVarToIndexMap,
                    indexOfNextSlot, mv, classRep.getClassName());

            //push the "this" reference
            mv.visitVarInsn(Opcodes.ALOAD, 0);

            //evaluate the initializer
            encodeExpr(initializer, context);

            //do the assignment
            mv.visitFieldInsn(Opcodes.PUTFIELD, classRep.getClassName().getJVMInternalName(),
                    fieldDecl.getFieldName(), fieldDecl.getFieldType().getJVMDescriptor());
        }
    }

    // Add the body code for the constructor
    GenerationContext context = new GenerationContext(methodVarToTypeMap, methodVarToIndexMap, indexOfNextSlot,
            mv, classRep.getClassName());
    boolean isTerminating = encodeStatement(javaConstructor.getBodyCode(), context);

    // Add any implicit "return" statement.
    if (!isTerminating) {
        mv.visitInsn(Opcodes.RETURN);
    }

    //mark the end of encoding the constructor
    mv.visitMaxs(0, 0);

    // End the method.
    mv.visitEnd();
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Encodes the Java code for a given Java operator expression.
 *   /* w ww.j a va2 s. c o m*/
 * @param operatorExpr the java operator expression  
 * @param context
 * @return JavaTypeName
 * @throws JavaGenerationException
 */
private static JavaTypeName encodeOperatorExpr(JavaExpression.OperatorExpression operatorExpr,
        GenerationContext context) throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    JavaOperator operator = operatorExpr.getJavaOperator();
    String symbol = operator.getSymbol();
    JavaTypeName valueType = operator.getValueType();

    // Now carry out the operation according to its type.
    if (operator.isArithmeticOp()) {

        // Add the instructions to evaluate the first argument.
        JavaTypeName arg1Type = encodeExpr(operatorExpr.getArgument(0), context);

        if (operatorExpr instanceof OperatorExpression.Unary) {

            if (symbol.equals("-")) { // number negation

                mv.visitInsn(getNegateOpCode(arg1Type));
                return arg1Type;
            }

            throw new JavaGenerationException("Unknown unary arithmetic operator " + symbol + ".");
        }

        // Add an instruction to widen the argument if necessary.
        int wideningOpCode = getWideningOpCode(arg1Type, valueType);
        if (wideningOpCode != Opcodes.NOP) {
            mv.visitInsn(wideningOpCode);
        }

        // Add the instructions to evaluate the second argument.
        JavaTypeName arg2Type = encodeExpr(operatorExpr.getArgument(1), context);

        // Add an instruction to widen the argument if necessary.
        wideningOpCode = getWideningOpCode(arg2Type, valueType);
        if (wideningOpCode != Opcodes.NOP) {
            mv.visitInsn(wideningOpCode);
        }

        // Evaluate.
        mv.visitInsn(getArithmeticBinaryOpCode(symbol, valueType));

        return valueType;
    }

    if (operator.isBitOp()) {
        // Add the instructions to evaluate the first argument.
        JavaTypeName arg1Type = encodeExpr(operatorExpr.getArgument(0), context);

        // Add an instruction to widen the argument if necessary.
        int wideningOpCode = getWideningOpCode(arg1Type, valueType);
        if (wideningOpCode != Opcodes.NOP) {
            mv.visitInsn(wideningOpCode);
        }

        if (operatorExpr instanceof OperatorExpression.Unary) {
            if (symbol.equals("~")) { // number negation
                if (valueType == JavaTypeName.INT) {
                    mv.visitInsn(Opcodes.ICONST_M1);
                    mv.visitInsn(Opcodes.IXOR);
                    return valueType;
                } else if (valueType == JavaTypeName.LONG) {
                    encodePushLongValue(new Long(-1), context);
                    mv.visitInsn(Opcodes.LXOR);
                    return valueType;
                }
            }

            throw new JavaGenerationException("Unknown unary arithmetic operator " + symbol + ".");
        }

        // Add the instructions to evaluate the second argument.
        JavaTypeName arg2Type = encodeExpr(operatorExpr.getArgument(1), context);

        // If this is >>, >>>, or << we may need to narrow the second argument to an int
        if (symbol.equals(">>") || symbol.equals(">>>") || symbol.equals("<<")) {
            if (arg2Type == JavaTypeName.LONG) {
                mv.visitInsn(Opcodes.L2I);
            }
        } else {
            // Add an instruction to widen the argument if necessary.
            wideningOpCode = getWideningOpCode(arg2Type, valueType);
            if (wideningOpCode != Opcodes.NOP) {
                mv.visitInsn(wideningOpCode);
            }
        }

        // Evaluate.
        mv.visitInsn(getArithmeticBinaryOpCode(symbol, valueType));

        return valueType;

    }

    if (operator.isLogicalOp() || operator.isRelationalOp()) {

        // Logical op:    {"!", "&&", "||"}
        // Relational op: {">", ">=", "<", "<=", "==", "!="}

        Label trueContinuation = new Label();
        Label falseContinuation = new Label();

        encodeBooleanValuedOperatorHelper(operatorExpr, context, trueContinuation, falseContinuation);
        return encodeThenTrueElseFalse(trueContinuation, falseContinuation, context);
    }

    if (operator == JavaOperator.STRING_CONCATENATION) {

        // Create an uninitialized StringBuilder, duplicate the reference (so we can invoke the initializer).
        mv.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder");
        mv.visitInsn(Opcodes.DUP);

        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V");

        // append the first arg.
        JavaTypeName firstArgType = encodeExpr(operatorExpr.getArgument(0), context);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                getAppendJVMDescriptor(firstArgType));

        // Append the results of evaluation of the second arg.
        // Note that, conveniently, StringBuilder has an append() method for all the different types.
        JavaTypeName secondArgType = encodeExpr(operatorExpr.getArgument(1), context);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "append",
                getAppendJVMDescriptor(secondArgType));

        // Call toString() on the result.           
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/StringBuilder", "toString",
                "()Ljava/lang/String;");

        return JavaTypeName.STRING;
    }

    return encodeTernaryOperatorExpr((OperatorExpression.Ternary) operatorExpr, context);
}

From source file:org.openquark.cal.internal.javamodel.AsmJavaBytecodeGenerator.java

License:Open Source License

/**
 * Create the Java code for a given method invocation.
 *   The expression result to be pushed onto the stack.
 * @param mi the method invocation     /*  www .  j  a v  a2 s  .com*/
 * @param context
 * @return JavaTypeName the type of the result on the operand stack. 
 * @throws JavaGenerationException
 */
private static JavaTypeName encodeMethodInvocationExpr(JavaExpression.MethodInvocation mi,
        GenerationContext context) throws JavaGenerationException {

    MethodInvocation.InvocationType invocationType = mi.getInvocationType();

    int invocationCode;
    JavaTypeName invocationClassType;

    if (invocationType != MethodInvocation.InvocationType.STATIC) {

        JavaExpression invocationTarget = ((MethodInvocation.Instance) mi).getInvocationTarget();
        if (invocationTarget == null) {
            //push a reference to 'this' onto the stack.
            invocationClassType = encodeThis(context);
        } else {
            //push a reference to the invoking expression onto the stack
            invocationClassType = encodeExpr(invocationTarget, context);
        }

        // The MethodInvocation may contain an explicit invoking class type.  If it does
        // use it in preference to the type of the invocation target.
        if (mi instanceof MethodInvocation.Instance
                && ((MethodInvocation.Instance) mi).getDeclaringClass() != null) {
            invocationClassType = ((MethodInvocation.Instance) mi).getDeclaringClass();
        }

        if (invocationType == MethodInvocation.InvocationType.VIRTUAL) {
            invocationCode = Opcodes.INVOKEVIRTUAL;

        } else if (invocationType == MethodInvocation.InvocationType.INTERFACE) {
            if (invocationClassType.isInterface()) {
                invocationCode = Opcodes.INVOKEINTERFACE;
            } else {
                //if we invoke an interface method on a reference that is known to be a Class, then we must use invoke virtual
                //to avoid getting a IncompatibleClassChangeError.
                invocationCode = Opcodes.INVOKEVIRTUAL;
            }

        } else if (invocationType == MethodInvocation.InvocationType.SPECIAL) {
            invocationCode = Opcodes.INVOKESPECIAL;

        } else {
            throw new JavaGenerationException("Unknown invocation type: " + invocationType);
        }

    } else {
        //static invocation. No object reference needs to be pushed.            
        invocationCode = Opcodes.INVOKESTATIC;
        invocationClassType = ((MethodInvocation.Static) mi).getInvocationClass();
    }

    //push the arguments onto the stack

    for (int i = 0, nArgs = mi.getNArgs(); i < nArgs; ++i) {
        encodeExpr(mi.getArg(i), context);
    }

    //invoke the method                            
    context.getMethodVisitor().visitMethodInsn(invocationCode, invocationClassType.getJVMInternalName(),
            mi.getMethodName(), mi.getJVMMethodDescriptor());

    return mi.getReturnType();
}