Example usage for org.objectweb.asm Opcodes ALOAD

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

Introduction

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

Prototype

int ALOAD

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

Click Source Link

Usage

From source file:com.android.tools.layoutlib.create.DelegateMethodAdapter.java

License:Apache License

/**
 * Generates the new code for the method.
 * <p/>//from   w w w .ja  v  a2 s.co m
 * For native methods, this must be invoked directly by {@link DelegateClassAdapter}
 * (since they have no code to visit).
 * <p/>
 * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
 * return this instance of {@link DelegateMethodAdapter} and let the normal visitor pattern
 * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
 * this method will be invoked from {@link MethodVisitor#visitEnd()}.
 */
public void generateCode() {
    /*
     * The goal is to generate a call to a static delegate method.
     * If this method is non-static, the first parameter will be 'this'.
     * All the parameters must be passed and then the eventual return type returned.
     *
     * Example, let's say we have a method such as
     *   public void method_1(int a, Object b, ArrayList<String> c) { ... }
     *
     * We'll want to create a body that calls a delegate method like this:
     *   TheClass_Delegate.method_1(this, a, b, c);
     *
     * If the method is non-static and the class name is an inner class (e.g. has $ in its
     * last segment), we want to push the 'this' of the outer class first:
     *   OuterClass_InnerClass_Delegate.method_1(
     *     OuterClass.this,
     *     OuterClass$InnerClass.this,
     *     a, b, c);
     *
     * Only one level of inner class is supported right now, for simplicity and because
     * we don't need more.
     *
     * The generated class name is the current class name with "_Delegate" appended to it.
     * One thing to realize is that we don't care about generics -- since generic types
     * are erased at runtime, they have no influence on the method name being called.
     */

    // Add our annotation
    AnnotationVisitor aw = mParentVisitor.visitAnnotation(
            Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(), true); // visible at runtime
    aw.visitEnd();

    if (!mVisitCodeCalled) {
        // If this is a direct call to generateCode() as done by DelegateClassAdapter
        // for natives, visitCode() hasn't been called yet.
        mParentVisitor.visitCode();
        mVisitCodeCalled = true;
    }

    ArrayList<Type> paramTypes = new ArrayList<Type>();
    String delegateClassName = mClassName + DELEGATE_SUFFIX;
    boolean pushedArg0 = false;
    int maxStack = 0;

    // For an instance method (e.g. non-static), push the 'this' preceded
    // by the 'this' of any outer class, if any.
    if (!mIsStatic) {
        // Check if the last segment of the class name has inner an class.
        // Right now we only support one level of inner classes.
        int slash = mClassName.lastIndexOf('/');
        int dol = mClassName.lastIndexOf('$');
        if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
            String outerClass = mClassName.substring(0, dol);
            Type outerType = Type.getObjectType(outerClass);

            // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
            delegateClassName = delegateClassName.replace('$', '_');

            // The first-level inner class has a package-protected member called 'this$0'
            // that points to the outer class.

            // Push this.getField("this$0") on the call stack.
            mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this
            mParentVisitor.visitFieldInsn(Opcodes.GETFIELD, mClassName, // class where the field is defined
                    "this$0", // field name
                    outerType.getDescriptor()); // type of the field
            maxStack++;
            paramTypes.add(outerType);
        }

        // Push "this" for the instance method, which is always ALOAD 0
        mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        maxStack++;
        pushedArg0 = true;
        paramTypes.add(Type.getObjectType(mClassName));
    }

    // Push all other arguments. Start at arg 1 if we already pushed 'this' above.
    Type[] argTypes = Type.getArgumentTypes(mDesc);
    int maxLocals = pushedArg0 ? 1 : 0;
    for (Type t : argTypes) {
        int size = t.getSize();
        mParentVisitor.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals);
        maxLocals += size;
        maxStack += size;
        paramTypes.add(t);
    }

    // Construct the descriptor of the delegate based on the parameters
    // we pushed on the call stack. The return type remains unchanged.
    String desc = Type.getMethodDescriptor(Type.getReturnType(mDesc),
            paramTypes.toArray(new Type[paramTypes.size()]));

    // Invoke the static delegate
    mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, delegateClassName, mMethodName, desc);

    Type returnType = Type.getReturnType(mDesc);
    mParentVisitor.visitInsn(returnType.getOpcode(Opcodes.IRETURN));

    mParentVisitor.visitMaxs(maxStack, maxLocals);
    mParentVisitor.visitEnd();

    // For debugging now. Maybe we should collect these and store them in
    // a text file for helping create the delegates. We could also compare
    // the text file to a golden and break the build on unsupported changes
    // or regressions. Even better we could fancy-print something that looks
    // like the expected Java method declaration.
    mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc);
}

From source file:com.android.tools.layoutlib.create.DelegateMethodAdapter2.java

License:Apache License

/**
 * Generates the new code for the method.
 * <p/>/*from w w  w .j  a v a2  s .c  om*/
 * For native methods, this must be invoked directly by {@link DelegateClassAdapter}
 * (since they have no code to visit).
 * <p/>
 * Otherwise for non-native methods the {@link DelegateClassAdapter} simply needs to
 * return this instance of {@link DelegateMethodAdapter2} and let the normal visitor pattern
 * invoke it as part of the {@link ClassReader#accept(ClassVisitor, int)} workflow and then
 * this method will be invoked from {@link MethodVisitor#visitEnd()}.
 */
public void generateDelegateCode() {
    /*
     * The goal is to generate a call to a static delegate method.
     * If this method is non-static, the first parameter will be 'this'.
     * All the parameters must be passed and then the eventual return type returned.
     *
     * Example, let's say we have a method such as
     *   public void myMethod(int a, Object b, ArrayList<String> c) { ... }
     *
     * We'll want to create a body that calls a delegate method like this:
     *   TheClass_Delegate.myMethod(this, a, b, c);
     *
     * If the method is non-static and the class name is an inner class (e.g. has $ in its
     * last segment), we want to push the 'this' of the outer class first:
     *   OuterClass_InnerClass_Delegate.myMethod(
     *     OuterClass.this,
     *     OuterClass$InnerClass.this,
     *     a, b, c);
     *
     * Only one level of inner class is supported right now, for simplicity and because
     * we don't need more.
     *
     * The generated class name is the current class name with "_Delegate" appended to it.
     * One thing to realize is that we don't care about generics -- since generic types
     * are erased at build time, they have no influence on the method name being called.
     */

    // Add our annotation
    AnnotationVisitor aw = mDelWriter.visitAnnotation(
            Type.getObjectType(Type.getInternalName(LayoutlibDelegate.class)).toString(), true); // visible at runtime
    if (aw != null) {
        aw.visitEnd();
    }

    mDelWriter.visitCode();

    if (mDelegateLineNumber != null) {
        Object[] p = mDelegateLineNumber;
        mDelWriter.visitLineNumber((Integer) p[0], (Label) p[1]);
    }

    ArrayList<Type> paramTypes = new ArrayList<Type>();
    String delegateClassName = mClassName + DELEGATE_SUFFIX;
    boolean pushedArg0 = false;
    int maxStack = 0;

    // Check if the last segment of the class name has inner an class.
    // Right now we only support one level of inner classes.
    Type outerType = null;
    int slash = mClassName.lastIndexOf('/');
    int dol = mClassName.lastIndexOf('$');
    if (dol != -1 && dol > slash && dol == mClassName.indexOf('$')) {
        String outerClass = mClassName.substring(0, dol);
        outerType = Type.getObjectType(outerClass);

        // Change a delegate class name to "com/foo/Outer_Inner_Delegate"
        delegateClassName = delegateClassName.replace('$', '_');
    }

    // For an instance method (e.g. non-static), push the 'this' preceded
    // by the 'this' of any outer class, if any.
    if (!mIsStatic) {

        if (outerType != null) {
            // The first-level inner class has a package-protected member called 'this$0'
            // that points to the outer class.

            // Push this.getField("this$0") on the call stack.
            mDelWriter.visitVarInsn(Opcodes.ALOAD, 0); // var 0 = this
            mDelWriter.visitFieldInsn(Opcodes.GETFIELD, mClassName, // class where the field is defined
                    "this$0", // field name
                    outerType.getDescriptor()); // type of the field
            maxStack++;
            paramTypes.add(outerType);

        }

        // Push "this" for the instance method, which is always ALOAD 0
        mDelWriter.visitVarInsn(Opcodes.ALOAD, 0);
        maxStack++;
        pushedArg0 = true;
        paramTypes.add(Type.getObjectType(mClassName));
    }

    // Push all other arguments. Start at arg 1 if we already pushed 'this' above.
    Type[] argTypes = Type.getArgumentTypes(mDesc);
    int maxLocals = pushedArg0 ? 1 : 0;
    for (Type t : argTypes) {
        int size = t.getSize();
        mDelWriter.visitVarInsn(t.getOpcode(Opcodes.ILOAD), maxLocals);
        maxLocals += size;
        maxStack += size;
        paramTypes.add(t);
    }

    // Construct the descriptor of the delegate based on the parameters
    // we pushed on the call stack. The return type remains unchanged.
    String desc = Type.getMethodDescriptor(Type.getReturnType(mDesc),
            paramTypes.toArray(new Type[paramTypes.size()]));

    // Invoke the static delegate
    mDelWriter.visitMethodInsn(Opcodes.INVOKESTATIC, delegateClassName, mMethodName, desc);

    Type returnType = Type.getReturnType(mDesc);
    mDelWriter.visitInsn(returnType.getOpcode(Opcodes.IRETURN));

    mDelWriter.visitMaxs(maxStack, maxLocals);
    mDelWriter.visitEnd();

    // For debugging now. Maybe we should collect these and store them in
    // a text file for helping create the delegates. We could also compare
    // the text file to a golden and break the build on unsupported changes
    // or regressions. Even better we could fancy-print something that looks
    // like the expected Java method declaration.
    mLog.debug("Delegate: %1$s # %2$s %3$s", delegateClassName, mMethodName, desc);
}

From source file:com.android.tools.layoutlib.create.StubMethodAdapter.java

License:Apache License

private void generateInvoke() {
    /* Generates the code:
     *  OverrideMethod.invoke("signature", mIsNative ? true : false, null or this);
     *///www .j av a 2  s. co  m
    mParentVisitor.visitLdcInsn(mInvokeSignature);
    // push true or false
    mParentVisitor.visitInsn(mIsNative ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
    // push null or this
    if (mIsStatic) {
        mParentVisitor.visitInsn(Opcodes.ACONST_NULL);
    } else {
        mParentVisitor.visitVarInsn(Opcodes.ALOAD, 0);
    }

    int sort = mReturnType != null ? mReturnType.getSort() : Type.VOID;
    switch (sort) {
    case Type.VOID:
        mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                "com/android/tools/layoutlib/create/OverrideMethod", "invokeV",
                "(Ljava/lang/String;ZLjava/lang/Object;)V");
        mParentVisitor.visitInsn(Opcodes.RETURN);
        break;
    case Type.BOOLEAN:
    case Type.CHAR:
    case Type.BYTE:
    case Type.SHORT:
    case Type.INT:
        mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                "com/android/tools/layoutlib/create/OverrideMethod", "invokeI",
                "(Ljava/lang/String;ZLjava/lang/Object;)I");
        switch (sort) {
        case Type.BOOLEAN:
            Label l1 = new Label();
            mParentVisitor.visitJumpInsn(Opcodes.IFEQ, l1);
            mParentVisitor.visitInsn(Opcodes.ICONST_1);
            mParentVisitor.visitInsn(Opcodes.IRETURN);
            mParentVisitor.visitLabel(l1);
            mParentVisitor.visitInsn(Opcodes.ICONST_0);
            break;
        case Type.CHAR:
            mParentVisitor.visitInsn(Opcodes.I2C);
            break;
        case Type.BYTE:
            mParentVisitor.visitInsn(Opcodes.I2B);
            break;
        case Type.SHORT:
            mParentVisitor.visitInsn(Opcodes.I2S);
            break;
        }
        mParentVisitor.visitInsn(Opcodes.IRETURN);
        break;
    case Type.LONG:
        mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                "com/android/tools/layoutlib/create/OverrideMethod", "invokeL",
                "(Ljava/lang/String;ZLjava/lang/Object;)J");
        mParentVisitor.visitInsn(Opcodes.LRETURN);
        break;
    case Type.FLOAT:
        mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                "com/android/tools/layoutlib/create/OverrideMethod", "invokeF",
                "(Ljava/lang/String;ZLjava/lang/Object;)F");
        mParentVisitor.visitInsn(Opcodes.FRETURN);
        break;
    case Type.DOUBLE:
        mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                "com/android/tools/layoutlib/create/OverrideMethod", "invokeD",
                "(Ljava/lang/String;ZLjava/lang/Object;)D");
        mParentVisitor.visitInsn(Opcodes.DRETURN);
        break;
    case Type.ARRAY:
    case Type.OBJECT:
        mParentVisitor.visitMethodInsn(Opcodes.INVOKESTATIC,
                "com/android/tools/layoutlib/create/OverrideMethod", "invokeA",
                "(Ljava/lang/String;ZLjava/lang/Object;)Ljava/lang/Object;");
        mParentVisitor.visitTypeInsn(Opcodes.CHECKCAST, mReturnType.getInternalName());
        mParentVisitor.visitInsn(Opcodes.ARETURN);
        break;
    }

}

From source file:com.android.tools.lint.checks.FieldGetterDetector.java

License:Apache License

@Override
public void checkInstruction(@NonNull ClassContext context, @NonNull ClassNode classNode,
        @NonNull MethodNode method, @NonNull AbstractInsnNode instruction) {
    // As of Gingerbread/API 9, Dalvik performs this optimization automatically
    if (context.getProject().getMinSdk() >= 9) {
        return;/*from ww  w  .  j av a2s .c  o m*/
    }

    if ((method.access & Opcodes.ACC_STATIC) != 0) {
        // Not an instance method
        return;
    }

    if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) {
        return;
    }

    MethodInsnNode node = (MethodInsnNode) instruction;
    String name = node.name;
    String owner = node.owner;

    AbstractInsnNode prev = LintUtils.getPrevInstruction(instruction);
    if (prev == null || prev.getOpcode() != Opcodes.ALOAD) {
        return;
    }
    VarInsnNode prevVar = (VarInsnNode) prev;
    if (prevVar.var != 0) { // Not on "this", variable 0 in instance methods?
        return;
    }

    if (((name.startsWith("get") && name.length() > 3 //$NON-NLS-1$
            && Character.isUpperCase(name.charAt(3)))
            || (name.startsWith("is") && name.length() > 2 //$NON-NLS-1$
                    && Character.isUpperCase(name.charAt(2))))
            && owner.equals(classNode.name)) {
        // Calling a potential getter method on self. We now need to
        // investigate the method body of the getter call and make sure
        // it's really a plain getter, not just a method which happens
        // to have a method name like a getter, or a method which not
        // only returns a field but possibly computes it or performs
        // other initialization or side effects. This is done in a
        // second pass over the bytecode, initiated by the finish()
        // method.
        if (mPendingCalls == null) {
            mPendingCalls = new ArrayList<Entry>();
        }

        mPendingCalls.add(new Entry(name, node, method));
    }

    super.checkInstruction(context, classNode, method, instruction);
}

From source file:com.android.tools.lint.checks.FieldGetterDetector.java

License:Apache License

private static Map<String, String> checkMethods(ClassNode classNode, Set<String> names) {
    Map<String, String> validGetters = Maps.newHashMap();
    @SuppressWarnings("rawtypes")
    List methods = classNode.methods;
    String fieldName = null;//from  w  ww  .  j a v  a 2 s.c o m
    checkMethod: for (Object methodObject : methods) {
        MethodNode method = (MethodNode) methodObject;
        if (names.contains(method.name) && method.desc.startsWith("()")) { //$NON-NLS-1$ // (): No arguments
            InsnList instructions = method.instructions;
            int mState = 1;
            for (AbstractInsnNode curr = instructions.getFirst(); curr != null; curr = curr.getNext()) {
                switch (curr.getOpcode()) {
                case -1:
                    // Skip label and line number nodes
                    continue;
                case Opcodes.ALOAD:
                    if (mState == 1) {
                        fieldName = null;
                        mState = 2;
                    } else {
                        continue checkMethod;
                    }
                    break;
                case Opcodes.GETFIELD:
                    if (mState == 2) {
                        FieldInsnNode field = (FieldInsnNode) curr;
                        fieldName = field.name;
                        mState = 3;
                    } else {
                        continue checkMethod;
                    }
                    break;
                case Opcodes.ARETURN:
                case Opcodes.FRETURN:
                case Opcodes.IRETURN:
                case Opcodes.DRETURN:
                case Opcodes.LRETURN:
                case Opcodes.RETURN:
                    if (mState == 3) {
                        validGetters.put(method.name, fieldName);
                    }
                    continue checkMethod;
                default:
                    continue checkMethod;
                }
            }
        }
    }

    return validGetters;
}

From source file:com.android.tools.lint.checks.UnsafeBroadcastReceiverDetector.java

License:Apache License

@SuppressWarnings("rawtypes")
public void checkClass(@NonNull final ClassContext context, @NonNull ClassNode classNode) {
    // If class isn't in mReceiversWithIntentFilter (set below by
    // XmlScanner), skip it.
    if (!mReceiversWithProtectedBroadcastIntentFilter.contains(classNode.name)) {
        return;//from w  w w .  ja v  a  2s.  c o  m
    }

    // Search for "void onReceive(android.content.Context, android.content.Intent)" method
    List methodList = classNode.methods;

    for (Object m : methodList) {
        MethodNode method = (MethodNode) m;
        if (!"onReceive".equals(method.name)
                || !"(Landroid/content/Context;Landroid/content/Intent;)V".equals(method.desc)) {
            continue;
        }
        // Search for call to getAction but also search for references to aload_2,
        // which indicates that the method is making use of the received intent in
        // some way.
        //
        // If the onReceive method doesn't call getAction but does make use of
        // the received intent, it is possible that it is passing it to another
        // method that might be performing the getAction check, so we warn that the
        // finding may be a false positive. (An alternative option would be to not
        // report a finding at all in this case.)
        boolean getActionEncountered = false;
        boolean intentParameterEncountered = false;
        InsnList nodes = method.instructions;
        for (int i = 0, n = nodes.size(); i < n; i++) {
            AbstractInsnNode instruction = nodes.get(i);
            int type = instruction.getType();
            if (type == AbstractInsnNode.VAR_INSN) {
                VarInsnNode node = (VarInsnNode) instruction;
                if (node.getOpcode() == Opcodes.ALOAD) {
                    if (node.var == 2) {
                        intentParameterEncountered = true;
                    }
                }
            } else if (type == AbstractInsnNode.METHOD_INSN) {
                MethodInsnNode node = (MethodInsnNode) instruction;
                if ("android/content/Intent".equals(node.owner) && "getAction".equals(node.name)) {
                    getActionEncountered = true;
                    break;
                }
            }
        }
        if (!getActionEncountered) {
            Location location = context.getLocation(method, classNode);
            String report;
            if (!intentParameterEncountered) {
                report = "This broadcast receiver declares an intent-filter for a protected "
                        + "broadcast action string, which can only be sent by the system, "
                        + "not third-party applications. However, the receiver's onReceive "
                        + "method does not appear to call getAction to ensure that the "
                        + "received Intent's action string matches the expected value, "
                        + "potentially making it possible for another actor to send a "
                        + "spoofed intent with no action string or a different action "
                        + "string and cause undesired behavior.";
            } else {
                // An alternative implementation option is to not report a finding at all in
                // this case, if we are worried about false positives causing confusion or
                // resulting in developers ignoring other lint warnings.
                report = "This broadcast receiver declares an intent-filter for a protected "
                        + "broadcast action string, which can only be sent by the system, "
                        + "not third-party applications. However, the receiver's onReceive "
                        + "method does not appear to call getAction to ensure that the "
                        + "received Intent's action string matches the expected value, "
                        + "potentially making it possible for another actor to send a "
                        + "spoofed intent with no action string or a different action "
                        + "string and cause undesired behavior. In this case, it is "
                        + "possible that the onReceive method passed the received Intent "
                        + "to another method that checked the action string. If so, this "
                        + "finding can safely be ignored.";
            }
            context.report(ACTION_STRING, method, null, location, report);
        }
    }
}

From source file:com.asakusafw.dag.compiler.builtin.ConvertOperatorGenerator.java

License:Apache License

private static ClassData generateClass(Context context, UserOperator operator, ClassDescription target) {
    OperatorInput input = operator.getInput(0);
    OperatorOutput output = operator.getOutput(Convert.ID_OUTPUT_CONVERTED);
    OperatorOutput copy = operator.getOutput(Convert.ID_OUTPUT_ORIGINAL);

    ClassWriter writer = newWriter(target, Object.class, Result.class);
    FieldRef impl = defineOperatorField(writer, operator, target);
    Map<OperatorProperty, FieldRef> map = defineConstructor(context, operator, target, writer, method -> {
        setOperatorField(method, operator, impl);
    });/*w  w w.j  a v  a2  s  . c  o m*/
    defineResultAdd(writer, method -> {
        LocalVarRef self = new LocalVarRef(Opcodes.ALOAD, 0);
        LocalVarRef data = cast(method, 1, input.getDataType());

        self.load(method);
        getField(method, map.get(output));

        List<ValueRef> arguments = new ArrayList<>();
        arguments.add(impl);
        arguments.add(data);
        appendSecondaryInputs(arguments::add, operator, map::get);
        appendArguments(arguments::add, operator, map::get);
        invoke(method, context, operator, arguments);

        invokeResultAdd(method);

        // must invoke about "original" after "converted" was processed
        self.load(method);
        getField(method, map.get(copy));
        data.load(method);
        invokeResultAdd(method);
    });
    return new ClassData(target, writer::toByteArray);
}

From source file:com.asakusafw.dag.compiler.builtin.ExtractOperatorGenerator.java

License:Apache License

private static ClassData generateClass(Context context, UserOperator operator, ClassDescription target) {
    OperatorInput input = operator.getInput(Extract.ID_INPUT);
    ClassWriter writer = newWriter(target, Object.class, Result.class);
    FieldRef impl = defineOperatorField(writer, operator, target);
    Map<OperatorProperty, FieldRef> map = defineConstructor(context, operator, target, writer, method -> {
        setOperatorField(method, operator, impl);
    });// w  w  w. j  a  v  a  2 s  .  co m
    defineResultAdd(writer, method -> {
        cast(method, 1, input.getDataType());
        List<ValueRef> arguments = new ArrayList<>();
        arguments.add(impl);
        arguments.add(new LocalVarRef(Opcodes.ALOAD, 1));
        appendSecondaryInputs(arguments::add, operator, map::get);
        appendOutputs(arguments::add, operator, map::get);
        appendArguments(arguments::add, operator, map::get);
        invoke(method, context, operator, arguments);
    });
    return new ClassData(target, writer::toByteArray);
}

From source file:com.asakusafw.dag.compiler.builtin.FoldOperatorGenerator.java

License:Apache License

private ClassData generateClass(Context context, UserOperator operator, ClassDescription target) {
    ClassDescription combinerClass = generateCombinerClass(context, operator, target);
    ClassWriter writer = newWriter(target, CombineResult.class);
    writer.visitInnerClass(combinerClass.getInternalName(), target.getInternalName(),
            combinerClass.getSimpleName(), Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC);

    OperatorInput input = operator.getInput(Fold.ID_INPUT);
    defineDependenciesConstructor(context, operator.getOutputs(), target, writer, method -> {
        method.visitVarInsn(Opcodes.ALOAD, 0);
        getNew(method, combinerClass);//w ww  .j  a va 2 s .  c  o  m
        getNew(method, input.getDataType());
        method.visitVarInsn(Opcodes.ALOAD, 1);
        method.visitMethodInsn(Opcodes.INVOKESPECIAL, typeOf(CombineResult.class).getInternalName(), "<init>",
                Type.getMethodDescriptor(Type.VOID_TYPE, typeOf(ObjectCombiner.class), typeOf(DataModel.class),
                        typeOf(Result.class)),
                false);
    }, Lang.discard());
    writer.visitEnd();

    return new ClassData(target, writer::toByteArray);
}

From source file:com.asakusafw.dag.compiler.builtin.FoldOperatorGenerator.java

License:Apache License

private ClassDescription generateCombinerClass(Context context, UserOperator operator, ClassDescription outer) {
    ClassDescription target = getCombinerName(outer);
    OperatorInput input = operator.getInput(0);

    ClassWriter writer = newWriter(target, Object.class, ObjectCombiner.class);
    writer.visitOuterClass(outer.getInternalName(), target.getInternalName(), null);

    FieldRef impl = defineOperatorField(writer, operator, target);
    defineEmptyConstructor(writer, Object.class, method -> {
        setOperatorField(method, operator, impl);
    });/*w  ww.j  a  v  a2 s . co  m*/
    defineBuildKey(context, writer, input.getDataType(), input.getGroup());

    MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC, "combine",
            Type.getMethodDescriptor(Type.VOID_TYPE, typeOf(Object.class), typeOf(Object.class)), null, null);

    List<ValueRef> arguments = new ArrayList<>();
    arguments.add(impl);
    arguments.add(m -> {
        m.visitVarInsn(Opcodes.ALOAD, 1);
        m.visitTypeInsn(Opcodes.CHECKCAST, typeOf(input.getDataType()).getInternalName());
    });
    arguments.add(m -> {
        m.visitVarInsn(Opcodes.ALOAD, 2);
        m.visitTypeInsn(Opcodes.CHECKCAST, typeOf(input.getDataType()).getInternalName());
    });
    for (VertexElement dep : context.getDependencies(operator.getArguments())) {
        Invariants.require(dep.getElementKind() == ElementKind.VALUE);
        ValueDescription value = ((ValueElement) dep).getValue();
        arguments.add(m -> {
            getConst(method, Invariants.safe(() -> value.resolve(context.getClassLoader())));
        });
    }
    invoke(method, context, operator, arguments);
    method.visitInsn(Opcodes.RETURN);
    method.visitMaxs(0, 0);
    method.visitEnd();
    return context.addClassFile(new ClassData(target, writer::toByteArray));
}