Example usage for org.objectweb.asm.commons GeneratorAdapter arrayStore

List of usage examples for org.objectweb.asm.commons GeneratorAdapter arrayStore

Introduction

In this page you can find the example usage for org.objectweb.asm.commons GeneratorAdapter arrayStore.

Prototype

public void arrayStore(final Type type) 

Source Link

Document

Generates the instruction to store an element in an array.

Usage

From source file:com.android.build.gradle.internal.incremental.ByteCodeUtils.java

License:Apache License

/**
 * Given an array on the stack, it loads it with the values of the given variables stating at
 * offset./*from   w  w  w .j a v a  2 s.  c  om*/
 */
static void loadVariableArray(@NonNull GeneratorAdapter mv, @NonNull List<LocalVariable> variables,
        int offset) {
    // we need to maintain the stack index when loading parameters from, as for long and double
    // values, it uses 2 stack elements, all others use only 1 stack element.
    for (int i = offset; i < variables.size(); i++) {
        LocalVariable variable = variables.get(i);
        // duplicate the array of objects reference, it will be used to store the value in.
        mv.dup();
        // index in the array of objects to store the boxed parameter.
        mv.push(i);
        // Pushes the appropriate local variable on the stack
        mv.visitVarInsn(variable.type.getOpcode(Opcodes.ILOAD), variable.var);
        // potentially box up intrinsic types.
        mv.box(variable.type);
        // store it in the array
        mv.arrayStore(Type.getType(Object.class));
    }
}

From source file:com.android.build.gradle.internal.incremental.ConstructorBuilder.java

License:Apache License

/**
 * Splits the constructor in two methods, the "set up" and the "body" parts (see above).
 *///from   www  .ja v  a2  s . com
@NonNull
private static Constructor split(@NonNull String owner, @NonNull MethodNode method,
        @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine,
        @NonNull List<LocalVariable> variables, int localsAtLoadThis) {
    String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]);

    // Do not add the local array yet, as we treat it as a new variable.
    String newDesc = method.desc.replace(")V", ")Ljava/lang/Object;");
    newDesc = newDesc.replace("(", "([L" + owner + ";");

    Type[] argumentTypes = Type.getArgumentTypes(newDesc);

    // Store the non hotswappable part of the constructor
    List<AbstractInsnNode> fixed = Lists.newLinkedList();
    AbstractInsnNode insn = method.instructions.getFirst();
    while (insn != loadThis) {
        fixed.add(insn);
        insn = insn.getNext();
    }
    fixed.add(loadThis);

    MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null,
            exceptions);
    GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc);
    int newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;"));

    mv.loadLocal(newArgument);
    ByteCodeUtils.restoreVariables(mv, variables.subList(0, localsAtLoadThis));

    // Now insert the original method
    insn = loadThis.getNext();
    while (insn != delegation) {
        insn.accept(mv);
        insn = insn.getNext();
    }
    LabelNode labelBefore = new LabelNode();
    labelBefore.accept(mv);

    // Create the args array with the local variables and the values to send to the delegated constructor
    Type[] returnTypes = Type.getArgumentTypes(delegation.desc);
    // The extra elements for the local variables and the qualified name of the constructor.
    mv.push(returnTypes.length + 2);
    mv.newArray(Type.getType(Object.class));
    int args = mv.newLocal(Type.getType("[Ljava/lang/Object;"));
    mv.storeLocal(args);
    for (int i = returnTypes.length - 1; i >= 0; i--) {
        Type type = returnTypes[i];
        mv.loadLocal(args);
        mv.swap(type, Type.getType(Object.class));
        mv.push(i + 2);
        mv.swap(type, Type.INT_TYPE);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
    }

    // Store the qualified name of the constructor in the second element of the array.
    mv.loadLocal(args);
    mv.push(1);
    mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called.
    mv.arrayStore(Type.getType(Object.class));

    // Create the locals array and place it in the first element of the return array
    mv.loadLocal(args);
    mv.push(0);
    mv.push(argumentTypes.length + 1);
    mv.newArray(Type.getType(Object.class));
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(Arrays.asList(argumentTypes)), 0);

    mv.dup();
    mv.push(argumentTypes.length);
    ByteCodeUtils.newVariableArray(mv, variables);
    mv.arrayStore(Type.getType(Object.class));

    mv.arrayStore(Type.getType(Object.class));

    mv.loadLocal(args);
    mv.returnValue();

    // Move the first variable up to be an argument
    initArgs.desc = initArgs.desc.replace(")", "[Ljava/lang/Object;)");

    newDesc = method.desc.replace("(", "(L" + owner + ";");
    MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null,
            exceptions);
    mv = new GeneratorAdapter(body, body.access, body.name, body.desc);
    newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;"));

    LabelNode labelAfter = new LabelNode();
    labelAfter.accept(body);
    Set<LabelNode> bodyLabels = new HashSet<LabelNode>();

    mv.loadLocal(newArgument);
    ByteCodeUtils.restoreVariables(mv, variables);

    insn = delegation.getNext();
    while (insn != null) {
        if (insn instanceof LabelNode) {
            bodyLabels.add((LabelNode) insn);
        }
        insn.accept(mv);
        insn = insn.getNext();
    }

    // manually transfer the exception table from the existing constructor to the new
    // "init$body" method. The labels were transferred just above so we can reuse them.

    //noinspection unchecked
    for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) {
        tryCatch.accept(mv);
    }

    //noinspection unchecked
    for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) {
        boolean startsInBody = bodyLabels.contains(variable.start);
        boolean endsInBody = bodyLabels.contains(variable.end);
        if (!startsInBody && !endsInBody) {
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                variable.accept(initArgs);
            }
        } else if (startsInBody && endsInBody) {
            variable.accept(body);
        } else if (!startsInBody && endsInBody) {
            // The variable spans from the args to the end of the method, create two:
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                        variable.start, labelBefore, variable.index);
                var0.accept(initArgs);
            }
            LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                    labelAfter, variable.end, variable.index);
            var1.accept(body);
        } else {
            throw new IllegalStateException("Local variable starts after it ends.");
        }
    }
    // Move the first variable up to be an argument
    body.desc = body.desc.replace(")", "[Ljava/lang/Object;)");

    return new Constructor(owner, fixed, loadThis, loadThisLine, initArgs, delegation, body, variables,
            localsAtLoadThis);
}

From source file:com.android.build.gradle.internal.incremental.ConstructorDelegationDetector.java

License:Apache License

/**
 * Splits the constructor in two methods, the "set up" and the "body" parts (see above).
 *//*from w w w .  j a  v  a 2 s.  c o m*/
@NonNull
private static Constructor split(@NonNull String owner, @NonNull MethodNode method,
        @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine) {
    String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]);
    String newDesc = method.desc.replaceAll("\\((.*)\\)V", "([Ljava/lang/Object;$1)Ljava/lang/Object;");

    MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null,
            exceptions);
    AbstractInsnNode insn = loadThis.getNext();
    while (insn != delegation) {
        insn.accept(initArgs);
        insn = insn.getNext();
    }
    LabelNode labelBefore = new LabelNode();
    labelBefore.accept(initArgs);

    GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc);
    // Copy the arguments back to the argument array
    // The init_args part cannot access the "this" object and can have side effects on the
    // local variables. Because of this we use the first argument (which we want to keep
    // so all the other arguments remain unchanged) as a reference to the array where to
    // return the values of the modified local variables.
    Type[] types = Type.getArgumentTypes(initArgs.desc);
    int stack = 1; // Skip the first one which is a reference to the local array.
    for (int i = 1; i < types.length; i++) {
        Type type = types[i];
        // This is not this, but the array of local arguments final values.
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.push(i);
        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), stack);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
        stack += type.getSize();
    }
    // Create the args array with the values to send to the delegated constructor
    Type[] returnTypes = Type.getArgumentTypes(delegation.desc);
    // The extra element for the qualified name of the constructor.
    mv.push(returnTypes.length + 1);
    mv.newArray(Type.getType(Object.class));
    int args = mv.newLocal(Type.getType("[Ljava/lang/Object;"));
    mv.storeLocal(args);
    for (int i = returnTypes.length - 1; i >= 0; i--) {
        Type type = returnTypes[i];
        mv.loadLocal(args);
        mv.swap(type, Type.getType(Object.class));
        mv.push(i + 1);
        mv.swap(type, Type.INT_TYPE);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
    }

    // Store the qualified name of the constructor in the first element of the array.
    mv.loadLocal(args);
    mv.push(0);
    mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called.
    mv.arrayStore(Type.getType(Object.class));

    mv.loadLocal(args);
    mv.returnValue();

    newDesc = method.desc.replace("(", "(L" + owner + ";");
    MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null,
            exceptions);
    LabelNode labelAfter = new LabelNode();
    labelAfter.accept(body);
    Set<LabelNode> bodyLabels = new HashSet<LabelNode>();

    insn = delegation.getNext();
    while (insn != null) {
        if (insn instanceof LabelNode) {
            bodyLabels.add((LabelNode) insn);
        }
        insn.accept(body);
        insn = insn.getNext();
    }

    // manually transfer the exception table from the existing constructor to the new
    // "init$body" method. The labels were transferred just above so we can reuse them.

    //noinspection unchecked
    for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) {
        tryCatch.accept(body);
    }

    //noinspection unchecked
    for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) {
        boolean startsInBody = bodyLabels.contains(variable.start);
        boolean endsInBody = bodyLabels.contains(variable.end);
        if (!startsInBody && !endsInBody) {
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                variable.accept(initArgs);
            }
        } else if (startsInBody && endsInBody) {
            variable.accept(body);
        } else if (!startsInBody && endsInBody) {
            // The variable spans from the args to the end of the method, create two:
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                        variable.start, labelBefore, variable.index);
                var0.accept(initArgs);
            }
            LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                    labelAfter, variable.end, variable.index);
            var1.accept(body);
        } else {
            throw new IllegalStateException("Local variable starts after it ends.");
        }
    }

    return new Constructor(loadThis, loadThisLine, initArgs, delegation, body);
}

From source file:com.android.build.gradle.internal.incremental.ConstructorRedirection.java

License:Apache License

@Override
protected void doRedirect(GeneratorAdapter mv, int change) {
    mv.loadLocal(change);//from  www  .  j  a va  2 s .  com
    mv.push("init$args." + constructor.args.desc);

    Type arrayType = Type.getType("[Ljava/lang/Object;");
    // init$args args (including this) + locals
    mv.push(types.size() + 1);
    mv.newArray(Type.getType(Object.class));

    int array = mv.newLocal(arrayType);
    mv.dup();
    mv.storeLocal(array);

    // "this" is not ready yet, use null instead.
    mv.dup();
    mv.push(0);
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.arrayStore(Type.getType(Object.class));

    // Set the arguments in positions 1..(n-1);
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(types), 1); // Skip the this value

    // Add the locals array at the last position.
    mv.dup();
    // The index of the last position of the array.
    mv.push(types.size());
    // Create the array with all the local variables declared up to this point.
    ByteCodeUtils.newVariableArray(mv, constructor.variables.subList(0, constructor.localsAtLoadThis));
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE,
            Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    //// At this point, init$args has been called and the result Object is on the stack.
    //// The value of that Object is Object[] with exactly n + 2 elements.
    //// The first element is the resulting local variables
    //// The second element is a string with the qualified name of the constructor to call.
    //// The remaining elements are the constructor arguments.

    // Keep a reference to the new locals array
    mv.dup();
    mv.push(0);
    mv.arrayLoad(Type.getType("[Ljava/lang/Object;"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    mv.storeLocal(array);

    // Call super constructor
    // Put this behind the returned array
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.swap();
    // Push a null for the marker parameter.
    mv.visitInsn(Opcodes.ACONST_NULL);
    // Invoke the constructor
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, "<init>", DISPATCHING_THIS_SIGNATURE, false);

    // Dispatch to init$body
    mv.loadLocal(change);
    mv.push("init$body." + constructor.body.desc);
    mv.loadLocal(array);

    // Now "this" can be set
    mv.dup();
    mv.push(0);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE,
            Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.pop();
}

From source file:com.android.build.gradle.internal.incremental.StringSwitch.java

License:Apache License

/**
 * Generates a standard error exception with message similar to:
 *
 *    String switch could not find 'equals.(Ljava/lang/Object;)Z' with hashcode 0
 *    in com/example/basic/GrandChild//from  w  w w .  j a v a  2 s . c  o  m
 *
 * @param mv The generator adaptor used to emit the lookup switch code.
 * @param visitedClassName The abstract string trie structure.
 */
void writeMissingMessageWithHash(GeneratorAdapter mv, String visitedClassName) {
    mv.newInstance(INSTANT_RELOAD_EXCEPTION_TYPE);
    mv.dup();
    mv.push("String switch could not find '%s' with hashcode %s in %s");
    mv.push(3);
    mv.newArray(OBJECT_TYPE);
    mv.dup();
    mv.push(0);
    visitString();
    mv.arrayStore(OBJECT_TYPE);
    mv.dup();
    mv.push(1);
    visitString();
    visitHashMethod(mv);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
    mv.arrayStore(OBJECT_TYPE);
    mv.dup();
    mv.push(2);
    mv.push(visitedClassName);
    mv.arrayStore(OBJECT_TYPE);
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/String", "format",
            "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;", false);
    mv.invokeConstructor(INSTANT_RELOAD_EXCEPTION_TYPE, Method.getMethod("void <init> (String)"));
    mv.throwException();
}

From source file:com.android.build.gradle.internal2.incremental.ConstructorBuilder.java

License:Apache License

/**
 * Splits the constructor in two methods, the "set up" and the "body" parts (see above).
 *//* w w w.  ja  va2s.  c  o m*/
@NonNull
private static Constructor split(@NonNull String owner, @NonNull MethodNode method,
        @NonNull VarInsnNode loadThis, @NonNull MethodInsnNode delegation, int loadThisLine,
        @NonNull List<LocalVariable> variables, int localsAtLoadThis) {
    String[] exceptions = ((List<String>) method.exceptions).toArray(new String[method.exceptions.size()]);

    // Do not add the local array yet, as we treat it as a new variable.
    String newDesc = method.desc.replace(")V", ")Ljava/lang/Object;");
    newDesc = newDesc.replace("(", "([L" + owner + ";");

    Type[] argumentTypes = Type.getArgumentTypes(newDesc);

    // Store the non hotswappable part of the constructor
    List<AbstractInsnNode> fixed = Lists.newLinkedList();
    AbstractInsnNode insn = method.instructions.getFirst();
    while (insn != loadThis) {
        fixed.add(insn);
        insn = insn.getNext();
    }
    fixed.add(loadThis);

    MethodNode initArgs = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$args", newDesc, null,
            exceptions);
    GeneratorAdapter mv = new GeneratorAdapter(initArgs, initArgs.access, initArgs.name, initArgs.desc);
    int newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;"));

    mv.loadLocal(newArgument);
    ByteCodeUtils.restoreVariables(mv, variables.subList(0, localsAtLoadThis));

    // Now insert the original method
    insn = loadThis.getNext();
    while (insn != delegation) {
        insn.accept(mv);
        insn = insn.getNext();
    }
    LabelNode labelBefore = new LabelNode();
    labelBefore.accept(mv);

    // Create the args array with the local variables and the values to send to the delegated constructor
    Type[] returnTypes = Type.getArgumentTypes(delegation.desc);
    // The extra elements for the local variables and the qualified name of the constructor.
    mv.push(returnTypes.length + 2);
    mv.newArray(Type.getType(Object.class));
    int args = mv.newLocal(Type.getType("[Ljava/lang/Object;"));
    mv.storeLocal(args);
    for (int i = returnTypes.length - 1; i >= 0; i--) {
        Type type = returnTypes[i];
        mv.loadLocal(args);
        mv.swap(type, Type.getType(Object.class));
        mv.push(i + 2);
        mv.swap(type, Type.INT_TYPE);
        mv.box(type);
        mv.arrayStore(Type.getType(Object.class));
    }

    // Store the qualified name of the constructor in the second element of the array.
    mv.loadLocal(args);
    mv.push(1);
    mv.push(delegation.owner + "." + delegation.desc); // Name of the constructor to be called.
    mv.arrayStore(Type.getType(Object.class));

    // Create the locals array and place it in the first element of the return array
    mv.loadLocal(args);
    mv.push(0);
    mv.push(argumentTypes.length + 1);
    mv.newArray(Type.getType(Object.class));
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(Arrays.asList(argumentTypes)), 0);

    mv.dup();
    mv.push(argumentTypes.length);
    ByteCodeUtils.newVariableArray(mv, variables);
    mv.arrayStore(Type.getType(Object.class));

    mv.arrayStore(Type.getType(Object.class));

    mv.loadLocal(args);
    mv.returnValue();

    // Move the first variable up to be an argument
    initArgs.desc = initArgs.desc.replace(")", "[Ljava/lang/Object;)");

    newDesc = method.desc.replace("(", "(L" + owner + ";");
    MethodNode body = new MethodNode(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, "init$body", newDesc, null,
            exceptions);
    mv = new GeneratorAdapter(body, body.access, body.name, body.desc);
    newArgument = mv.newLocal(Type.getType("[Ljava/lang/Object;"));

    LabelNode labelAfter = new LabelNode();
    labelAfter.accept(body);
    Set<LabelNode> bodyLabels = new HashSet<LabelNode>();

    mv.loadLocal(newArgument);
    ByteCodeUtils.restoreVariables(mv, variables);

    insn = delegation.getNext();
    while (insn != null) {
        if (insn instanceof LabelNode) {
            bodyLabels.add((LabelNode) insn);
        }
        insn.accept(mv);
        insn = insn.getNext();
    }

    // manually transfer the exception table from the existing constructor to the new
    // "init$body" method. The labels were transferred just above so we can reuse them.

    //noinspection unchecked
    for (TryCatchBlockNode tryCatch : (List<TryCatchBlockNode>) method.tryCatchBlocks) {
        tryCatch.accept(mv);
    }

    //noinspection unchecked
    for (LocalVariableNode variable : (List<LocalVariableNode>) method.localVariables) {
        boolean startsInBody = bodyLabels.contains(variable.start);
        boolean endsInBody = bodyLabels.contains(variable.end);
        if (!startsInBody && !endsInBody) {
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                variable.accept(initArgs);
            }
        } else if (startsInBody && endsInBody) {
            variable.accept(body);
        } else if (!startsInBody && endsInBody) {
            // The variable spans from the args to the end of the method, create two:
            if (variable.index != 0) { // '#0' on init$args is not 'this'
                LocalVariableNode var0 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                        variable.start, labelBefore, variable.index);
                var0.accept(initArgs);
            }
            LocalVariableNode var1 = new LocalVariableNode(variable.name, variable.desc, variable.signature,
                    labelAfter, variable.end, variable.index);
            var1.accept(body);
        } else {
            throw new IllegalStateException("Local variable starts after it ends.");
        }
    }
    // Move the first variable up to be an argument
    body.desc = body.desc.replace(")", "[Ljava/lang/Object;)");

    return new Constructor(owner, method, fixed, loadThis, loadThisLine, initArgs, delegation, body, variables,
            localsAtLoadThis);
}

From source file:com.android.build.gradle.internal2.incremental.ConstructorRedirection.java

License:Apache License

@Override
protected void doRedirect(GeneratorAdapter mv, int change) {
    mv.loadLocal(change);//from w ww  .ja  v  a 2  s.c om
    mv.push("init$args." + constructor.args.desc);

    Type arrayType = Type.getType("[Ljava/lang/Object;");
    // init$args args (including this) + locals
    mv.push(types.size() + 1);
    mv.newArray(Type.getType(Object.class));

    int array = mv.newLocal(arrayType);
    mv.dup();
    mv.storeLocal(array);

    // "this" is not ready yet, use null instead.
    mv.dup();
    mv.push(0);
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.arrayStore(Type.getType(Object.class));

    // Set the arguments in positions 1..(n-1);
    ByteCodeUtils.loadVariableArray(mv, ByteCodeUtils.toLocalVariables(types), 1); // Skip the this value

    // Add the locals array at the last position.
    mv.dup();
    // The index of the last position of the array.
    mv.push(types.size());
    // Create the array with all the local variables declared up to this point.
    ByteCodeUtils.newVariableArray(mv, constructor.variables.subList(0, constructor.localsAtLoadThis));
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE,
            Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    //// At this point, init$args has been called and the result Object is on the stack.
    //// The value of that Object is Object[] with exactly n + 2 elements.
    //// The first element is the resulting local variables
    //// The second element is a string with the qualified name of the constructor to call.
    //// The remaining elements are the constructor arguments.

    // Keep a reference to the new locals array
    mv.dup();
    mv.push(0);
    mv.arrayLoad(Type.getType("[Ljava/lang/Object;"));
    mv.visitTypeInsn(Opcodes.CHECKCAST, "[Ljava/lang/Object;");
    mv.storeLocal(array);

    // Call super constructor
    // Put this behind the returned array
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.swap();
    // Push a null for the marker parameter.
    mv.visitInsn(Opcodes.ACONST_NULL);
    // Invoke the constructor
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, ByteCodeUtils.CONSTRUCTOR,
            DISPATCHING_THIS_SIGNATURE, false);

    //        {
    //            // FIXME: Opcodes.INVOKESPECIAL??????this?,?????
    //            mv.visitVarInsn(Opcodes.ALOAD, 0);
    //
    //            List<LocalVariable> variables = ByteCodeUtils.toLocalVariables(types);
    //            for (int i = 1; i < variables.size(); i++) {
    //                LocalVariable variable = variables.get(i);
    //                // Duplicates the array on the stack;
    //                mv.loadLocal(array);
    //                // Sets up the index
    //                mv.push(i + 1);
    //                // Gets the Object value
    //                mv.arrayLoad(Type.getType(Object.class));
    //                mv.unbox(variable.type);
    //            }
    //            mv.visitMethodInsn(Opcodes.INVOKESPECIAL, constructor.owner, ByteCodeUtils.CONSTRUCTOR, constructor.originConstructor.desc, false);
    //        }

    // Dispatch to init$body
    mv.loadLocal(change);
    mv.push("init$body." + constructor.body.desc);
    mv.loadLocal(array);

    // Now "this" can be set
    mv.dup();
    mv.push(0);
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.arrayStore(Type.getType(Object.class));

    mv.invokeInterface(IncrementalVisitor.CHANGE_TYPE,
            Method.getMethod("Object access$dispatch(String, Object[])"));
    mv.pop();
}

From source file:com.changingbits.Builder.java

License:Apache License

private void buildAsm(GeneratorAdapter gen, Node node, int uptoLocal) {

    if (node.outputs != null) {
        //System.out.println("gen outputs=" + node.outputs);
        // Increment any range outputs at the current node:
        for (int range : node.outputs) {
            // Load arg 1 (the int[] answers):
            gen.loadArg(1);//www  . j a va2s . co m
            // Load the index we will store to
            gen.loadLocal(uptoLocal, Type.INT_TYPE);
            // The range value we will store:
            gen.push(range);
            // Store it
            gen.arrayStore(Type.INT_TYPE);
            // Increment our upto:
            gen.iinc(uptoLocal, 1);
        }
    }

    if (node.left != null && (node.left.hasOutputs || node.right.hasOutputs)) {
        assert node.left.end + 1 == node.right.start;
        if (node.left.hasOutputs && node.right.hasOutputs) {
            // Recurse on either left or right
            Label labelLeft = new Label();
            Label labelEnd = new Label();
            gen.loadArg(0);
            gen.push(node.left.end);

            gen.ifCmp(Type.LONG_TYPE, GeneratorAdapter.LE, labelLeft);
            buildAsm(gen, node.right, uptoLocal);
            gen.goTo(labelEnd);
            gen.visitLabel(labelLeft);
            buildAsm(gen, node.left, uptoLocal);
            gen.visitLabel(labelEnd);
        } else if (node.left.hasOutputs) {
            // Recurse only on left
            Label labelEnd = new Label();
            gen.loadArg(0);
            gen.push(node.left.end);

            gen.ifCmp(Type.LONG_TYPE, GeneratorAdapter.GT, labelEnd);
            buildAsm(gen, node.left, uptoLocal);
            gen.visitLabel(labelEnd);
        } else {
            // Recurse only on right
            Label labelEnd = new Label();
            gen.loadArg(0);
            gen.push(node.left.end);

            gen.ifCmp(Type.LONG_TYPE, GeneratorAdapter.LE, labelEnd);
            buildAsm(gen, node.right, uptoLocal);
            gen.visitLabel(labelEnd);
        }
    }
}

From source file:com.changingbits.Builder.java

License:Apache License

private void buildCounterAsm(GeneratorAdapter gen, Node node, boolean sawOutputs) {

    sawOutputs |= node.outputs != null;//from  ww  w  .j  av a  2  s  .c o  m

    if (node.left != null) {
        assert node.left.end + 1 == node.right.start;
        // Recurse on either left or right
        Label labelLeft = new Label();
        Label labelEnd = new Label();
        gen.loadArg(0);
        gen.push(node.left.end);

        gen.ifCmp(Type.LONG_TYPE, GeneratorAdapter.LE, labelLeft);
        buildCounterAsm(gen, node.right, sawOutputs);
        gen.goTo(labelEnd);
        gen.visitLabel(labelLeft);
        buildCounterAsm(gen, node.left, sawOutputs);
        gen.visitLabel(labelEnd);
    } else if (sawOutputs) {
        // leaf: elementaryCounts[node.leafIndex]++
        gen.loadThis();
        gen.getField(BASE_LONG_RANGE_COUNTER_TYPE, "elementaryCounts", INT_ARRAY_TYPE);
        gen.push(node.leafIndex);
        gen.dup2();
        gen.arrayLoad(Type.INT_TYPE);
        gen.push(1);
        gen.visitInsn(Opcodes.IADD);
        gen.arrayStore(Type.INT_TYPE);
    }
}

From source file:com.changingbits.Builder.java

License:Apache License

public LongRangeCounter getCounter2() {
    finish(false);//  w  w w  . j a  va  2s .c o  m

    // Maps each range to the leaf counts that contribute to it:
    Map<Integer, List<Integer>> rangeToLeaf = new HashMap<>();
    buildRangeToLeaf(root, new ArrayList<Integer>(), rangeToLeaf);

    StringBuilder sb = new StringBuilder();
    sb.append('\n');
    sb.append("public void add(long v) {\n");
    int count = 0;
    for (LongRange range : ranges) {
        sb.append("  // range ");
        sb.append(count++);
        sb.append(": ");
        sb.append(range);
        sb.append('\n');
    }

    buildJavaCounter2Source(root, 1, sb, false);

    sb.append("}\n\n");
    sb.append("public int[] getCounts() {\n");
    sb.append("  int[] counts = new int[");
    sb.append(ranges.length);
    sb.append("];\n");
    for (int range = 0; range < ranges.length; range++) {
        List<Integer> elements = rangeToLeaf.get(range);
        if (elements != null) {
            sb.append("  counts[");
            sb.append(range);
            sb.append("] = count");
            sb.append(elements.get(0));

            for (int i = 1; i < elements.size(); i++) {
                sb.append(" + count");
                sb.append(elements.get(i));
            }
            sb.append(";\n");
        }
    }
    sb.append("  return counts;\n}\n");

    String javaSource = sb.toString();
    //System.out.println("counter2 javaSource:\n" + javaSource);

    ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
    classWriter.visit(Opcodes.V1_7,
            Opcodes.ACC_PUBLIC | Opcodes.ACC_SUPER | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC,
            COMPILED_COUNTER_CLASS2.replace('.', '/'), null, LONG_RANGE_COUNTER_TYPE.getInternalName(), null);
    classWriter.visitSource(javaSource, null);

    // Define "int countN" members:
    int numLeaves = elementaryIntervals.size();
    for (int i = 0; i < numLeaves; i++) {
        classWriter.visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_SYNTHETIC, "count" + i, "I", null, null);
    }

    // init:
    Method m = Method.getMethod("void <init> ()");
    GeneratorAdapter constructor = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, m, null,
            null, classWriter);
    // Init all counters to 0:
    for (int i = 0; i < numLeaves; i++) {
        constructor.loadThis();
        constructor.push(0);
        constructor.putField(COMPILED_COUNTER_CLASS2_TYPE, "count" + i, Type.INT_TYPE);
    }
    constructor.loadThis();
    constructor.invokeConstructor(LONG_RANGE_COUNTER_TYPE, m);
    constructor.returnValue();
    constructor.endMethod();

    // void add(long v):
    GeneratorAdapter gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, ADD_METHOD, null,
            null, classWriter);
    buildCounterAsm2(gen, root, false);
    gen.returnValue();
    gen.endMethod();

    // int[] getCounts():
    gen = new GeneratorAdapter(Opcodes.ACC_PUBLIC | Opcodes.ACC_SYNTHETIC, GET_COUNTS_METHOD, null, null,
            classWriter);
    int countsLocal = gen.newLocal(INT_ARRAY_TYPE);
    gen.push(ranges.length);
    gen.newArray(Type.INT_TYPE);
    gen.storeLocal(countsLocal);

    for (int range = 0; range < ranges.length; range++) {
        List<Integer> elements = rangeToLeaf.get(range);
        if (elements != null) {
            gen.loadLocal(countsLocal);
            gen.push(range);

            gen.loadThis();
            gen.getField(COMPILED_COUNTER_CLASS2_TYPE, "count" + elements.get(0), Type.INT_TYPE);

            for (int i = 1; i < elements.size(); i++) {
                gen.loadThis();
                gen.getField(COMPILED_COUNTER_CLASS2_TYPE, "count" + elements.get(i), Type.INT_TYPE);
                gen.visitInsn(Opcodes.IADD);
            }

            gen.arrayStore(Type.INT_TYPE);
        }
    }

    gen.loadLocal(countsLocal);
    gen.returnValue();
    gen.endMethod();

    classWriter.visitEnd();

    byte[] bytes = classWriter.toByteArray();

    // javap -c /x/tmp/my.class
    /*
    try {
      FileOutputStream fos = new FileOutputStream(new File("/x/tmp/counter2.class"));
      fos.write(bytes);
      fos.close();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    */

    // nocommit allow changing the class loader
    Class<? extends LongRangeCounter> cl = new CounterLoader(LongRangeCounter.class.getClassLoader())
            .define(COMPILED_COUNTER_CLASS2, classWriter.toByteArray());
    try {
        return cl.getConstructor().newInstance();
    } catch (InstantiationException | IllegalAccessException | NoSuchMethodException
            | InvocationTargetException e) {
        throw new RuntimeException(e);
    }
}