Example usage for org.objectweb.asm.commons InstructionAdapter areturn

List of usage examples for org.objectweb.asm.commons InstructionAdapter areturn

Introduction

In this page you can find the example usage for org.objectweb.asm.commons InstructionAdapter areturn.

Prototype

public void areturn(final Type type) 

Source Link

Usage

From source file:com.gargoylesoftware.js.nashorn.internal.runtime.linker.JavaAdapterBytecodeGenerator.java

License:Open Source License

/**
 * Generates a method in the adapter class that adapts a method from the original class. The generated methods will
 * inspect the method handle field assigned to them. If it is null (the JS object doesn't provide an implementation
 * for the method) then it will either invoke its version in the supertype, or if it is abstract, throw an
 * {@link UnsupportedOperationException}. Otherwise, if the method handle field's value is not null, the handle is
 * invoked using invokeExact (signature polymorphic invocation as per JLS 15.12.3). Before the invocation, the
 * current Nashorn {@link Context} is checked, and if it is different than the global used to create the adapter
 * instance, the creating global is set to be the current global. In this case, the previously current global is
 * restored after the invocation. If invokeExact results in a Throwable that is not one of the method's declared
 * exceptions, and is not an unchecked throwable, then it is wrapped into a {@link RuntimeException} and the runtime
 * exception is thrown. The method handle retrieved from the field is guaranteed to exactly match the signature of
 * the method; this is guaranteed by the way constructors of the adapter class obtain them using
 * {@link #getHandle(Object, String, MethodType, boolean)}.
 * @param mi the method info describing the method to be generated.
 *//*from w ww  . j av  a 2  s.  c o  m*/
private void generateMethod(final MethodInfo mi) {
    final Method method = mi.method;
    final Class<?>[] exceptions = method.getExceptionTypes();
    final String[] exceptionNames = getExceptionNames(exceptions);
    final MethodType type = mi.type;
    final String methodDesc = type.toMethodDescriptorString();
    final String name = mi.getName();

    final Type asmType = Type.getMethodType(methodDesc);
    final Type[] asmArgTypes = asmType.getArgumentTypes();

    final InstructionAdapter mv = new InstructionAdapter(
            cw.visitMethod(getAccessModifiers(method), name, methodDesc, null, exceptionNames));
    mv.visitCode();

    final Label handleDefined = new Label();

    final Class<?> returnType = type.returnType();
    final Type asmReturnType = Type.getType(returnType);

    // See if we have overriding method handle defined
    if (classOverride) {
        mv.getstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
    } else {
        mv.visitVarInsn(ALOAD, 0);
        mv.getfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
    }
    // stack: [handle]
    mv.visitInsn(DUP);
    mv.visitJumpInsn(IFNONNULL, handleDefined);

    // No handle is available, fall back to default behavior
    if (Modifier.isAbstract(method.getModifiers())) {
        // If the super method is abstract, throw an exception
        mv.anew(UNSUPPORTED_OPERATION_TYPE);
        mv.dup();
        mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR, false);
        mv.athrow();
    } else {
        mv.visitInsn(POP);
        // If the super method is not abstract, delegate to it.
        emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
    }

    mv.visitLabel(handleDefined);
    // Load the creatingGlobal object
    if (classOverride) {
        // If class handle is defined, load the static defining global
        mv.getstatic(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
    } else {
        mv.visitVarInsn(ALOAD, 0);
        mv.getfield(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
    }
    // stack: [creatingGlobal, handle]
    final Label setupGlobal = new Label();
    mv.visitLabel(setupGlobal);

    // Determine the first index for a local variable
    int nextLocalVar = 1; // "this" is at 0
    for (final Type t : asmArgTypes) {
        nextLocalVar += t.getSize();
    }
    // Set our local variable indices
    final int currentGlobalVar = nextLocalVar++;
    final int globalsDifferVar = nextLocalVar++;

    mv.dup();
    // stack: [creatingGlobal, creatingGlobal, handle]

    // Emit code for switching to the creating global
    // Global currentGlobal = Context.getGlobal();
    invokeGetGlobal(mv);
    mv.dup();

    mv.visitVarInsn(ASTORE, currentGlobalVar);
    // stack: [currentGlobal, creatingGlobal, creatingGlobal, handle]
    // if(definingGlobal == currentGlobal) {
    final Label globalsDiffer = new Label();
    mv.ifacmpne(globalsDiffer);
    // stack: [creatingGlobal, handle]
    //     globalsDiffer = false
    mv.pop();
    // stack: [handle]
    mv.iconst(0); // false
    // stack: [false, handle]
    final Label invokeHandle = new Label();
    mv.goTo(invokeHandle);
    mv.visitLabel(globalsDiffer);
    // } else {
    //     Context.setGlobal(definingGlobal);
    // stack: [creatingGlobal, handle]
    invokeSetGlobal(mv);
    // stack: [handle]
    //     globalsDiffer = true
    mv.iconst(1);
    // stack: [true, handle]

    mv.visitLabel(invokeHandle);
    mv.visitVarInsn(ISTORE, globalsDifferVar);
    // stack: [handle]

    // Load all parameters back on stack for dynamic invocation. NOTE: since we're using a generic
    // Object(Object, Object, ...) type signature for the method, we must box all arguments here.
    int varOffset = 1;
    for (final Type t : asmArgTypes) {
        mv.load(varOffset, t);
        boxStackTop(mv, t);
        varOffset += t.getSize();
    }

    // Invoke the target method handle
    final Label tryBlockStart = new Label();
    mv.visitLabel(tryBlockStart);
    emitInvokeExact(mv, type.generic());
    convertReturnValue(mv, returnType, asmReturnType);
    final Label tryBlockEnd = new Label();
    mv.visitLabel(tryBlockEnd);
    emitFinally(mv, currentGlobalVar, globalsDifferVar);
    mv.areturn(asmReturnType);

    // If Throwable is not declared, we need an adapter from Throwable to RuntimeException
    final boolean throwableDeclared = isThrowableDeclared(exceptions);
    final Label throwableHandler;
    if (!throwableDeclared) {
        // Add "throw new RuntimeException(Throwable)" handler for Throwable
        throwableHandler = new Label();
        mv.visitLabel(throwableHandler);
        mv.anew(RUNTIME_EXCEPTION_TYPE);
        mv.dupX1();
        mv.swap();
        mv.invokespecial(RUNTIME_EXCEPTION_TYPE_NAME, INIT,
                Type.getMethodDescriptor(Type.VOID_TYPE, THROWABLE_TYPE), false);
        // Fall through to rethrow handler
    } else {
        throwableHandler = null;
    }
    final Label rethrowHandler = new Label();
    mv.visitLabel(rethrowHandler);
    // Rethrow handler for RuntimeException, Error, and all declared exception types
    emitFinally(mv, currentGlobalVar, globalsDifferVar);
    mv.athrow();
    final Label methodEnd = new Label();
    mv.visitLabel(methodEnd);

    mv.visitLocalVariable("currentGlobal", GLOBAL_TYPE_DESCRIPTOR, null, setupGlobal, methodEnd,
            currentGlobalVar);
    mv.visitLocalVariable("globalsDiffer", Type.BOOLEAN_TYPE.getDescriptor(), null, setupGlobal, methodEnd,
            globalsDifferVar);

    if (throwableDeclared) {
        mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, THROWABLE_TYPE_NAME);
        assert throwableHandler == null;
    } else {
        mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, RUNTIME_EXCEPTION_TYPE_NAME);
        mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, ERROR_TYPE_NAME);
        for (final String excName : exceptionNames) {
            mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, excName);
        }
        mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, throwableHandler, THROWABLE_TYPE_NAME);
    }
    endMethod(mv);
}

From source file:com.gargoylesoftware.js.nashorn.internal.runtime.linker.JavaAdapterBytecodeGenerator.java

License:Open Source License

private void emitSuperCall(final InstructionAdapter mv, final Class<?> owner, final String name,
        final String methodDesc) {
    mv.visitVarInsn(ALOAD, 0);//  w  w  w.  j a v  a2 s.  c o  m
    int nextParam = 1;
    final Type methodType = Type.getMethodType(methodDesc);
    for (final Type t : methodType.getArgumentTypes()) {
        mv.load(nextParam, t);
        nextParam += t.getSize();
    }

    // default method - non-abstract, interface method
    if (Modifier.isInterface(owner.getModifiers())) {
        // we should call default method on the immediate "super" type - not on (possibly)
        // the indirectly inherited interface class!
        mv.invokespecial(Type.getInternalName(findInvokespecialOwnerFor(owner)), name, methodDesc, false);
    } else {
        mv.invokespecial(superClassName, name, methodDesc, false);
    }
    mv.areturn(methodType.getReturnType());
}

From source file:com.github.jasmo.obfuscate.ScrambleStrings.java

License:Open Source License

private void createStaticConstructor(ClassNode owner) throws UnsupportedEncodingException {
    MethodNode original = BytecodeHelper.getMethod(owner, "<clinit>", "()V");
    MethodVisitor mv = owner.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
    // generate instructions
    InstructionAdapter builder = new InstructionAdapter(mv);
    builder.iconst(stringList.size());//from w w w .j  a v a2s .  c om
    builder.newarray(Type.getType(String.class));
    for (int i = 0; i < stringList.size(); i++) {
        builder.dup();
        builder.iconst(i);
        builder.aconst(Base64.getEncoder().encodeToString(stringList.get(i).getBytes("UTF-8")));
        builder.astore(InstructionAdapter.OBJECT_TYPE);
    }
    builder.putstatic(unscrambleClass.name, FIELD_NAME, "[Ljava/lang/String;");
    // merge with original if it exists
    if (original != null) {
        // original should already end with RETURN
        owner.methods.remove(original);
        original.instructions.accept(builder);
    } else {
        builder.areturn(Type.VOID_TYPE);
    }
}

From source file:com.google.devtools.build.android.resources.RClassGenerator.java

License:Open Source License

private static void writeStaticClassInit(ClassWriter classWriter, String className,
        List<FieldInitializer> initializers) {
    MethodVisitor visitor = classWriter.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, /* signature */
            null /* exceptions */);
    visitor.visitCode();//from  w ww .  ja v a  2  s .c  o  m
    int stackSlotsNeeded = 0;
    InstructionAdapter insts = new InstructionAdapter(visitor);
    for (FieldInitializer fieldInit : initializers) {
        stackSlotsNeeded = Math.max(stackSlotsNeeded, fieldInit.writeCLInit(insts, className));
    }
    insts.areturn(Type.VOID_TYPE);
    visitor.visitMaxs(stackSlotsNeeded, 0);
    visitor.visitEnd();
}

From source file:com.google.devtools.build.android.resources.RClassWriter.java

License:Open Source License

private static void writeStaticClassInit(ClassWriter classWriter, String className,
        List<DeferredInitializer> deferredInitializers) {
    MethodVisitor visitor = classWriter.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
    visitor.visitCode();//from  w w w. ja v  a 2 s.c om
    int stackSlotsNeeded = 0;
    InstructionAdapter insts = new InstructionAdapter(visitor);
    for (DeferredInitializer fieldInit : deferredInitializers) {
        stackSlotsNeeded = Math.max(stackSlotsNeeded, fieldInit.writeCLInit(className, insts));
    }
    insts.areturn(Type.VOID_TYPE);
    visitor.visitMaxs(stackSlotsNeeded, 0);
    visitor.visitEnd();
}

From source file:edu.ubc.mirrors.holograms.HologramClassGenerator.java

License:Open Source License

@Override
public void visitEnd() {
    // Generate the static field used to store the corresponding ClassMirror
    int staticAccess = Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL | Opcodes.ACC_STATIC;
    super.visitField(staticAccess, "classMirror", classMirrorType.getDescriptor(), null, null);

    // Generate the constructor that takes a mirror instance as an Object parameter
    String constructorDesc = Type.getMethodDescriptor(Type.VOID_TYPE, Type.getType(Object.class));
    if (name.equals(getHologramType(Type.getType(Throwable.class), true).getInternalName())) {
        // This doesn't extend ObjectHologram so we have to set the field directly
        super.visitField(Opcodes.ACC_PUBLIC, "mirror", objectMirrorType.getDescriptor(), null, null);

        MethodVisitor methodVisitor = super.visitMethod(Opcodes.ACC_PUBLIC, "<init>", constructorDesc, null,
                null);//from w  ww  . ja  v  a2s  . c  om
        methodVisitor.visitCode();
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "<init>",
                Type.getMethodDescriptor(Type.VOID_TYPE));
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
        methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, objectMirrorType.getInternalName());
        methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, name, "mirror", Type.getDescriptor(ObjectMirror.class));
        methodVisitor.visitInsn(Opcodes.RETURN);
        methodVisitor.visitMaxs(2, 2);
        methodVisitor.visitEnd();

        methodVisitor = super.visitMethod(Opcodes.ACC_PUBLIC, "getMirror",
                Type.getMethodDescriptor(objectMirrorType), null, null);
        methodVisitor.visitCode();
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitFieldInsn(Opcodes.GETFIELD, name, "mirror", Type.getDescriptor(ObjectMirror.class));
        methodVisitor.visitInsn(Opcodes.ARETURN);
        methodVisitor.visitMaxs(1, 1);
        methodVisitor.visitEnd();
    } else if (!isInterface) {
        MethodVisitor methodVisitor = super.visitMethod(Opcodes.ACC_PUBLIC, "<init>", constructorDesc, null,
                null);
        methodVisitor.visitCode();
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "<init>", constructorDesc);
        methodVisitor.visitInsn(Opcodes.RETURN);
        methodVisitor.visitMaxs(2, 2);
        methodVisitor.visitEnd();
    }

    // Add a class initialization method to initialize the static fields,
    // if one doesn't exist already.
    if (!hasClinit) {
        InstructionAdapter mv = new InstructionAdapter(
                super.visitMethod(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "<clinit>", "()V", null, null));
        mv.visitCode();
        HologramMethodGenerator.initializeStaticFields(Type.getObjectType(this.name), mv);
        mv.areturn(Type.VOID_TYPE);
        mv.visitMaxs(2, 2);
        mv.visitEnd();
    }

    super.visitEnd();
}