Example usage for org.objectweb.asm Opcodes CHECKCAST

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

Introduction

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

Prototype

int CHECKCAST

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

Click Source Link

Usage

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

License:Open Source License

/**
 * Create the Java code for a given cast expression. This will cause the resulting casted object reference to
 * be pushed onto the operand stack.//from w  ww .  j  av a2s. c o  m
 *  
 * @param castExpression the cast expression
 * @param context  
 * @return JavaTypeName the type of the result on the operand stack.        
 * @throws JavaGenerationException
 */
private static JavaTypeName encodeCastExpr(JavaExpression.CastExpression castExpression,
        GenerationContext context) throws JavaGenerationException {

    MethodVisitor mv = context.getMethodVisitor();

    final JavaTypeName expressionToCastType = encodeExpr(castExpression.getExpressionToCast(), context);
    final JavaTypeName castType = castExpression.getCastType();

    if (expressionToCastType.equals(castType)) {
        //no operation needed if the types are the same.
        return castType;
    }

    if (castType instanceof JavaTypeName.Reference) {
        //when the cast type is a object or array type, use the CHECKCAST instruction. This will fail bytecode verification if 
        //the expressionToCast type is a primitive type

        mv.visitTypeInsn(Opcodes.CHECKCAST, castType.getJVMInternalName());
        return castType;
    }

    //casting between primitive types.
    //There are 15 supported primitive conversions: I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S
    //Depending upon the expressionToCastType and castType, choose the appropriate instruction.

    final int conversionOpCode;
    switch (expressionToCastType.getTag()) {

    case JavaTypeName.VOID_TAG:
    case JavaTypeName.BOOLEAN_TAG:
        throw new JavaGenerationException("Unsupported primitive cast.");

    case JavaTypeName.BYTE_TAG: {
        switch (castType.getTag()) {

        case JavaTypeName.VOID_TAG:
        case JavaTypeName.BOOLEAN_TAG:
            throw new JavaGenerationException("Unsupported primitive cast.");

        case JavaTypeName.BYTE_TAG:
            //should be handled above as a no-op.
            throw new IllegalArgumentException();

        case JavaTypeName.SHORT_TAG:
            conversionOpCode = Opcodes.I2S;
            break;

        case JavaTypeName.CHAR_TAG:
            conversionOpCode = Opcodes.I2C;
            break;

        case JavaTypeName.INT_TAG:
            //no-op
            return castType;

        case JavaTypeName.LONG_TAG:
            conversionOpCode = Opcodes.I2L;
            break;

        case JavaTypeName.DOUBLE_TAG:
            conversionOpCode = Opcodes.I2D;
            break;

        case JavaTypeName.FLOAT_TAG:
            conversionOpCode = Opcodes.I2F;
            break;

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG:
            throw new JavaGenerationException("Cannot cast a primitive type to a reference type.");

        default: {
            throw new IllegalArgumentException();
        }
        }

        break;
    }

    case JavaTypeName.SHORT_TAG: {
        switch (castType.getTag()) {

        case JavaTypeName.VOID_TAG:
        case JavaTypeName.BOOLEAN_TAG:
            throw new JavaGenerationException("Unsupported primitive cast.");

        case JavaTypeName.BYTE_TAG:
            conversionOpCode = Opcodes.I2B;
            break;

        case JavaTypeName.SHORT_TAG:
            //should be handled above as a no-op.
            throw new IllegalArgumentException();

        case JavaTypeName.CHAR_TAG:
            conversionOpCode = Opcodes.I2C;
            break;

        case JavaTypeName.INT_TAG:
            //no-op
            return castType;

        case JavaTypeName.LONG_TAG:
            conversionOpCode = Opcodes.I2L;
            break;

        case JavaTypeName.DOUBLE_TAG:
            conversionOpCode = Opcodes.I2D;
            break;

        case JavaTypeName.FLOAT_TAG:
            conversionOpCode = Opcodes.I2F;
            break;

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG:
            throw new JavaGenerationException("Cannot cast a primitive type to a reference type.");

        default: {
            throw new IllegalArgumentException();
        }
        }

        break;
    }

    case JavaTypeName.CHAR_TAG: {
        switch (castType.getTag()) {

        case JavaTypeName.VOID_TAG:
        case JavaTypeName.BOOLEAN_TAG:
            throw new JavaGenerationException("Unsupported primitive cast.");

        case JavaTypeName.BYTE_TAG:
            conversionOpCode = Opcodes.I2B;
            break;

        case JavaTypeName.SHORT_TAG:
            conversionOpCode = Opcodes.I2S;
            break;

        case JavaTypeName.CHAR_TAG:
            //should be handled above as a no-op.
            throw new IllegalArgumentException();

        case JavaTypeName.INT_TAG:
            //no-op
            return castType;

        case JavaTypeName.LONG_TAG:
            conversionOpCode = Opcodes.I2L;
            break;

        case JavaTypeName.DOUBLE_TAG:
            conversionOpCode = Opcodes.I2D;
            break;

        case JavaTypeName.FLOAT_TAG:
            conversionOpCode = Opcodes.I2F;
            break;

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG:
            throw new JavaGenerationException("Cannot cast a primitive type to a reference type.");

        default: {
            throw new IllegalArgumentException();
        }
        }

        break;
    }

    case JavaTypeName.INT_TAG: {
        switch (castType.getTag()) {

        case JavaTypeName.VOID_TAG:
        case JavaTypeName.BOOLEAN_TAG:
            throw new JavaGenerationException("Unsupported primitive cast.");

        case JavaTypeName.BYTE_TAG:
            conversionOpCode = Opcodes.I2B;
            break;

        case JavaTypeName.SHORT_TAG:
            conversionOpCode = Opcodes.I2S;
            break;

        case JavaTypeName.CHAR_TAG:
            conversionOpCode = Opcodes.I2C;
            break;

        case JavaTypeName.INT_TAG:
            //should be handled above as a no-op.
            throw new IllegalArgumentException();

        case JavaTypeName.LONG_TAG:
            conversionOpCode = Opcodes.I2L;
            break;

        case JavaTypeName.DOUBLE_TAG:
            conversionOpCode = Opcodes.I2D;
            break;

        case JavaTypeName.FLOAT_TAG:
            conversionOpCode = Opcodes.I2F;
            break;

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG:
            throw new JavaGenerationException("Cannot cast a primitive type to a reference type.");

        default: {
            throw new IllegalArgumentException();
        }
        }

        break;
    }

    case JavaTypeName.LONG_TAG: {
        switch (castType.getTag()) {

        case JavaTypeName.VOID_TAG:
        case JavaTypeName.BOOLEAN_TAG:
            throw new JavaGenerationException("Unsupported primitive cast.");

        case JavaTypeName.BYTE_TAG:
            mv.visitInsn(Opcodes.L2I);
            conversionOpCode = Opcodes.I2B;
            break;

        case JavaTypeName.SHORT_TAG:
            mv.visitInsn(Opcodes.L2I);
            conversionOpCode = Opcodes.I2S;
            break;

        case JavaTypeName.CHAR_TAG:
            mv.visitInsn(Opcodes.L2I);
            conversionOpCode = Opcodes.I2C;
            break;

        case JavaTypeName.INT_TAG:
            conversionOpCode = Opcodes.L2I;
            break;

        case JavaTypeName.LONG_TAG:
            //should be handled above as a no-op.
            throw new IllegalArgumentException();

        case JavaTypeName.DOUBLE_TAG:
            conversionOpCode = Opcodes.L2D;
            break;

        case JavaTypeName.FLOAT_TAG:
            conversionOpCode = Opcodes.L2F;
            break;

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG:
            throw new JavaGenerationException("Cannot cast a primitive type to a reference type.");

        default: {
            throw new IllegalArgumentException();
        }
        }

        break;
    }

    case JavaTypeName.DOUBLE_TAG: {
        switch (castType.getTag()) {

        case JavaTypeName.VOID_TAG:
        case JavaTypeName.BOOLEAN_TAG:
            throw new JavaGenerationException("Unsupported primitive cast.");

        case JavaTypeName.BYTE_TAG:
            mv.visitInsn(Opcodes.D2I);
            conversionOpCode = Opcodes.I2B;
            break;

        case JavaTypeName.SHORT_TAG:
            mv.visitInsn(Opcodes.D2I);
            conversionOpCode = Opcodes.I2S;
            break;

        case JavaTypeName.CHAR_TAG:
            mv.visitInsn(Opcodes.D2I);
            conversionOpCode = Opcodes.I2C;
            break;

        case JavaTypeName.INT_TAG:
            conversionOpCode = Opcodes.D2I;
            break;

        case JavaTypeName.LONG_TAG:
            conversionOpCode = Opcodes.D2L;
            break;

        case JavaTypeName.DOUBLE_TAG:
            //should be handled above as a no-op.
            throw new IllegalArgumentException();

        case JavaTypeName.FLOAT_TAG:
            conversionOpCode = Opcodes.D2F;
            break;

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG:
            throw new JavaGenerationException("Cannot cast a primitive type to a reference type.");

        default: {
            throw new IllegalArgumentException();
        }
        }

        break;
    }

    case JavaTypeName.FLOAT_TAG: {
        switch (castType.getTag()) {

        case JavaTypeName.VOID_TAG:
        case JavaTypeName.BOOLEAN_TAG:
            throw new JavaGenerationException("Unsupported primitive cast.");

        case JavaTypeName.BYTE_TAG:
            mv.visitInsn(Opcodes.F2I);
            conversionOpCode = Opcodes.I2B;
            break;

        case JavaTypeName.SHORT_TAG:
            mv.visitInsn(Opcodes.F2I);
            conversionOpCode = Opcodes.I2S;
            break;

        case JavaTypeName.CHAR_TAG:
            mv.visitInsn(Opcodes.F2I);
            conversionOpCode = Opcodes.I2C;
            break;

        case JavaTypeName.INT_TAG:
            conversionOpCode = Opcodes.F2I;
            break;

        case JavaTypeName.LONG_TAG:
            conversionOpCode = Opcodes.F2L;
            break;

        case JavaTypeName.DOUBLE_TAG:
            conversionOpCode = Opcodes.F2D;
            break;

        case JavaTypeName.FLOAT_TAG:
            //should be handled above as a no-op.
            throw new IllegalArgumentException();

        case JavaTypeName.ARRAY_TAG:
        case JavaTypeName.OBJECT_TAG:
            throw new JavaGenerationException("Cannot cast a primitive type to a reference type.");

        default: {
            throw new IllegalArgumentException();
        }
        }

        break;
    }

    case JavaTypeName.ARRAY_TAG:
    case JavaTypeName.OBJECT_TAG:
        throw new JavaGenerationException("Cannot cast a reference type to a primitive type.");

    default: {
        throw new IllegalArgumentException();
    }
    }

    mv.visitInsn(conversionOpCode);
    return castType;
}

From source file:org.sonar.java.bytecode.se.BytecodeEGWalkerExecuteTest.java

License:Open Source License

@Test
public void test_checkcast() throws Exception {
    SymbolicValue objectRef = new SymbolicValue();
    ProgramState programState = execute(new Instruction(Opcodes.CHECKCAST),
            ProgramState.EMPTY_STATE.stackValue(objectRef));
    assertThat(programState.peekValue()).isEqualTo(objectRef);

    assertThatThrownBy(() -> execute(new Instruction(Opcodes.CHECKCAST), ProgramState.EMPTY_STATE))
            .hasMessage("CHECKCAST needs 1 value on stack");
}

From source file:org.spongepowered.asm.mixin.injection.callback.CallbackInjector.java

License:MIT License

/**
 * Inject the appropriate return code for the method type
 * /* ww  w. j ava 2  s .c  om*/
 * @param callback callback handle
 */
protected void injectReturnCode(final Callback callback) {
    if (callback.target.returnType.equals(Type.VOID_TYPE)) {
        // Void method, so just return void
        callback.add(new InsnNode(Opcodes.RETURN));
    } else {
        // Non-void method, so work out which accessor to call to get the
        // return value, and return it
        callback.add(new VarInsnNode(Opcodes.ALOAD, callback.marshallVar));
        String accessor = CallbackInfoReturnable.getReturnAccessor(callback.target.returnType);
        String descriptor = CallbackInfoReturnable.getReturnDescriptor(callback.target.returnType);
        callback.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, callback.target.callbackInfoClass, accessor,
                descriptor, false));
        if (callback.target.returnType.getSort() == Type.OBJECT) {
            callback.add(new TypeInsnNode(Opcodes.CHECKCAST, callback.target.returnType.getInternalName()));
        }
        callback.add(new InsnNode(callback.target.returnType.getOpcode(Opcodes.IRETURN)));
    }
}

From source file:org.spongepowered.despector.emitter.bytecode.instruction.BytecodeCastEmitter.java

License:Open Source License

@Override
public void emit(BytecodeEmitterContext ctx, Cast arg, TypeSignature type) {
    MethodVisitor mv = ctx.getMethodVisitor();
    ctx.emitInstruction(arg.getValue(), null);
    TypeSignature to = arg.getType();/*w  w  w.  ja  v  a2  s  .com*/
    TypeSignature from = arg.getValue().inferType();
    if (to == ClassTypeSignature.INT) {
        if (from == ClassTypeSignature.LONG) {
            mv.visitInsn(Opcodes.L2I);
        } else if (from == ClassTypeSignature.FLOAT) {
            mv.visitInsn(Opcodes.F2I);
        } else if (from == ClassTypeSignature.DOUBLE) {
            mv.visitInsn(Opcodes.D2I);
        }
    } else if (to == ClassTypeSignature.LONG) {
        if (from == ClassTypeSignature.INT) {
            mv.visitInsn(Opcodes.I2L);
        } else if (from == ClassTypeSignature.FLOAT) {
            mv.visitInsn(Opcodes.F2L);
        } else if (from == ClassTypeSignature.DOUBLE) {
            mv.visitInsn(Opcodes.D2L);
        }
    } else if (to == ClassTypeSignature.FLOAT) {
        if (from == ClassTypeSignature.LONG) {
            mv.visitInsn(Opcodes.L2F);
        } else if (from == ClassTypeSignature.INT) {
            mv.visitInsn(Opcodes.I2F);
        } else if (from == ClassTypeSignature.DOUBLE) {
            mv.visitInsn(Opcodes.D2F);
        }
    } else if (to == ClassTypeSignature.DOUBLE) {
        if (from == ClassTypeSignature.LONG) {
            mv.visitInsn(Opcodes.L2D);
        } else if (from == ClassTypeSignature.FLOAT) {
            mv.visitInsn(Opcodes.F2D);
        } else if (from == ClassTypeSignature.INT) {
            mv.visitInsn(Opcodes.I2D);
        }
    }
    mv.visitTypeInsn(Opcodes.CHECKCAST, to.getDescriptor());
}

From source file:org.spongepowered.mod.asm.util.ASMEventListenerFactory.java

License:MIT License

@SuppressWarnings("unchecked")
private static <T> Class<T> createClass(Class<T> interf, Method input, Method output) {

    String className = getClassName(interf, input, output);

    ClassWriter cwBase = new ClassWriter(0);
    CheckClassAdapter cw = new CheckClassAdapter(cwBase);

    MethodVisitor mv;/*from   w ww.  ja  v  a  2  s.c o  m*/

    String classNameDesc = className.replace('.', '/');

    String interfaceInternalName = Type.getInternalName(interf);

    String inputName = input.getName();
    String inputMethodDescriptor = Type.getMethodDescriptor(input);

    String outputParameterTypeIntName = Type.getInternalName(output.getParameterTypes()[0]);
    String outputTargetTypeIntName = Type.getInternalName(output.getDeclaringClass());
    String outputMethodDescriptor = Type.getMethodDescriptor(output);
    String outputName = output.getName();

    boolean isOutputInterface = output.getDeclaringClass().isInterface();

    // A new class of the following form is created, with a unique name
    //
    // package org.spongepowered.mod.asm;
    // public class <className> extends java.lang.Object implements <interf>
    //
    //     private final Object target
    //
    //     public <className> (java.lang.Object target) {
    //         super();
    //         this.target = target;
    //         return;
    //     }
    //
    //     public void <inputMethod> (<inputMethodType event) {
    //         ((outputTargetType) this.target).outputMethod((outputParameteType) event);
    //         return
    //     }
    // }

    // package org.spongepowered.mod.asm;
    // public class <className> extends java.lang.Object implements <interf>
    cw.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER, classNameDesc, null, "java/lang/Object",
            new String[] { interfaceInternalName });

    // private final Object target
    cw.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL, "target", "Ljava/lang/Object;", null, null);

    // Constructor

    // public UniqueClass (java.lang.Object target) {
    mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "(Ljava/lang/Object;)V", null, null);
    mv.visitCode();

    // super();
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);

    // this.target = target;
    mv.visitVarInsn(Opcodes.ALOAD, 0); // Loads this
    mv.visitVarInsn(Opcodes.ALOAD, 1); // Loads target (from input)
    mv.visitFieldInsn(Opcodes.PUTFIELD, classNameDesc, "target", "Ljava/lang/Object;");

    // return;
    mv.visitInsn(Opcodes.RETURN);

    // }
    // 2 localvars due to inputs: this, target
    // 2 items on stack after double ALOAD
    mv.visitMaxs(2, 2);
    mv.visitEnd();

    // Callback method

    // public void <inputMethod> (<inputMethodType event) {
    mv = cw.visitMethod(Opcodes.ACC_PUBLIC, inputName, inputMethodDescriptor, null, null);
    mv.visitCode();

    // push((casted) this.target)
    mv.visitVarInsn(Opcodes.ALOAD, 0); // Loads this
    mv.visitFieldInsn(Opcodes.GETFIELD, classNameDesc, "target", "Ljava/lang/Object;");
    mv.visitTypeInsn(Opcodes.CHECKCAST, outputTargetTypeIntName);

    // push((casted) event)
    mv.visitVarInsn(Opcodes.ALOAD, 1); // Loads method parameter 0
    mv.visitTypeInsn(Opcodes.CHECKCAST, outputParameterTypeIntName);

    // ((outputTargetType) this.target).outputMethod((outputParameteType) event);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, outputTargetTypeIntName, outputName, outputMethodDescriptor,
            isOutputInterface);

    // return
    mv.visitInsn(Opcodes.RETURN);

    // }
    mv.visitMaxs(2, 2);
    mv.visitEnd();

    cw.visitEnd();

    byte[] bytes = cwBase.toByteArray();

    return (Class<T>) loader.defineClass(className, bytes);
}

From source file:org.springsource.loaded.test.infra.MethodPrinter.java

License:Apache License

public void visitTypeInsn(int opcode, String type) {
    if (opcode == Opcodes.NEW) { // 187
        to.println("    NEW " + type);
    } else if (opcode == Opcodes.ANEWARRAY) { // 189
        to.println("    ANEWARRAY " + type);
    } else if (opcode == Opcodes.CHECKCAST) { // 192
        to.println("    CHECKCAST " + type);
    } else if (opcode == Opcodes.INSTANCEOF) { // 193
        to.println("    INSTANCEOF " + type);
    } else {/*from  w w  w.  j a va 2  s .  co  m*/
        throw new IllegalStateException(":" + opcode);
    }
}

From source file:org.zoeey.ztpl.compiler.ByteCodeHelper.java

License:LGPL

/**
 * Writer??/*from  w  w  w . j a  va 2  s .c  o m*/
 * @param key ????
 */
public void writeVar(String key) {
    mv.visitVarInsn(Opcodes.ALOAD, VAR_INDEX_WRITER);
    getContext(key);
    mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/CharSequence");
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/Writer"//
            , "append", "(Ljava/lang/CharSequence;)Ljava/io/Writer;");
    mv.visitInsn(Opcodes.POP);
}

From source file:org.zoeey.ztpl.compiler.ByteCodeHelper.java

License:LGPL

/**
 * WriterContext??/*from  w w  w.  j a va2s.c  o  m*/
 * @param pos ???
 */
public void writeVar(int pos) {
    mv.visitVarInsn(Opcodes.ALOAD, VAR_INDEX_WRITER);
    mv.visitVarInsn(Opcodes.ALOAD, pos);
    mv.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/CharSequence");
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/Writer"//
            , "append", "(Ljava/lang/CharSequence;)Ljava/io/Writer;");
    mv.visitInsn(Opcodes.POP);
}

From source file:pl.clareo.coroutines.core.ClassTransformer.java

License:Apache License

@SuppressWarnings("unchecked")
void transform() {
    for (MethodNode coroutine : coroutines) {
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Generating method for coroutine " + coroutine.name + coroutine.desc);
        }/* w  w  w  .j  a va 2 s .  c o  m*/
        String coroutineName = getCoroutineName(coroutine);
        MethodTransformer methodTransformer = new MethodTransformer(coroutine, thisType);
        MethodNode coroutineImpl = methodTransformer.transform(coroutineName, generateDebugCode);
        thisNode.methods.add(coroutineImpl);
        /*
         * generate co iterators and method stubs
         */
        log.finest("Generating CoIterator implementation and method stubs");
        String baseCoIteratorName;
        Map<String, Object> annotation = getCoroutineAnnotationValues(coroutine);
        if (getBoolean(annotation, "threadLocal")) {
            baseCoIteratorName = Type.getInternalName(ThreadLocalCoIterator.class);
        } else {
            baseCoIteratorName = Type.getInternalName(SingleThreadedCoIterator.class);
        }
        String coIteratorClassName = "pl/clareo/coroutines/core/CoIterator" + num;
        ClassNode coIteratorClass = new ClassNode();
        coIteratorClass.version = Opcodes.V1_6;
        coIteratorClass.access = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_SUPER;
        coIteratorClass.name = coIteratorClassName;
        coIteratorClass.superName = baseCoIteratorName;
        if (generateDebugCode) {
            /*
             * If debugging code is emitted create field keeping JDK logger
             */
            FieldNode loggerField = new FieldNode(Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC,
                    "logger", "Ljava/util/logging/Logger;", null, null);
            coIteratorClass.fields.add(loggerField);
            MethodNode clinit = new MethodNode();
            clinit.access = Opcodes.ACC_STATIC;
            clinit.name = "<clinit>";
            clinit.desc = "()V";
            clinit.exceptions = Collections.EMPTY_LIST;
            String loggerName = thisType.getClassName();
            InsnList clinitCode = clinit.instructions;
            clinitCode.add(new LdcInsnNode(loggerName));
            clinitCode.add(new MethodInsnNode(Opcodes.INVOKESTATIC, "java/util/logging/Logger", "getLogger",
                    "(Ljava/lang/String;)Ljava/util/logging/Logger;"));
            clinitCode.add(new FieldInsnNode(Opcodes.PUTSTATIC, coIteratorClassName, "logger",
                    "Ljava/util/logging/Logger;"));
            clinitCode.add(new InsnNode(Opcodes.RETURN));
            clinit.maxStack = 1;
            clinit.maxLocals = 0;
            coIteratorClass.methods.add(clinit);
        }
        /*
         * Generate constructor
         */
        MethodNode init = new MethodNode();
        init.access = Opcodes.ACC_PUBLIC;
        init.name = "<init>";
        init.desc = CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR;
        init.exceptions = Collections.EMPTY_LIST;
        InsnList initCode = init.instructions;
        initCode.add(new VarInsnNode(Opcodes.ALOAD, 0));
        initCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
        initCode.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, baseCoIteratorName, "<init>",
                CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR));
        initCode.add(new InsnNode(Opcodes.RETURN));
        init.maxStack = 2;
        init.maxLocals = 2;
        coIteratorClass.methods.add(init);
        /*
         * Generate overriden call to coroutine
         */
        MethodNode call = new MethodNode();
        call.access = Opcodes.ACC_PROTECTED;
        call.name = "call";
        call.desc = CALL_METHOD_DESCRIPTOR;
        call.exceptions = Collections.EMPTY_LIST;
        InsnList callCode = call.instructions;
        /*
         * if debug needed generate call details
         */
        if (generateDebugCode) {
            String coroutineId = "Coroutine " + coroutine.name;
            callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER,
                    coroutineId + " call. Caller sent: ", 2));
            callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK));
            callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINEST,
                    coroutineId + " state ", 1));
            callCode.add(new FrameNode(Opcodes.F_SAME, 0, EMPTY_LOCALS, 0, EMPTY_STACK));
        }
        /*
         * push call arguments: this (if not static), frame, input, output
         */
        boolean isStatic = (coroutine.access & Opcodes.ACC_STATIC) != 0;
        if (!isStatic) {
            callCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
            callCode.add(
                    new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getThis", "()Ljava/lang/Object;"));
            callCode.add(new TypeInsnNode(Opcodes.CHECKCAST, thisType.getInternalName()));
        }
        callCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
        callCode.add(new InsnNode(Opcodes.ACONST_NULL));
        callCode.add(new VarInsnNode(Opcodes.ALOAD, 2));
        callCode.add(new MethodInsnNode(isStatic ? Opcodes.INVOKESTATIC : Opcodes.INVOKEVIRTUAL,
                thisType.getInternalName(), coroutineName, COROUTINE_METHOD_DESCRIPTOR));
        // stack: *
        if (!generateDebugCode) {
            callCode.add(new InsnNode(Opcodes.ARETURN));
        } else {
            // save result display suspension point (two more locals
            // needed)
            callCode.add(new VarInsnNode(Opcodes.ASTORE, 3));
            callCode.add(new VarInsnNode(Opcodes.ALOAD, 1));
            callCode.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLineOfCode", "()I"));
            callCode.add(box_int(Type.INT));
            callCode.add(new VarInsnNode(Opcodes.ASTORE, 4));
            callCode.add(loggingInstructions(coIteratorClassName, "logger", Level.FINER,
                    "Coroutine suspended at line ", 4, ". Yielded:", 3));
            callCode.add(new FrameNode(Opcodes.F_APPEND, 2,
                    new Object[] { "java/lang/Object", "java/lang/Integer" }, 0, EMPTY_STACK));
            callCode.add(new VarInsnNode(Opcodes.ALOAD, 3));
            callCode.add(new InsnNode(Opcodes.ARETURN));
        }
        coIteratorClass.methods.add(call);
        // if debugging code is emitted it needs space for two
        // additional locals and 5 stack operand
        if (generateDebugCode) {
            call.maxStack = 5;
            call.maxLocals = 5;
        } else {
            if (isStatic) {
                call.maxStack = 3;
            } else {
                call.maxStack = 4;
            }
            call.maxLocals = 3;
        }
        /*
         * CoIterator created - define it in the runtime and verify if
         * needed
         */
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Generated class " + coIteratorClassName);
        }
        ClassWriter cw = new ClassWriter(0);
        coIteratorClass.accept(cw);
        byte[] classBytes = cw.toByteArray();
        try {
            CoroutineInstrumentator.dumpClass(coIteratorClassName, classBytes);
        } catch (IOException e) {
            throw new CoroutineGenerationException("Unable to write class " + coIteratorClassName, e);
        }
        /*
         * start generating method - new method is named as the method in
         * user code, it: returns instance of appropriate CoIterator (see
         * above), saves arguments of call
         */
        if (log.isLoggable(Level.FINEST)) {
            log.finest("Instrumenting method " + coroutine.name);
        }
        InsnList code = coroutine.instructions;
        code.clear();
        /*
         * create new Frame
         */
        boolean isDebugFramePossible = generateDebugCode && coroutine.localVariables != null;
        if (isDebugFramePossible) {
            code.add(createDebugFrame(coroutine));
        } else {
            code.add(createFrame(coroutine));
        }
        /*
         * save frame in the first, and locals array in the second local
         * variable
         */
        int argsSize = Type.getArgumentsAndReturnSizes(coroutine.desc) >> 2;
        if (isStatic) {
            argsSize -= 1;
        }
        code.add(new VarInsnNode(Opcodes.ASTORE, argsSize));
        code.add(new VarInsnNode(Opcodes.ALOAD, argsSize));
        code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, FRAME_NAME, "getLocals", "()[Ljava/lang/Object;"));
        int localsArrayIndex = argsSize + 1;
        code.add(new VarInsnNode(Opcodes.ASTORE, localsArrayIndex));
        /*
         * save all call arguments (along with this if this method is not
         * static) into locals array
         */
        Type[] argsTypes = Type.getArgumentTypes(coroutine.desc);
        if (!isStatic) {
            code.add(saveloc(localsArrayIndex, 0, 0, JAVA_LANG_OBJECT));
            code.add(savelocs(localsArrayIndex, 1, 1, argsTypes));
        } else {
            code.add(savelocs(localsArrayIndex, 0, 0, argsTypes));
        }
        /*
         * create CoIterator instance with saved frame, make initial call to
         * next if needed and return to caller
         */
        code.add(new TypeInsnNode(Opcodes.NEW, coIteratorClassName));
        code.add(new InsnNode(Opcodes.DUP));
        code.add(new VarInsnNode(Opcodes.ALOAD, argsSize));
        code.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, coIteratorClassName, "<init>",
                CO_ITERATOR_CONSTRUCTOR_DESCRIPTOR));
        if (!getBoolean(annotation, "generator", true)) {
            code.add(new InsnNode(Opcodes.DUP));
            code.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, coIteratorClassName, "next",
                    "()Ljava/lang/Object;"));
            code.add(new InsnNode(Opcodes.POP));
        }
        code.add(new InsnNode(Opcodes.ARETURN));
        /*
         * end method generation; maxs can be statically determined 3
         * operands on stack (call to frame setLocals and CoIterator
         * constructor) + 1 if any argument is long or double (debug frame
         * needs 7 operands for variable names creation); locals = argsSize
         * + 1 reference to frame + 1 array of locals
         */
        if (isDebugFramePossible) {
            coroutine.maxStack = 7;
        } else {
            boolean isCategory2ArgumentPresent = false;
            for (Type argType : argsTypes) {
                int sort = argType.getSort();
                if (sort == Type.LONG || sort == Type.DOUBLE) {
                    isCategory2ArgumentPresent = true;
                    break;
                }
            }
            coroutine.maxStack = isCategory2ArgumentPresent ? 4 : 3;
        }
        coroutine.maxLocals = localsArrayIndex + 1;
        coroutine.localVariables.clear();
        coroutine.tryCatchBlocks.clear();
        num++;
    }
}

From source file:serianalyzer.JVMImpl.java

License:Open Source License

/**
 * @param opcode//from  www . j a v  a 2s . c om
 * @param type
 * @param s
 */
static void handleJVMTypeInsn(int opcode, String type, JVMStackState s) {
    BaseType o;
    switch (opcode) {
    case Opcodes.NEW:
        s.push(new ObjectReferenceConstant(false, Type.getObjectType(type), type.replace('/', '.')));
        break;
    case Opcodes.ANEWARRAY:
        s.pop();
        if (type.charAt(0) == '[') {
            s.push(new BasicVariable(Type.getObjectType("[" + type), "array", false)); //$NON-NLS-1$//$NON-NLS-2$
        } else {
            s.push(new BasicVariable(Type.getObjectType("[L" + type + ";"), "array", false)); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
        }
        break;
    case Opcodes.CHECKCAST:
        if (log.isDebugEnabled()) {
            log.debug("Checkcast " + type); //$NON-NLS-1$
        }
        o = s.pop();
        if (o != null) {
            o.addAlternativeType(Type.getObjectType(type));
            s.push(o);
        } else {
            s.clear();
        }
        break;
    case Opcodes.INSTANCEOF:
        o = s.pop();
        if (o != null) {
            o.addAlternativeType(Type.getObjectType(type));
        }
        s.push(new BasicConstant(Type.BOOLEAN_TYPE, "typeof " + o + " = " + type, //$NON-NLS-1$//$NON-NLS-2$
                !(o != null) || o.isTainted()));
        break;
    }
}