Example usage for org.objectweb.asm Opcodes ASTORE

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

Introduction

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

Prototype

int ASTORE

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

Click Source Link

Usage

From source file:com.sun.fortress.compiler.asmbytecodeoptimizer.Inlining.java

License:Open Source License

public static List<Insn> convertInsns(MethodInsn mi, List<Insn> insns, int[] args, int _index, Label end) {
    List<Insn> result = new ArrayList<Insn>();
    HashMap labels = new HashMap();
    int index = _index;
    for (Insn i : insns) {
        if (i.isExpanded()) {
            MethodInsn expanded = (MethodInsn) i;
            // This use of end should be OK because all returns should have been removed when inlined before.
            // What could go wrong?
            result.addAll(convertInsns(expanded, expanded.inlineExpansionInsns, args, _index, end));
        } else if (i instanceof SingleInsn) {
            SingleInsn si = (SingleInsn) i;
            switch (si.opcode) {
            case Opcodes.IRETURN:
            case Opcodes.LRETURN:
            case Opcodes.FRETURN:
            case Opcodes.DRETURN:
            case Opcodes.ARETURN:
            case Opcodes.RETURN:
                result.add(new JumpInsn("RETURN->GOTO", Opcodes.GOTO, end, newIndex(mi, index++)));
                break;
            default:
                result.add(i.copy(newIndex(mi, index++)));
            }//from   w w w  .  jav  a2s  .c  o  m
        } else if (i instanceof VarInsn) {
            VarInsn vi = (VarInsn) i;
            switch (vi.opcode) {
            case Opcodes.ILOAD:
            case Opcodes.LLOAD:
            case Opcodes.FLOAD:
            case Opcodes.DLOAD:
            case Opcodes.ALOAD:
            case Opcodes.ISTORE:
            case Opcodes.LSTORE:
            case Opcodes.FSTORE:
            case Opcodes.DSTORE:
            case Opcodes.ASTORE:
                VarInsn newVarInsn = new VarInsn(vi.name, vi.opcode, args[vi.var], newIndex(mi, index++));
                result.add(newVarInsn);
                break;
            default:
                result.add(i.copy(newIndex(mi, index++)));
            }
        } else if (i instanceof VisitMaxs) {
        } else if (i instanceof VisitEnd) {
        } else if (i instanceof VisitCode) {
        } else if (i instanceof VisitFrame) {
        } else if (i instanceof LabelInsn) {
            LabelInsn li = (LabelInsn) i;
            if (labels.containsKey(li.label))
                result.add(new LabelInsn(li.name, (Label) labels.get(li.label), newIndex(mi, index++)));
            else {
                Label l = new Label();
                labels.put(li.label, l);
                result.add(new LabelInsn(li.name, l, newIndex(mi, index++)));
            }
        } else if (i instanceof JumpInsn) {
            JumpInsn ji = (JumpInsn) i;
            if (labels.containsKey(ji.label))
                result.add(
                        new JumpInsn(ji.name, ji.opcode, (Label) labels.get(ji.label), newIndex(mi, index++)));
            else {
                Label l = new Label();
                labels.put(ji.label, l);
                result.add(new JumpInsn(ji.name, ji.opcode, l, newIndex(mi, index++)));
            }
        } else if (i instanceof VisitLineNumberInsn) {
            VisitLineNumberInsn vlni = (VisitLineNumberInsn) i;
            if (labels.containsKey(vlni.start))
                result.add(new VisitLineNumberInsn(vlni.name, vlni.line, (Label) labels.get(vlni.start),
                        newIndex(mi, index++)));
            else {
                Label l = new Label();
                labels.put(vlni.start, l);
                result.add(new VisitLineNumberInsn(vlni.name, vlni.line, l, newIndex(mi, index++)));
            }
        } else if (i instanceof LocalVariableInsn) {
            LocalVariableInsn lvi = (LocalVariableInsn) i;
            if (labels.containsKey(lvi.start) && labels.containsKey(lvi.end)) {
                result.add(new LocalVariableInsn(lvi.name, lvi._name, lvi.desc, lvi.sig,
                        (Label) labels.get(lvi.start), (Label) labels.get(lvi.end), args[lvi._index],
                        newIndex(mi, index++)));
            } else
                throw new RuntimeException("NYI");
        } else if (i instanceof TryCatchBlock) {
            TryCatchBlock tcb = (TryCatchBlock) i;
            if (labels.containsKey(tcb.start) && labels.containsKey(tcb.end)
                    && labels.containsKey(tcb.handler)) {
                result.add(
                        new TryCatchBlock(tcb.name, (Label) labels.get(tcb.start), (Label) labels.get(tcb.end),
                                (Label) labels.get(tcb.handler), tcb.type, newIndex(mi, index++)));
            } else if (!labels.containsKey(tcb.start) && !labels.containsKey(tcb.end)
                    && !labels.containsKey(tcb.handler)) {
                Label s = new Label();
                Label e = new Label();
                Label h = new Label();
                labels.put(tcb.start, s);
                labels.put(tcb.end, e);
                labels.put(tcb.handler, h);
                result.add(new TryCatchBlock(tcb.name, s, e, h, tcb.type, newIndex(mi, index++)));
            } else
                throw new RuntimeException("NYI");
            // Need to add TableSwitch, LookupSwitch
        } else {
            result.add(i.copy(newIndex(mi, index++)));
        }
    }
    return result;
}

From source file:com.sun.fortress.compiler.asmbytecodeoptimizer.Inlining.java

License:Open Source License

public static void inlineMethodCall(String className, ByteCodeMethodVisitor method, MethodInsn mi,
        ByteCodeMethodVisitor methodToInline, Boolean staticMethod) {
    List<Insn> insns = new ArrayList<Insn>();
    Label start = new Label();
    Label end = new Label();
    int argsStart = methodToInline.args.size();
    int localsStart = methodToInline.maxLocals;
    int index = 0;
    insns.add(new LabelInsn("start_" + mi._name, start, newIndex(mi, index++)));
    int[] offsets = new int[methodToInline.maxLocals + 1];

    // Static Method start at args.size() - 1, NonStatic Methods start at args.size()
    if (staticMethod)
        argsStart = argsStart - 1;/*from   w  ww .j  a  v  a 2s  . co  m*/

    for (int i = argsStart; i >= 0; i--) {
        insns.add(new VarInsn("ASTORE", Opcodes.ASTORE, method.maxLocals + i, newIndex(mi, index++)));
        offsets[i] = method.maxLocals + i;
    }

    for (int i = localsStart - 1; i > argsStart; i--)
        offsets[i] = method.maxLocals + i;

    method.maxStack = method.maxStack + methodToInline.maxStack;
    method.maxLocals = method.maxLocals + methodToInline.args.size() + methodToInline.maxLocals;
    insns.addAll(convertInsns(mi, methodToInline.insns, offsets, index, end));
    insns.add(new LabelInsn("end_" + mi._name, end, newIndex(mi, insns.size())));

    for (Insn insn : insns) {
        insn.setParentInsn(mi);
    }

    mi.inlineExpansionInsns.addAll(insns);
}

From source file:com.sun.fortress.compiler.asmbytecodeoptimizer.RemoveLiteralCoercions.java

License:Open Source License

public static Substitution removeFloatLiterals2(ByteCodeMethodVisitor bcmv) {
    String floatLiteral = "com/sun/fortress/compiler/runtimeValues/FFloatLiteral";
    String RR64 = "com/sun/fortress/compiler/runtimeValues/FRR64";
    ArrayList<Insn> matches = new ArrayList<Insn>();
    matches.add(new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC, floatLiteral, "make",
            "(D)L" + floatLiteral + ";", "targetedForRemoval"));
    matches.add(new VarInsn("ASTORE", Opcodes.ASTORE, 0, "targetedForRemoval"));
    matches.add(new LabelInsn("LabelInsn", new Label(), "targetedForRemoval"));
    matches.add(new VisitLineNumberInsn("visitlinenumber", 0, new Label(), "targetedForRemoval"));
    matches.add(new VarInsn("ALOAD", Opcodes.ALOAD, 0, "targetedForRemoval"));
    matches.add(new LabelInsn("LabelInsn", new Label(), "targetedForRemoval"));
    matches.add(new VisitLineNumberInsn("visitlinenumber", 0, new Label(), "targetedForRemoval"));
    matches.add(new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC, "fortress/CompilerBuiltin", "coerce_RR64",
            "(Lfortress/CompilerBuiltin$FloatLiteral;)L" + RR64 + ";", "targetedForRemoval"));
    ArrayList<Insn> replacements = new ArrayList<Insn>();
    replacements.add(new MethodInsn("INVOKESTATIC", Opcodes.INVOKESTATIC, RR64, "make", "(D)L" + RR64 + ";",
            "ReplacementInsn"));
    return new Substitution(matches, replacements);
}

From source file:com.sun.fortress.compiler.OverloadSet.java

License:Open Source License

public void generateCall(MethodVisitor mv, int firstArgIndex, int one_if_method_closure) {
    if (!splitDone) {
        throw new CompilerError("Must split overload set before generating call(s)");
    }/*from   w  w  w .j  a va 2  s  .  c  om*/
    int l = specificDispatchOrder.length;

    TaggedFunctionName[] functionsToCall = new TaggedFunctionName[l];
    for (int i = 0; i < l; i++) {
        functionsToCall[i] = getFunctionToCall(specificDispatchOrder[i]);
    }

    //  create type structures for parameter types.
    TypeStructure[][] type_structures = new TypeStructure[l][];
    MultiMap[] spmaps = new MultiMap[l];
    TypeStructure[] return_type_structures = new TypeStructure[l];

    for (int i = 0; i < l; i++) {
        TaggedFunctionName f = functionsToCall[i];
        Functional eff = f.getF();
        List<Param> parameters = f.getParameters();
        MultiMap<String, TypeStructure> spmap = new MultiMap<String, TypeStructure>();
        spmaps[i] = spmap;
        List<StaticParam> staticParams = staticParametersOf(f.getF());

        Type rt = oa.getRangeType(eff);
        return_type_structures[i] = makeTypeStructure(rt, null, 1, 0, staticParams, eff);

        // skip parameters -- no 'this' for ordinary functions

        if (parameters.size() == 1 && oa.getDomainType(eff) instanceof TupleType) {
            TupleType tt = (TupleType) oa.getDomainType(eff);
            List<Type> tl = tt.getElements();
            int storeAtIndex = tl.size(); // DRC back this out + firstArgIndex;
            // little dubious here, not sure we are getting the
            // right type structures for generic methods.  what about 'self'
            TypeStructure[] f_type_structures = new TypeStructure[tl.size()];
            type_structures[i] = f_type_structures;

            for (int j = 0; j < tl.size(); j++) {
                Type t = STypesUtil.insertStaticParams(tl.get(j), tt.getInfo().getStaticParams());
                TypeStructure type_structure = makeTypeStructure(t, spmap, 1, storeAtIndex, staticParams, eff);
                f_type_structures[j] = type_structure;
                storeAtIndex = type_structure.successorIndex;
            }

        } else {

            int storeAtIndex = parameters.size(); // DRC back this out + firstArgIndex;
            TypeStructure[] f_type_structures = new TypeStructure[parameters.size()];
            type_structures[i] = f_type_structures;

            for (int j = 0; j < parameters.size(); j++) {
                if (j != selfIndex()) {
                    Type t = oa.getParamType(eff, j);
                    TypeStructure type_structure = makeTypeStructure(t, spmap, 1, storeAtIndex, staticParams,
                            eff);
                    f_type_structures[j] = type_structure;
                    storeAtIndex = type_structure.successorIndex;
                }
            }
        }
    }

    for (int i = 0; i < l; i++) {
        TaggedFunctionName f = functionsToCall[i];
        TypeStructure[] f_type_structures = type_structures[i];
        Label lookahead = null;
        boolean infer = false;

        List<StaticParam> staticParams = staticParametersOf(f.getF());
        boolean last_case = i == l - 1;

        /* Trust the static checker; no need to verify
         * applicability of the last one.
         * Also, static parameters will be provided by static checker for the last one
         */
        // Will need lookahead for the next one.
        lookahead = new Label();

        // if this was a generic method that needs inference, we need to include the receiver argument
        // in the inference even if the firstArgIndex is 1 so that we can include it in inference
        // and dispatch
        //KBN-WIP is there a cleaner way to do this?
        int offset = (f_type_structures.length == specificDispatchOrder[i].getParameters().size())
                ? firstArgIndex
                : 0;

        for (int j = 0; j < f_type_structures.length; j++) {
            if (j != selfIndex()) {
                //inference needed if the type structure contains generics TODO: do generics not appearing in the parameters make sense?  probably not, but might need to deal with them.
                if (f_type_structures[j].containsTypeVariables)
                    infer = true;
            }
        }

        if (infer || !last_case)
            for (int j = 0; j < f_type_structures.length; j++) {
                // Load actual parameter
                if (j != selfIndex()) {
                    mv.visitVarInsn(Opcodes.ALOAD, j + offset);
                    f_type_structures[j].emitInstanceOf(mv, lookahead, true);
                }
            }

        //Runtime inference for some cases
        if (infer) {
            @SuppressWarnings("unchecked")
            MultiMap<String, TypeStructure> staticTss = spmaps[i];

            int localCount = f_type_structures[f_type_structures.length - 1].successorIndex; //counter for use storing stuff such as lower bounds

            //create type structures for lower bounds
            Map<StaticParam, TypeStructure> lowerBounds = new HashMap<StaticParam, TypeStructure>();
            for (StaticParam sp : staticParams)
                lowerBounds.put(sp, makeParamTypeStructure(sp, localCount++, TypeStructure.COVARIANT));

            //gather different types of bounds into Multimaps for use later
            MultiMap<StaticParam, StaticParam> relativeLowerBounds = new MultiMap<StaticParam, StaticParam>(); //form X :> Y
            MultiMap<StaticParam, Type> genericUpperBounds = new MultiMap<StaticParam, Type>(); //form X <: GenericStem[\ ... \] where Y appears in ...
            MultiMap<StaticParam, Type> concreteUpperBounds = new MultiMap<StaticParam, Type>(); //form X <: T where T contains no type variables
            for (int outer = 0; outer < staticParams.size(); outer++) {
                StaticParam outerSP = staticParams.get(outer);
                for (BaseType bt : outerSP.getExtendsClause()) {
                    if (bt instanceof VarType) { // outerSP <: bt so outerSP will provide a lower bound on BT
                        String varName = ((VarType) bt).getName().getText();
                        boolean found = false;
                        for (int inner = 0; inner < outer && !found; inner++) {
                            StaticParam innerSP = staticParams.get(inner);
                            if (varName.equals(innerSP.getName().getText())) {
                                relativeLowerBounds.putItem(innerSP, outerSP); // outerSP provides a lower bound on innerSP
                                found = true;
                            }
                        }
                        if (!found)
                            throw new CompilerError(
                                    "Bad Scoping of static parameters found during runtime inference codegen:"
                                            + varName + " not declared before used in a bound");
                    } else if (bt instanceof AnyType) { //figure out if concrete or generic
                        //do nothing - no need to add meaningless upper bound
                    } else if (bt instanceof NamedType) {
                        if (isGeneric(bt))
                            genericUpperBounds.putItem(outerSP, bt);
                        else
                            concreteUpperBounds.putItem(outerSP, bt);
                    }
                }
            }

            //infer and load RTTIs
            for (int j = 0; j < staticParams.size(); j++) {
                StaticParam sp = staticParams.get(staticParams.size() - 1 - j); //reverse order due to left to right scoping
                Set<TypeStructure> instances = staticTss.get(sp.getName().getText());

                //sort static parameters by their variance and put into
                //arrays using their local variable number
                List<Integer> invariantInstances = new ArrayList<Integer>();
                List<Integer> covariantInstances = new ArrayList<Integer>();
                List<Integer> contravariantInstances = new ArrayList<Integer>();
                if (instances != null)
                    for (TypeStructure ts : instances) {
                        switch (ts.variance) {
                        case TypeStructure.INVARIANT:
                            invariantInstances.add(ts.localIndex);
                            break;
                        case TypeStructure.CONTRAVARIANT:
                            contravariantInstances.add(ts.localIndex);
                            break;
                        case TypeStructure.COVARIANT:
                            covariantInstances.add(ts.localIndex);
                            break;
                        default:
                            throw new CompilerError("Unexpected Variance on TypeStructure during "
                                    + "generic instantiation analysis for overload dispatch");
                        }
                    }

                // if any invariant instances, we must use that RTTI and check that 
                //1) any other invariant instances are the same type (each subtypes the other)
                //2) any covariant instances are subtypes of the invariant instance
                //3) any contravariant instances are supertypes of the invariant instance
                if (invariantInstances.size() > 0) {

                    //a valid instantiation must use the runtime type
                    //of all invariant instances (which must all be the same)
                    //thus, wlog, we can use the first invariant instance
                    int RTTItoUse = invariantInstances.get(0);

                    //1) for each other invariant instance, they must be the same
                    //which we test by checking that each subtypes the other
                    for (int k = 1; k < invariantInstances.size(); k++) {
                        int RTTIcompare = invariantInstances.get(k);
                        //RTTItoUse.runtimeSupertypeOf(RTTIcompare)
                        mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                        mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare);
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE,
                                Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG);
                        mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail
                        //RTTIcompare.runtimeSupertypeOf(RTTItoUse)
                        mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare);
                        mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE,
                                Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG);
                        mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail
                    }

                    //2) for each covariant instance, the runtime type (RTTIcompare) must be a
                    // subtype of the instantiated type (RTTItoUse)
                    for (int RTTIcompare : covariantInstances) {
                        //RTTItoUse.runtimeSupertypeOf(RTTIcompare)
                        mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                        mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare);
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE,
                                Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG);
                        mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail
                    }

                    //3) for each contravariant instance, the instantiated type (RTTItoUse) must be a 
                    // subtype of the runtime type (RTTIcompare)
                    for (int RTTIcompare : contravariantInstances) {
                        //RTTIcompare.runtimeSupertypeOf(RTTItoUse)
                        mv.visitVarInsn(Opcodes.ALOAD, RTTIcompare);
                        mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE,
                                Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG);
                        mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail
                    }

                    //check lower bounds given by other variables
                    Set<StaticParam> relativeLB = relativeLowerBounds.get(sp);
                    if (relativeLB != null)
                        for (StaticParam lb : relativeLB) {
                            //RTTItoUse.runtimeSupertypeOf(otherLB)
                            int otherOffset = lowerBounds.get(lb).localIndex;
                            mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                            mv.visitVarInsn(Opcodes.ALOAD, otherOffset);
                            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE,
                                    Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG);
                            mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail
                        }

                    //verify meets upper bounds
                    Set<Type> concreteUB = concreteUpperBounds.get(sp);
                    if (concreteUB != null)
                        for (Type cub : concreteUB) {
                            //transform into RTTI
                            generateRTTIfromStaticType(mv, cub);
                            mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE,
                                    Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG);
                            mv.visitJumpInsn(Opcodes.IFEQ, lookahead); //if false fail
                        }

                    //generate more bounds for generic upper bounds
                    Set<Type> genericUB = genericUpperBounds.get(sp);
                    if (genericUB != null)
                        for (Type gub : genericUB) {
                            TypeStructure newTS = makeTypeStructure(gub, staticTss, TypeStructure.COVARIANT,
                                    localCount, staticParams, null);
                            localCount = newTS.successorIndex;
                            mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                            newTS.emitInstanceOf(mv, lookahead, false); //fail if RTTItoUse doesn't have this structure
                        }

                    //checks out, so store the RTTI we will use into the lower bound for this parameter
                    mv.visitVarInsn(Opcodes.ALOAD, RTTItoUse);
                    int index = lowerBounds.get(sp).localIndex;
                    mv.visitVarInsn(Opcodes.ASTORE, index);

                } else if (contravariantInstances.size() == 0) { //we can do inference for covariant-only occurrences

                    boolean started = false;
                    if (covariantInstances.size() > 0) {
                        started = true;
                        mv.visitVarInsn(Opcodes.ALOAD, covariantInstances.get(0));

                        for (int k = 1; k < covariantInstances.size(); k++) {
                            mv.visitVarInsn(Opcodes.ALOAD, covariantInstances.get(k));
                            //TODO: allow unions
                            joinStackNoUnion(mv, lookahead); //fails if cannot join w/o union
                        }
                    }

                    //incorporate lower bounds 
                    Set<StaticParam> relativeLB = relativeLowerBounds.get(sp);
                    if (relativeLB != null)
                        for (StaticParam lb : relativeLB) {
                            mv.visitVarInsn(Opcodes.ALOAD, lowerBounds.get(lb).localIndex);
                            if (started) { //join it in
                                //TODO: allow unions
                                joinStackNoUnion(mv, lookahead);
                            } else { //start with this lower bound
                                started = true;
                            }
                        }

                    if (started) {

                        //verify meets upper bounds
                        Set<Type> concreteUB = concreteUpperBounds.get(sp);
                        if (concreteUB != null)
                            for (Type cub : concreteUB) {
                                Label cleanup = new Label();
                                Label next = new Label();

                                mv.visitInsn(Opcodes.DUP);
                                generateRTTIfromStaticType(mv, cub); //transform concrete bound into RTTI
                                mv.visitInsn(Opcodes.SWAP); // LB <: CUB
                                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE,
                                        Naming.RTTI_SUBTYPE_METHOD_NAME, Naming.RTTI_SUBTYPE_METHOD_SIG);
                                mv.visitJumpInsn(Opcodes.IFEQ, cleanup);
                                mv.visitJumpInsn(Opcodes.GOTO, next);
                                mv.visitLabel(cleanup);
                                mv.visitInsn(Opcodes.POP);
                                mv.visitJumpInsn(Opcodes.GOTO, lookahead);
                                mv.visitLabel(next);
                            }

                        //checks out, so store to lower bound of sp
                        int index = lowerBounds.get(sp).localIndex;
                        mv.visitVarInsn(Opcodes.ASTORE, index);

                        //generate more bounds for generic upper bounds
                        Set<Type> genericUB = genericUpperBounds.get(sp);
                        if (genericUB != null)
                            for (Type gub : genericUB) {
                                TypeStructure newTS = makeTypeStructure(gub, staticTss, TypeStructure.COVARIANT,
                                        localCount, staticParams, null);
                                localCount = newTS.successorIndex;
                                mv.visitVarInsn(Opcodes.ALOAD, index);
                                newTS.emitInstanceOf(mv, lookahead, false); //fail if candidate doesn't have this structure
                            }

                    } else {
                        //Bottom is ok - no need to check upper bounds
                        //or generate lower bounds
                        mv.visitFieldInsn(Opcodes.GETSTATIC, Naming.RT_VALUES_PKG + "VoidRTTI",
                                Naming.RTTI_SINGLETON, Naming.RTTI_CONTAINER_DESC);
                        int index = lowerBounds.get(sp).localIndex;
                        mv.visitVarInsn(Opcodes.ASTORE, index);

                    }

                } else { //otherwise, we might need to do inference which is not implemented yet
                    throw new CompilerError("non-invariant inference with contravariance not implemented");
                }
            }

            //load instance cache table to avoid classloader when possible
            String tableName = this.generateClosureTableName(specificDispatchOrder[i]); //use original function for table name
            String tableOwner = this.generateClosureTableOwner(f);
            mv.visitFieldInsn(Opcodes.GETSTATIC, tableOwner, tableName, Naming.CACHE_TABLE_DESC);

            //load template class name
            String arrow = this.instanceArrowSchema(f); //NamingCzar.makeArrowDescriptor(f.getParameters(), f.getReturnType(),f.tagA);
            String functionName = this.functionName(f);

            String templateClass = Naming.genericFunctionPkgClass(Naming.dotToSep(f.tagA.getText()),
                    functionName, Naming.LEFT_OXFORD + Naming.RIGHT_OXFORD, arrow);

            if (otherOverloadKeys.contains(templateClass)) {
                templateClass = Naming.genericFunctionPkgClass(Naming.dotToSep(f.tagA.getText()),
                        NamingCzar.mangleAwayFromOverload(functionName),
                        Naming.LEFT_OXFORD + Naming.RIGHT_OXFORD, arrow);
                //templateClass = NamingCzar.mangleAwayFromOverload(templateClass);
            }

            mv.visitLdcInsn(templateClass);

            String ic_sig;
            if (staticParams.size() > 6) { //use an array
                //load the function: RThelpers.loadClosureClass:(BAlongTree,String,RTTI[])
                String paramList = Naming.CACHE_TABLE_DESC + NamingCzar.descString
                        + Naming.RTTI_CONTAINER_ARRAY_DESC;
                ic_sig = Naming.makeMethodDesc(paramList, Naming.internalToDesc(NamingCzar.internalObject));

                mv.visitLdcInsn(staticParams.size());
                mv.visitTypeInsn(Opcodes.ANEWARRAY, Naming.RTTI_CONTAINER_TYPE);

                //dup array enough times to store RTTIs into it  //know need at least 6 more
                mv.visitInsn(Opcodes.DUP); //first one to get arrays as top two elts on stack

                for (int numDups = staticParams.size() - 1; numDups > 0; numDups = numDups / 2)
                    mv.visitInsn(Opcodes.DUP2);
                if (staticParams.size() % 2 == 0)
                    mv.visitInsn(Opcodes.DUP); //if even, started halving with an odd number, so needs one last

                //store parameters into array
                for (int k = 0; k < staticParams.size(); k++) {
                    int index = lowerBounds.get(staticParams.get(k)).localIndex;
                    mv.visitLdcInsn(k); //index is the static param number
                    mv.visitVarInsn(Opcodes.ALOAD, index);
                    mv.visitInsn(Opcodes.AASTORE);
                }

                //array left on stack

            } else {
                //load the function: RTHelpers.loadClosureClass:(BAlongTree,(String,RTTI)^n)Object
                ic_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes(
                        Naming.CACHE_TABLE_TYPE + ";L" + NamingCzar.internalString, staticParams.size(),
                        Naming.RTTI_CONTAINER_TYPE, Naming.internalToDesc(NamingCzar.internalObject));

                //load parameter RTTIs
                for (int k = 0; k < staticParams.size(); k++) {
                    int index = lowerBounds.get(staticParams.get(k)).localIndex;
                    mv.visitVarInsn(Opcodes.ALOAD, index);
                }

            }
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, Naming.RT_HELPERS, "loadClosureClass", ic_sig);

            //cast to object arrow
            int numParams = f.getParameters().size();
            String objectAbstractArrow = NamingCzar.objectAbstractArrowTypeForNParams(numParams);
            InstantiatingClassloader.generalizedCastTo(mv, objectAbstractArrow);

            //if a method parameters converted
            //loadThisForMethods(mv);

            //load parameters
            for (int j = 0; j < f_type_structures.length; j++) {
                // Load actual parameter
                if (j != selfIndex()) {
                    mv.visitVarInsn(Opcodes.ALOAD, j); // DRC back this out+ one_if_method_closure); // + firstArgIndex); KBN if a method, parameters already converted
                    //no cast needed here - done by apply method
                }
            }

            //call apply method
            String objectArrow = NamingCzar.objectArrowTypeForNParams(numParams);
            String applySig = InstantiatingClassloader.jvmSignatureForNTypes(numParams,
                    NamingCzar.internalObject, Naming.internalToDesc(NamingCzar.internalObject));
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, objectArrow, Naming.APPLY_METHOD, applySig);

            //cast to correct return type
            Type f_return = f.getReturnType();
            if (f_return instanceof BottomType) {
                CodeGen.castToBottom(mv);
            } else {
                String returnType = NamingCzar.makeBoxedTypeName(f_return, f.tagA);
                InstantiatingClassloader.generalizedCastTo(mv, returnType);
            }
        } else {

            //no inferences needed
            loadThisForMethods(mv);

            for (int j = 0; j < f_type_structures.length; j++) {
                // Load actual parameter
                if (j != selfIndex()) {
                    mv.visitVarInsn(Opcodes.ALOAD, j + firstArgIndex);
                    InstantiatingClassloader.generalizedCastTo(mv, f_type_structures[j].fullname);
                }
            }

            String sig = jvmSignatureFor(f);

            invokeParticularMethod(mv, f, sig);
            Type f_return = f.getReturnType();
            if (f_return instanceof BottomType) {
                CodeGen.castToBottom(mv);
            }
        }

        mv.visitInsn(Opcodes.ARETURN);

        if (lookahead != null)
            mv.visitLabel(lookahead);
    }
}

From source file:com.sun.fortress.runtimeSystem.InstantiatingClassloader.java

License:Open Source License

private byte[] instantiateAbstractArrow(String name, List<String> parameters) {
    ManglingClassWriter cw = new ManglingClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);

    /*//  w w w . j ava2 s. c  o m
     * Special case extensions to plumb tuples
     * correctly in the face of generics instantiated
     * with tuple types.
     * 
     * Except, recall that Arrow parameters are domain...;range
     * 
     * if > 1 param then
     *   unwrap = params
     *   wrap = tuple params
     * else 1 param
     *   if tuple
     *     wrap = param
     *     unwrap = untuple params
     *   else
     *     unwrap = param
     *     wrap = null
     *     
     *  Use unwrapped parameters to generate the all-Objects case
     *  for casting; check the generated signature against the input
     *  to see if we are them.
     *   
     */

    Triple<List<String>, List<String>, String> stuff = normalizeArrowParameters(parameters);

    List<String> flat_params_and_ret = stuff.getA();
    List<String> tupled_params_and_ret = stuff.getB();
    String tupleType = stuff.getC();

    List<String> flat_obj_params_and_ret = Useful.applyToAll(flat_params_and_ret, toJLO);
    List<String> norm_obj_params_and_ret = normalizeArrowParametersAndReturn(flat_obj_params_and_ret);
    List<String> norm_params_and_ret = normalizeArrowParametersAndReturn(flat_params_and_ret);

    String obj_sig = stringListToGeneric(ABSTRACT_ARROW, norm_obj_params_and_ret);
    String obj_intf_sig = stringListToGeneric(Naming.ARROW_TAG, norm_obj_params_and_ret);
    String wrapped_sig = stringListToGeneric(WRAPPED_ARROW, norm_params_and_ret);
    String typed_intf_sig = stringListToGeneric(Naming.ARROW_TAG, norm_params_and_ret);
    String unwrapped_apply_sig;

    if (parameters.size() == 2 && parameters.get(0).equals(Naming.INTERNAL_SNOWMAN))
        unwrapped_apply_sig = arrowParamsToJVMsig(parameters.subList(1, 2));
    else
        unwrapped_apply_sig = arrowParamsToJVMsig(flat_params_and_ret);

    String obj_apply_sig = arrowParamsToJVMsig(flat_obj_params_and_ret);

    String[] interfaces = new String[] { stringListToArrow(norm_params_and_ret) };
    /*
     * Note that in the case of foo -> bar,
     * normalized = flattened, and tupled does not exist (is null).
     */
    String typed_tupled_intf_sig = tupled_params_and_ret == null ? null
            : stringListToGeneric(Naming.ARROW_TAG, tupled_params_and_ret);
    String objectified_tupled_intf_sig = tupled_params_and_ret == null ? null
            : stringListToGeneric(Naming.ARROW_TAG, Useful.applyToAll(tupled_params_and_ret, toJLO));

    boolean is_all_objects = norm_obj_params_and_ret.equals(norm_params_and_ret);

    String _super = is_all_objects ? "java/lang/Object" : obj_sig;

    cw.visit(JVM_BYTECODE_VERSION, ACC_PUBLIC + ACC_SUPER + ACC_ABSTRACT, name, null, _super, interfaces);

    simpleInitMethod(cw, _super);

    /* */
    if (!is_all_objects) {
        // implement method for the object version.
        // cast parameters, invoke this.apply on cast parameters, ARETURN

        // note cut and paste from apply below, work in progress.

        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, obj_apply_sig, null, null);

        mv.visitVarInsn(Opcodes.ALOAD, 0); // this

        int unwrapped_l = flat_params_and_ret.size();

        for (int i = 0; i < unwrapped_l - 1; i++) {
            String t = flat_params_and_ret.get(i);
            if (!t.equals(Naming.INTERNAL_SNOWMAN) || unwrapped_l > 2) {
                mv.visitVarInsn(Opcodes.ALOAD, i + 1); // element
                // mv.visitTypeInsn(CHECKCAST, t);
                generalizedCastTo(mv, Naming.internalToType(t));
            }
        }

        mv.visitMethodInsn(INVOKEVIRTUAL, name, Naming.APPLY_METHOD, unwrapped_apply_sig);
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);

        mv.visitEnd();
    }

    // is instance method -- takes an Object
    {
        String sig = "(Ljava/lang/Object;)Z";
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, IS_A, sig, null, null);

        Label fail = new Label();

        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.INSTANCEOF, Naming.ANY_TYPE_CLASS);
        mv.visitJumpInsn(Opcodes.IFEQ, fail);

        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.CHECKCAST, Naming.ANY_TYPE_CLASS);
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, name, IS_A,
                "(" + Naming.internalToDesc(Naming.ANY_TYPE_CLASS) + ")Z");
        mv.visitInsn(Opcodes.IRETURN);

        mv.visitLabel(fail);
        mv.visitIntInsn(BIPUSH, 0);
        mv.visitInsn(Opcodes.IRETURN);

        mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
        mv.visitEnd();
    }

    // is instance method -- takes an Any
    {
        String sig = "(" + Naming.internalToDesc(Naming.ANY_TYPE_CLASS) + ")Z";
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, IS_A, sig, null, null);
        Label fail = new Label();

        //get RTTI to compare to
        mv.visitFieldInsn(GETSTATIC, name, Naming.RTTI_FIELD, Naming.RTTI_CONTAINER_DESC);
        //get RTTI of object
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(INVOKEINTERFACE, Naming.ANY_TYPE_CLASS, Naming.RTTI_GETTER,
                "()" + Naming.RTTI_CONTAINER_DESC);
        // mv.visitJumpInsn(IFNONNULL, fail);
        mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_CONTAINER_TYPE, Naming.RTTI_SUBTYPE_METHOD_NAME,
                Naming.RTTI_SUBTYPE_METHOD_SIG);

        //mv.visitIntInsn(BIPUSH, 0);
        mv.visitJumpInsn(Opcodes.IFEQ, fail);

        mv.visitIntInsn(BIPUSH, 1);
        mv.visitInsn(Opcodes.IRETURN);

        mv.visitLabel(fail);
        mv.visitIntInsn(BIPUSH, 0);
        mv.visitInsn(Opcodes.IRETURN);
        mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
        mv.visitEnd();
    }

    // castTo
    {
        /*
         *  If arg0 instanceof typed_intf_sig
         *     return arg0
         *  arg0 = arg0.getWrappee()
         *  if arg0 instanceof typed_intf_sig
         *     return arg0
         *  new WrappedArrow
         *  dup
         *  push argo
         *  init
         *  return tos
         */

        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, CAST_TO, "(" +
        // Naming.internalToDesc(obj_intf_sig)
                "Ljava/lang/Object;" + ")" + Naming.internalToDesc(typed_intf_sig), null, null);

        Label not_instance1 = new Label();
        Label not_instance2 = new Label();

        // try bare instanceof
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig);
        mv.visitJumpInsn(Opcodes.IFEQ, not_instance1);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.CHECKCAST, typed_intf_sig);
        mv.visitInsn(Opcodes.ARETURN);

        // unwrap
        mv.visitLabel(not_instance1);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.CHECKCAST, obj_intf_sig);
        mv.visitMethodInsn(INVOKEINTERFACE, obj_intf_sig, getWrappee,
                "()" + Naming.internalToDesc(obj_intf_sig));
        mv.visitVarInsn(Opcodes.ASTORE, 0);

        // try instanceof on unwrapped
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig);
        mv.visitJumpInsn(Opcodes.IFEQ, not_instance2);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.CHECKCAST, typed_intf_sig);
        mv.visitInsn(Opcodes.ARETURN);

        // wrap and return
        mv.visitLabel(not_instance2);
        mv.visitTypeInsn(NEW, wrapped_sig);
        mv.visitInsn(DUP);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, wrapped_sig, "<init>",
                "(" + Naming.internalToDesc(obj_intf_sig) + ")V");

        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);

        mv.visitEnd();
    }

    if (typed_tupled_intf_sig != null) {
        /*
         *  If arg0 instanceof typed_intf_sig
         *     return arg0
         *  arg0 = arg0.getWrappee()
         *  if arg0 instanceof typed_intf_sig
         *     return arg0
         *  new WrappedArrow
         *  dup
         *  push argo
         *  init
         *  return tos
         */

        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, CAST_TO,
                "(" + Naming.internalToDesc(objectified_tupled_intf_sig) + ")"
                        + Naming.internalToDesc(typed_intf_sig),
                null, null);

        Label not_instance1 = new Label();
        Label not_instance2 = new Label();

        // try bare instanceof
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig);
        mv.visitJumpInsn(Opcodes.IFEQ, not_instance1);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitInsn(Opcodes.ARETURN);

        // unwrap
        mv.visitLabel(not_instance1);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(INVOKEINTERFACE, objectified_tupled_intf_sig, getWrappee,
                "()" + Naming.internalToDesc(objectified_tupled_intf_sig));
        mv.visitVarInsn(Opcodes.ASTORE, 0);

        // try instanceof on unwrapped
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitTypeInsn(Opcodes.INSTANCEOF, typed_intf_sig);
        mv.visitJumpInsn(Opcodes.IFEQ, not_instance2);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitInsn(Opcodes.ARETURN);

        // wrap and return - untupled should be okay here, since it subtypes
        mv.visitLabel(not_instance2);
        mv.visitTypeInsn(NEW, wrapped_sig);
        mv.visitInsn(DUP);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, wrapped_sig, "<init>",
                "(" + Naming.internalToDesc(obj_intf_sig) + ")V");

        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);

        mv.visitEnd();
    }

    // getWrappee
    {
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, getWrappee, "()" + Naming.internalToDesc(obj_intf_sig),
                null, null);

        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd(); // return this
    }

    if (tupled_params_and_ret == null) {
        /* Single abstract method */
        if (LOG_LOADS)
            System.err.println(name + ".apply" + unwrapped_apply_sig + " abstract for abstract");
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, Naming.APPLY_METHOD, unwrapped_apply_sig,
                null, null);
        mv.visitEnd();

    } else {
        /*
         * Establish two circular forwarding methods;
         * the eventual implementer will break the cycle.
         * 
         */
        String tupled_apply_sig = arrowParamsToJVMsig(tupled_params_and_ret);

        {
            /* Given tupled args, extract, and invoke apply. */

            if (LOG_LOADS)
                System.err.println(name + ".apply" + tupled_apply_sig + " abstract for abstract");
            MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, tupled_apply_sig, null, null);

            mv.visitVarInsn(Opcodes.ALOAD, 0); // closure

            int unwrapped_l = flat_params_and_ret.size();

            for (int i = 0; i < unwrapped_l - 1; i++) {
                String param = flat_params_and_ret.get(i);
                mv.visitVarInsn(Opcodes.ALOAD, 1); // tuple
                mv.visitMethodInsn(INVOKEINTERFACE, tupleType, TUPLE_TYPED_ELT_PFX + (Naming.TUPLE_ORIGIN + i),
                        "()" + Naming.internalToDesc(param));
            }

            mv.visitMethodInsn(INVOKEVIRTUAL, name, Naming.APPLY_METHOD, unwrapped_apply_sig);
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);

            mv.visitEnd();
        }

        { /* Given untupled args, load, make a tuple, invoke apply. */
            if (LOG_LOADS)
                System.err.println(name + ".apply" + unwrapped_apply_sig + " abstract for abstract");
            MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, unwrapped_apply_sig, null, null);

            mv.visitVarInsn(Opcodes.ALOAD, 0); // closure

            int unwrapped_l = flat_params_and_ret.size();

            for (int i = 0; i < unwrapped_l - 1; i++) {
                mv.visitVarInsn(Opcodes.ALOAD, i + 1); // element
            }

            List<String> tuple_elements = flat_params_and_ret.subList(0, unwrapped_l - 1);

            String make_sig = toJvmSig(tuple_elements, Naming.javaDescForTaggedFortressType(tupleType));
            mv.visitMethodInsn(INVOKESTATIC, stringListToGeneric(CONCRETE_TUPLE, tuple_elements), "make",
                    make_sig);

            mv.visitMethodInsn(INVOKEVIRTUAL, name, Naming.APPLY_METHOD, tupled_apply_sig);
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);

            mv.visitEnd();
        }

    }

    //RTTI comparison field

    final String final_name = name;
    ArrayList<InitializedStaticField> isf_list = new ArrayList<InitializedStaticField>();
    if (!parameters.contains("java/lang/Object")) {

        isf_list.add(new InitializedStaticField.StaticForUsualRttiField(final_name, this));
    } else {
        isf_list.add(new InitializedStaticField.StaticForJLOParameterizedRttiField(final_name));
    }
    cw.visitEnd();
    //      //RTTI getter
    {
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, Naming.RTTI_GETTER, "()" + Naming.RTTI_CONTAINER_DESC,
                null, null);
        mv.visitCode();
        mv.visitFieldInsn(GETSTATIC, name, Naming.RTTI_FIELD, Naming.RTTI_CONTAINER_DESC);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    optionalStaticsAndClassInitForTO(isf_list, cw);
    return cw.toByteArray();
}

From source file:com.sun.fortress.runtimeSystem.InstantiatingClassloader.java

License:Open Source License

/**
 * @param rttiClassName/*from   w w  w .  j  ava  2s. c  o m*/
 * @param sparams_size
 */
static public void emitDictionaryAndFactoryForGenericRTTIclass(ManglingClassWriter cw, String rttiClassName,
        int sparams_size, final Naming.XlationData xldata) {

    // Push nulls for opr parameters in the factory call.
    List<Boolean> spks;
    int type_sparams_size = sparams_size;
    if (xldata != null) {
        spks = xldata.isOprKind();
        sparams_size = spks.size();
    } else {
        spks = new InfiniteList<Boolean>(false);
    }

    // FIELD
    // static, initialized to Map-like thing
    cw.visitField(ACC_PRIVATE + ACC_STATIC + ACC_FINAL, "DICTIONARY", Naming.RTTI_MAP_DESC, null, null);

    // CLINIT
    // factory, consulting map, optionally invoking constructor.
    MethodVisitor mv = cw.visitNoMangleMethod(ACC_STATIC, "<clinit>", "()V", null, null);
    mv.visitCode();
    // new
    mv.visitTypeInsn(NEW, Naming.RTTI_MAP_TYPE);
    // init
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, Naming.RTTI_MAP_TYPE, "<init>", "()V");
    // store
    mv.visitFieldInsn(PUTSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC);

    mv.visitInsn(RETURN);
    mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
    mv.visitEnd();

    // FACTORY

    boolean useSparamsArray = sparams_size > 6;
    int sparamsArrayIndex = sparams_size;

    String fact_sig = Naming.rttiFactorySig(type_sparams_size);
    String init_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes("java/lang/Class",
            type_sparams_size, Naming.RTTI_CONTAINER_TYPE, "V");
    String get_sig;
    String put_sig;
    String getClass_sig;
    if (useSparamsArray) {
        get_sig = Naming.makeMethodDesc(Naming.RTTI_CONTAINER_ARRAY_DESC, Naming.RTTI_CONTAINER_DESC);
        put_sig = Naming.makeMethodDesc(Naming.RTTI_CONTAINER_ARRAY_DESC + Naming.RTTI_CONTAINER_DESC,
                Naming.RTTI_CONTAINER_DESC);
        getClass_sig = Naming.makeMethodDesc(NamingCzar.descString + Naming.RTTI_CONTAINER_ARRAY_DESC,
                NamingCzar.descClass);
    } else {
        get_sig = InstantiatingClassloader.jvmSignatureForNTypes(sparams_size, Naming.RTTI_CONTAINER_TYPE,
                Naming.RTTI_CONTAINER_DESC);
        put_sig = InstantiatingClassloader.jvmSignatureForNTypes(sparams_size + 1, Naming.RTTI_CONTAINER_TYPE,
                Naming.RTTI_CONTAINER_DESC);
        getClass_sig = InstantiatingClassloader.jvmSignatureForOnePlusNTypes(NamingCzar.internalString,
                sparams_size, Naming.RTTI_CONTAINER_TYPE, NamingCzar.descClass);
    }

    mv = cw.visitNoMangleMethod(ACC_PUBLIC + ACC_STATIC, Naming.RTTI_FACTORY, fact_sig, null, null);
    mv.visitCode();
    /* 
     * First arg is java class, necessary for creation of type.
     * 
     * rCN x = DICTIONARY.get(args)
     * if  x == null then
     *   x = new rCN(args)
     *   x = DICTIONARY.put(args, x)
     * end
     * return x
     */

    // object
    mv.visitFieldInsn(GETSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC);
    // push args
    int l = sparams_size;
    if (useSparamsArray) {
        mv.visitLdcInsn(sparams_size);
        mv.visitTypeInsn(Opcodes.ANEWARRAY, Naming.RTTI_CONTAINER_TYPE);
        mv.visitVarInsn(Opcodes.ASTORE, sparamsArrayIndex);
        InstantiatingClassloader.pushArgsIntoArray(mv, 0, l, sparamsArrayIndex, spks);
    } else {
        InstantiatingClassloader.pushArgs(mv, 0, l, spks);
    }
    // invoke Dictionary.get
    mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_MAP_TYPE, "get", get_sig);
    Label not_null = new Label();
    mv.visitInsn(DUP);
    mv.visitJumpInsn(IFNONNULL, not_null);
    mv.visitInsn(POP); // discard dup'd null
    // doing it all on the stack -- (unless too many static params, then use an array for human coded stuff)
    // 1) first push the dictionary and args (array if used) 
    // 2) create new RTTI object
    // 3) push args again (array if used) and create the class for this object
    // 4) push the args again (never array) to init RTTI object
    // 5) add to dictionary

    //1)
    mv.visitFieldInsn(GETSTATIC, rttiClassName, "DICTIONARY", Naming.RTTI_MAP_DESC);

    if (useSparamsArray) {
        mv.visitVarInsn(ALOAD, sparamsArrayIndex);
    } else {
        InstantiatingClassloader.pushArgs(mv, 0, l, spks);
    }

    // 2) invoke constructor
    mv.visitTypeInsn(NEW, rttiClassName);
    mv.visitInsn(DUP);

    // 3) create class for this object
    String stem = Naming.rttiClassToBaseClass(rttiClassName);
    if (true || xldata == null) {
        // NOT symbolic (and a problem if we pretend that it is)
        mv.visitLdcInsn(stem);
    } else {
        RTHelpers.symbolicLdc(mv, stem);
    }
    if (useSparamsArray) {
        mv.visitVarInsn(ALOAD, sparamsArrayIndex);
    } else {
        InstantiatingClassloader.pushArgs(mv, 0, l, spks);
    }

    //(mv, "before getRTTIclass");
    mv.visitMethodInsn(Opcodes.INVOKESTATIC, Naming.RT_HELPERS, "getRTTIclass", getClass_sig);
    //eep(mv, "after getRTTIclass");

    // 4) init RTTI object (do not use array)
    // NOTE only pushing type_sparams here.
    InstantiatingClassloader.pushArgs(mv, 0, type_sparams_size);
    mv.visitMethodInsn(INVOKESPECIAL, rttiClassName, "<init>", init_sig);
    // 5) add to dictionary
    mv.visitMethodInsn(INVOKEVIRTUAL, Naming.RTTI_MAP_TYPE, "putIfNew", put_sig);

    mv.visitLabel(not_null);
    mv.visitInsn(ARETURN);

    mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
    mv.visitEnd();
}

From source file:com.tencent.tinker.build.auxiliaryclass.AuxiliaryClassInjectAdapter.java

License:Open Source License

@Override
public void visitEnd() {
    // If method <clinit> and <init> are not found, we should generate a <clinit>.
    if (!this.isClInitExists && !this.isInitExists) {
        MethodVisitor mv = super.visitMethod(Opcodes.ACC_STATIC, "<clinit>", "()V", null, null);
        mv.visitCode();/*from  w  w  w  . j a v a  2 s  .  c o m*/
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "lineSeparator", "()Ljava/lang/String;",
                false);
        Label lblSkipInvalidInsn = new Label();
        mv.visitJumpInsn(Opcodes.IFNONNULL, lblSkipInvalidInsn);
        mv.visitLdcInsn(Type.getType(this.auxiliaryClassDesc));
        mv.visitVarInsn(Opcodes.ASTORE, 0);
        mv.visitLabel(lblSkipInvalidInsn);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    super.visitEnd();
}

From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java

public void testReplacingThisWithOtherVariable() throws Exception {

    final String FIELDPROXYWORKED = "FIELDPROXYWORKED";

    //set up the proxy object. this is the object that will receive
    //the proxied calls
    TestSubClass tcc = new TestSubClass();
    tcc.setBaseString(FIELDPROXYWORKED);

    TestBaseClassHolder.setTestBase(tcc);

    //get the dynamic source that has the donor body in it
    ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF);
    MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout");

    System.out.println("Donor");
    printMethodNode(donorMethod);/*from  ww  w.ja  v  a2s .c o m*/

    //alright here's the strategy:  (1) inject a new local variable that points 
    //   to our remote instance,
    //  (2) inject code that sets this local to the value of a method call,
    //  (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1

    InsnList instructionsToInject = donorMethod.instructions;

    //make a new local variable
    LabelNode begin = new LabelNode();
    LabelNode end = new LabelNode();
    instructionsToInject.insertBefore(instructionsToInject.getFirst(), begin);
    instructionsToInject.add(end);

    Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass");
    int variableIndex = donorMethod.maxLocals;
    donorMethod.maxLocals += type.getSize();
    donorMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(),
            variableIndex);

    //set the value of the local variable with a new instruction at the top
    //fetch a reference to our proxy object
    MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC,
            "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase",
            "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;");

    //insert after begin label
    instructionsToInject.insert(begin, getTestBase);

    //store reference
    VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex);

    //insert store after fetch
    instructionsToInject.insert(getTestBase, setRef);

    //replace all references to 'this'  with the new variable

    for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) {
        AbstractInsnNode node = instructionsToInject.get(currentIndex);
        if (node.getOpcode() == Opcodes.ALOAD) {
            VarInsnNode vin = (VarInsnNode) node;

            //'this' is var index 0. ours is var index varindex
            if (vin.var == 0) {
                vin.var = variableIndex;
            }
        }
    }

    System.out.println(">>>>>>>>>Finished Modifying<<<<<<<<");
    printMethodNode(donorMethod);
    String NEWCLASSNAME = "ScriptTestClass";

    //write a class 
    Class c = createClassFromClassNode(donorSource, NEWCLASSNAME);

    Object o = c.newInstance();
    Method m = o.getClass().getDeclaredMethod("before_whatDoIThinkAbout", String.class);

    //should return HAHAHA not baseStringValue 
    String result = (String) m.invoke(o, new Object[] { "AAAA" });
    System.out.println("TestDonorClass.whatDoIThinkAbout Result: " + result);
    assertTrue(result.equals(FIELDPROXYWORKED + "AAAA"));
}

From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java

@Test
public void testInjectingIntoMethodWithLotsOfParameters() throws Exception {
    final String FIELDPROXYWORKED = "FIELDPROXYWORKED";

    //set up the proxy object. this is the object that will receive
    //the proxied calls
    TestSubClass tcc = new TestSubClass();
    tcc.setBaseString(FIELDPROXYWORKED);

    TestBaseClassHolder.setTestBase(tcc);

    //get the dynamic source that has the donor body in it
    ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF2);
    MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout");

    System.out.println("Donor Method Before Modifications:");
    printMethodNode(donorMethod);//w w w. j av a2 s . com

    String TARGETCLASSNAME = "com.triage.bytecodemaster.fortesting.Concatenator";
    ClassNode targetSource = loadLocalClass(TARGETCLASSNAME);

    ClassNode exampleSource = loadLocalClass("com.triage.bytecodemaster.fortesting.JustLikeGroovyClass");
    MethodNode exampleMethod = findMethod(exampleSource, "before_whatDoIThinkAbout");

    System.out.println("Example Method-- Should be just like the Donor Source");
    printMethodNode(exampleMethod);
    MethodNode targetMethod = findMethod(targetSource, "concat");
    System.out.println("Target Method <Before Mods>");
    printMethodNode(targetMethod);

    //alright here's the strategy:  (1) inject a new local variable that points 
    //   to our remote instance,
    //  (2) inject code that sets this local to the value of a method call,
    //  (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1

    InsnList instructionsToInject = donorMethod.instructions;
    InsnList targetInstructions = targetMethod.instructions;

    //make a new local variable in the donor method.
    //this variable needs to have a slot high enough that it doesnt
    //conflict with either the target or the source method
    //it will hold references to the objects we replace with 'this'
    LabelNode begin = new LabelNode();
    LabelNode end = new LabelNode();
    targetInstructions.insertBefore(targetInstructions.getFirst(), begin);
    targetInstructions.add(end);

    Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass");
    int variableIndex = targetMethod.maxLocals;
    targetMethod.maxLocals += type.getSize();
    targetMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(),
            variableIndex);

    //set the value of the local variable with a new instruction at the top
    //fetch a reference to our proxy object
    MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC,
            "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase",
            "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;");

    //insert after begin label
    targetInstructions.insert(begin, getTestBase);

    //store reference
    VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex);

    //insert store after fetch
    targetInstructions.insert(getTestBase, setRef);

    //replace all references to 'this' in the DONOR method with the new variable
    //in the TARGET code

    for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) {
        AbstractInsnNode node = instructionsToInject.get(currentIndex);
        if (node.getOpcode() == Opcodes.ALOAD) {
            VarInsnNode vin = (VarInsnNode) node;

            //'this' is var index 0. ours is var index varindex
            if (vin.var == 0) {
                vin.var = variableIndex;
            }
        }

        //remove return methods. this will prevent a return. it should cause the donor 
        //method to have parameters that overlap with the target, which has more parameters
        if (node.getOpcode() == Opcodes.RETURN || node.getOpcode() == Opcodes.ARETURN) {
            instructionsToInject.remove(node);
        }
    }

    System.out.println(">>>>>>>>>Finished Modifying Donor Method <<<<<<<<");
    printMethodNode(donorMethod);
    String NEWCLASSNAME = "ScriptTestClass";

    //stash instructions at the beginning of the original method, 
    //but after populating the new variable
    targetInstructions.insert(setRef, instructionsToInject);

    System.out.println("Modified Target:");
    printMethodNode(targetMethod);

    //write a class 
    Class c = createClassFromClassNode(targetSource, TARGETCLASSNAME);

    Object o = c.newInstance();
    Method m = o.getClass().getDeclaredMethod("concat", String.class, String.class, String.class, String.class);

    //should return HAHAHA not baseStringValue 
    String result = (String) m.invoke(o, new Object[] { "A", "B", "C", "D" });
    System.out.println("Concatenator.concat Result: " + result);
    assertTrue(result.equals("ABCD"));

}

From source file:com.triage.bytecodemaster.TestObjectReferenceSwitches.java

public void testMergedInReplacingThisWithOtherVariable() throws Exception {

    final String FIELDPROXYWORKED = "FIELDPROXYWORKED";

    //set up the proxy object. this is the object that will receive
    //the proxied calls
    TestSubClass tcc = new TestSubClass();
    tcc.setBaseString(FIELDPROXYWORKED);

    TestBaseClassHolder.setTestBase(tcc);

    //get the dynamic source that has the donor body in it
    ClassNode donorSource = loadGroovyTestClassAsBytecode(GROOVY_CLASS_FIELDREF);
    MethodNode donorMethod = findMethod(donorSource, "before_whatDoIThinkAbout");

    //load the target class
    String TARGETCLASSNAME = "com.triage.bytecodemaster.fortesting.TestFriend";
    ClassNode targetSource = loadLocalClass(TARGETCLASSNAME);
    MethodNode targetMethod = findMethod(targetSource, "whatDoIThinkAbout");

    System.out.println("Target");
    printMethodNode(targetMethod);/*from  w w w .  ja v  a2s .c o m*/

    System.out.println("Donor");
    printMethodNode(donorMethod);

    //alright here's the strategy:  (1) inject a new local variable that points 
    //   to our remote instance,
    //  (2) inject code that sets this local to the value of a method call,
    //  (3) change references to 'this' ( ALOAD0 or ALOAD 0 ) to ALOAD1

    InsnList instructionsToInject = donorMethod.instructions;

    //make a new local variable
    LabelNode begin = new LabelNode();
    LabelNode end = new LabelNode();
    instructionsToInject.insertBefore(instructionsToInject.getFirst(), begin);
    instructionsToInject.add(end);

    Type type = Type.getObjectType("com/triage/bytecodemaster/fortesting/TestBaseClass");
    int variableIndex = donorMethod.maxLocals;
    donorMethod.maxLocals += type.getSize();
    donorMethod.visitLocalVariable("proxy", type.getDescriptor(), null, begin.getLabel(), end.getLabel(),
            variableIndex);

    //set the value of the local variable with a new instruction at the top
    //fetch a reference to our proxy object
    MethodInsnNode getTestBase = new MethodInsnNode(Opcodes.INVOKESTATIC,
            "com/triage/bytecodemaster/fortesting/TestBaseClassHolder", "getTestBase",
            "()Lcom/triage/bytecodemaster/fortesting/TestBaseClass;");

    //insert after begin label
    instructionsToInject.insert(begin, getTestBase);

    //store reference
    VarInsnNode setRef = new VarInsnNode(Opcodes.ASTORE, variableIndex);

    //insert store after fetch
    instructionsToInject.insert(getTestBase, setRef);

    //replace all references to 'this'  with the new variable

    for (int currentIndex = 0; currentIndex < instructionsToInject.size(); currentIndex++) {
        AbstractInsnNode node = instructionsToInject.get(currentIndex);
        if (node.getOpcode() == Opcodes.ALOAD) {
            VarInsnNode vin = (VarInsnNode) node;

            //'this' is var index 0. ours is var index varindex
            if (vin.var == 0) {
                vin.var = variableIndex;
            }
        }
    }

    System.out.println(">>>>>>>>>Finished Modifying<<<<<<<<");
    printMethodNode(donorMethod);

    //insert the donorMethod
    targetMethod.instructions.insert(instructionsToInject);

    System.out.println(">>>>>>>>>Final Method<<<<<<<<");
    printMethodNode(targetMethod);

    //write a class 
    Class c = createClassFromClassNode(targetSource, TARGETCLASSNAME);

    Object o = c.newInstance();
    Method m = o.getClass().getDeclaredMethod("whatDoIThinkAbout", TestPerson.class);
    TestPerson testPerson = new TestPerson();
    testPerson.setName("AAAA");
    //should return HAHAHA not baseStringValue 
    String result = (String) m.invoke(o, new Object[] { testPerson });
    System.out.println("TestFriend.whatDoIThinkAbout Result: " + result);
    assertTrue(result.equals(FIELDPROXYWORKED + "AAAA"));
}