Example usage for org.objectweb.asm MethodVisitor visitEnd

List of usage examples for org.objectweb.asm MethodVisitor visitEnd

Introduction

In this page you can find the example usage for org.objectweb.asm MethodVisitor visitEnd.

Prototype

public void visitEnd() 

Source Link

Document

Visits the end of the method.

Usage

From source file:com.sun.fortress.compiler.nativeInterface.fortressConverter.java

License:Open Source License

private MethodVisitor generateNewBody(int access, String desc, String signature, String[] exceptions,
        String name, String newName) {

    Debug.debug(Debug.Type.COMPILER, 1, "generateNewBody: ", name, " with desc ", desc);

    SignatureParser sp = new SignatureParser(desc);

    List<String> desc_args = sp.getJVMArguments();
    String desc_result = sp.getJVMResult();
    List<String> fortress_args = new ArrayList<String>();
    List<fortressConverter> convert_args = new ArrayList<fortressConverter>();

    String fsig = "(";
    StringBuilder buf = new StringBuilder();
    buf.append(fsig);/*ww w .j  a v a2  s .  c  o m*/
    for (String s : desc_args) {

        SignatureAndConverter s_a_c = toImplFFFF(s, name, false);
        buf.append(s_a_c.signature);
        fortress_args.add(s_a_c.signature);

        convert_args.add(s_a_c.converter);
    }
    fsig = buf.toString();
    SignatureAndConverter s_a_c = toImplFFFF(desc_result, name, true);
    fsig = fsig + ")" + s_a_c.signature;

    fortressConverter convert_result = s_a_c.converter;

    // FORWARDING METHOD, only with type conversions on the way in/out!
    MethodVisitor mv = cv.visitMethod(access, name, fsig, signature, exceptions);
    mv.visitCode();
    Label l0 = new Label();
    mv.visitLabel(l0);
    int count = 0;
    for (String s : fortress_args) {
        fortressConverter converter = convert_args.get(count);
        mv.visitVarInsn(Opcodes.ALOAD, count++);
        converter.convertArg(mv, s);
    }

    Debug.debug(Debug.Type.COMPILER, 1, "className = ", inputClassName, " name = ", name, " access = ", access);

    mv.visitMethodInsn(Opcodes.INVOKESTATIC, inputClassName, name, sp.getSignature());

    convert_result.convertResult(mv, s_a_c.signature);

    mv.visitInsn(Opcodes.ARETURN);
    mv.visitMaxs(2, 1);
    mv.visitEnd();
    return mv;
}

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

License:Open Source License

protected void generateBody(MethodVisitor mv, int one_if_method_closure) {
    mv.visitCode();//from w  w  w  . j  a  v  a 2  s  . co  m
    //   Label fail = new Label();

    generateCall(mv, firstArg(), one_if_method_closure); // Guts of overloaded method

    // Emit failure case
    //        mv.visitLabel(fail);
    //        // Boilerplate for throwing an error.
    //        // mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);

    mv.visitMethodInsn(Opcodes.INVOKESTATIC, NamingCzar.miscCodegen, NamingCzar.matchFailure,
            NamingCzar.errorReturn);
    mv.visitInsn(Opcodes.ATHROW);

    mv.visitMaxs(getParamCount(), getParamCount()); // autocomputed
    mv.visitEnd();
}

From source file:com.sun.fortress.interpreter.env.ClosureMaker.java

License:Open Source License

public static byte[] forTopLevelFunction(APIName apiname, FnDecl fd, String closureClass, String aClass,
        String aMethod) throws Exception {

    //IdOrOp ua_name = fd.getUnambiguousName();
    /*/*from w  w  w  .j  a v a2  s  .  c  om*/
     This is a cheat; ought to be more algorithmic, so this will
     work in general, not just for native wrappers.  Proper
     algorithm derives it from the FnDecl.
     */
    String md = ForeignJava.only.methodToDecl.inverse().get(fd);

    /*
     translate apiname into package name
     extract aClass from name
     md is the method name.
            
     need to generate a class, extending
     com.sun.fortress.interpreter.Glue.NativeFn#,
     where # is the number of parameters in the decl,
            
     that class must contain a method (say, #=3)
      FValue applyToArgs(FValue x, FValue y, FValue z) {
    return package.class.md(x,y,z);
      }
     and that is all.
    */
    String pkg_dots = NamingCzar.apiNameToPackageName(apiname);
    String pkg_slashes = Useful.replace(pkg_dots, ".", "/");
    int nargs = fd.getHeader().getParams().size();

    String nativeHelper = "com/sun/fortress/interpreter/glue/NativeFn" + nargs;
    String nativeWrapperClass = pkg_slashes + "/" + aClass;
    String LclosureClass = "L" + closureClass + ";";
    String fvalue = "Lcom/sun/fortress/interpreter/evaluator/values/FValue;";

    String signature = "(";
    StringBuilder buf = new StringBuilder();
    buf.append(signature);
    for (int i = 1; i <= nargs; i++) {
        buf.append(fvalue);
    }
    signature = buf.toString();
    signature += ")" + fvalue;

    System.err.println(md);

    ClassWriter cw = new ClassWriter(0);
    MethodVisitor mv;

    cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, closureClass, null, nativeHelper, null);

    cw.visitSource(null, null);

    {
        mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(INVOKESPECIAL, nativeHelper, "<init>", "()V");
        mv.visitInsn(RETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", LclosureClass, null, l0, l1, 0);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }
    {
        mv = cw.visitMethod(ACC_PROTECTED, "applyToArgs", signature, null, null);
        mv.visitCode();
        Label l0 = new Label();
        mv.visitLabel(l0);
        for (int i = 1; i <= nargs; i++) {
            mv.visitVarInsn(ALOAD, i);
        }
        mv.visitMethodInsn(INVOKESTATIC, nativeWrapperClass, aMethod, signature);
        mv.visitInsn(ARETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);
        mv.visitLocalVariable("this", LclosureClass, null, l0, l1, 0);
        for (int i = 1; i <= nargs; i++) {
            mv.visitLocalVariable("p" + i, fvalue, null, l0, l1, 1);
        }
        mv.visitMaxs(nargs, nargs + 1);
        mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
}

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

License:Open Source License

@Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
    // necessary?
    name = oprs.getMethodName(name);//from   w ww .j  a va  2 s  .c om
    //System.out.println("old desc=" + desc);
    //desc = types.getMethodDesc(desc);
    //System.out.println("new desc=" + desc);
    String newDesc = types.getMethodDesc(desc);
    MethodVisitor mv = cv.visitMethod(access, name, newDesc, signature, exceptions);

    if (!desc.equals(newDesc)) { // catch flattened tuples
        String params = desc.substring(desc.indexOf("(") + 1, //TODO: wrong if nested parens
                desc.indexOf(")"));
        String newParams = newDesc.substring(newDesc.indexOf("(") + 1, newDesc.indexOf(")"));
        if (params.split(";").length == 1 && //single generic parameter 
                newParams.startsWith("LTuple")) { //tuple substituted in
            //System.out.println(access + " " + name + " " + signature + " " +this.instanceName);
            if ((this.access_flags & Opcodes.ACC_INTERFACE) == 0 && //not in an interface
                    (access & Opcodes.ACC_STATIC) == 0) { //and not a static method, so generate a body  

                //extract the parameters and create strings for the types 
                List<String> paramList = InstantiationMap.extractStringParameters(newParams,
                        newParams.indexOf(Naming.LEFT_OXFORD),
                        InstantiationMap.templateClosingRightOxford(newParams), new ArrayList<String>());
                String rawParams = "";
                for (String p : paramList)
                    rawParams = rawParams + Naming.internalToDesc(p);
                final String altDesc = newDesc.substring(0, newDesc.indexOf("(") + 1) + rawParams
                        + newDesc.substring(newDesc.indexOf(")"), newDesc.length());
                String tuple_params = InstantiatingClassloader.stringListToTuple(paramList);
                String make_sig = InstantiatingClassloader.toJvmSig(paramList,
                        Naming.javaDescForTaggedFortressType(tuple_params));

                MethodVisitor altMv = cv.visitMethod(access, name, altDesc, signature, exceptions);

                altMv.visitVarInsn(Opcodes.ALOAD, 0); //load this

                final int n = paramList.size(); //load the parameters
                for (int i = 1; i <= n; i++) {
                    altMv.visitVarInsn(Opcodes.ALOAD, i);
                }
                altMv.visitMethodInsn(Opcodes.INVOKESTATIC, InstantiatingClassloader.CONCRETE_ + tuple_params,
                        "make", make_sig); //create a tuple from the parameters

                if (name.equals("<init>")) {
                    altMv.visitMethodInsn(Opcodes.INVOKESPECIAL, this.instanceName, name, newDesc); //call original method
                    altMv.visitInsn(Opcodes.RETURN); //return
                } else {
                    altMv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, this.instanceName, name, newDesc); //call original method
                    altMv.visitInsn(Opcodes.ARETURN); //return
                }
                altMv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
                altMv.visitEnd();
            }
        }
    }
    return new MethodInstantiater(mv, types, icl);
}

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

License:Open Source License

public static String closureClassPrefix(String name, ManglingClassWriter cw, String staticClass, String sig,
        boolean is_forwarding_closure, String forceCastParam0, List<InitializedStaticField> statics) {
    int env_loc = name.indexOf(Naming.ENVELOPE);
    int last_dot = name.substring(0, env_loc).lastIndexOf('$');

    String api = name.substring(0, last_dot);
    String suffix = name.substring(last_dot + 1);
    env_loc = suffix.indexOf(Naming.ENVELOPE); // followed by $
    String fn = is_forwarding_closure ? suffix.substring(0, env_loc) : Naming.APPLIED_METHOD;
    String ft = suffix.substring(env_loc + 2); // skip $ following ENVELOPE

    // Normalize out leading HEAVY_CROSS, if there is one.
    {/*from   www  .  j a v  a 2s . c  o m*/
        if (ft.charAt(0) == Naming.HEAVY_CROSS_CHAR)
            ft = ft.substring(1);

        // Allow bound-specific disambiguation in a suffix
        int hvy_x = ft.indexOf(Naming.HEAVY_X_CHAR);
        if (hvy_x != -1)
            ft = ft.substring(0, hvy_x);

        int left = ft.indexOf(Naming.LEFT_OXFORD);
        int right = ft.lastIndexOf(Naming.RIGHT_OXFORD);
        List<String> parameters = RTHelpers.extractStringParameters(ft, left, right);

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

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

        if (sig == null)
            sig = arrowParamsToJVMsig(flat_params_and_ret);
    }

    SignatureParser sp = new SignatureParser(sig);

    /*
     * Recipe:
     * need to emit class "name".
     * It needs to extend AbstractArrow[\parameters\]
     * It needs to contain
     *   RT apply (params_except_last) {
     *     return api.fn(params_except_last);
     *   }
     */

    FieldVisitor fv;
    MethodVisitor mv;
    String superClass = ABSTRACT_ + ft; // ft is assumed to begin with "Arrow"
    name = api.replace(".", "/") + '$' + suffix;
    final String final_name = name;

    //String desc = Naming.internalToDesc(name);
    final String field_desc = Naming.internalToDesc(ft);
    // Begin with a class
    cw.visit(JVM_BYTECODE_VERSION, ACC_PUBLIC + ACC_SUPER, name, null, superClass, null);

    statics.add(new InitializedStaticField.StaticForClosureField(field_desc, final_name));

    //RTTI field
    //        statics.add(new InitializedStaticField() {
    //
    //            @Override
    //            public void forClinit(MethodVisitor init_mv) {
    //               MethodInstantiater mi = new MethodInstantiater(init_mv, null, null);
    //               mi.rttiReference(final_name + Naming.RTTI_CLASS_SUFFIX);
    //               init_mv.visitFieldInsn(PUTSTATIC, final_name, Naming.RTTI_FIELD, Naming.RTTI_CONTAINER_DESC);
    //            }
    //
    //            @Override
    //            public String asmName() {
    //                return Naming.RTTI_FIELD;
    //            }
    //
    //            @Override
    //            public String asmSignature() {
    //                return Naming.RTTI_CONTAINER_DESC;
    //            }});

    // Instance init does nothing special
    mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    // Supertype is mangle("Abstract"+ft)
    mv.visitMethodInsn(INVOKESPECIAL, superClass, "<init>", "()V");
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();

    // What if staticClass is compiler builtin?  How do we know?
    if (staticClass == null)
        staticClass = api;
    staticClass = staticClass.replace(".", "/");

    if (LOG_LOADS)
        System.err.println(name + ".apply" + sig + " concrete\nparams = " + sp);

    // KBN 06/2011 handled above now
    // Monkey business to deal with case of "void" args.
    //int sz = parameters.size();
    // Last parameter is actually result type!
    // But we need to include an extra arg in sz to represent the closure itself (this).
    // if (sz==2 && Naming.INTERNAL_SNOWMAN.equals(parameters.get(0))) {
    // Arity 1 (sz 2) with void parameter should actually be arity 0 (sz 1).
    //    sz = 1;
    //}

    // Emit a method with well-known name ("apply", most likely)
    // to forward calls from the instance to the static, which our
    // caller will supply.  Note that the static class can be a
    // different class.
    forwardingMethod(cw, Naming.APPLY_METHOD, ACC_PUBLIC, 0, staticClass, fn, INVOKESTATIC, sig, sig,
            sp.paramCount() + 1, false, forceCastParam0);

    return fn;

}

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

License:Open Source License

/**
 * Emits a forwarding method.//from  w  ww  .j ava 2s  .c om
 * 
 * Cases:
 * apply static, target static
 * apply instance, target static
 * apply instance, target instance
 * 
 * @param cw Classwriter that will write the forwarding method
 * @param thisName       name of the generated (forwarding) method
 * @param thisModifiers  modifiers for the generated (forwarding) method
 * @param selfIndex      index of the self parameter, if any
 * @param fwdClass       class for the target method
 * @param fwdName        name of the target method
 * @param fwdOp          the appropriate INVOKE opcode for the forward
 * @param thisSig        the signature of the generated (forwarding) method
 * @param fwdSig         the signature of the target (called) method
 * @param selfCastSig    a full signature containing self at selfIndex
 * @param nparamsIncludingSelf number of parameters, including self (if any)
 * @param pushSelf       if true, push self first, using selfIndex to find it
 * @param forceCastParam0 cast param 0, even if it is not self.  This is for
 *                        implementation of generic methods.  It may need
 *                        to be generalized to all params, not entirely sure.
 * @param castReturn      cast the return type to what it "ought" to be.
 *                        deals with BottomType case.  Makes verifier happy.
 */
public static void forwardingMethod(ClassWriter cw, String thisName, int thisModifiers, int selfIndex,
        String fwdClass, String fwdName, int fwdOp, String thisSig, String fwdSig, String selfCastSig,
        int nparamsIncludingSelf, boolean pushSelf, String forceCastParam0, boolean castReturn) {
    String selfSig = null;
    if (pushSelf) {
        if (selfCastSig != null) {
            selfSig = Naming.nthSigParameter(selfCastSig, selfIndex);
            selfSig = selfSig.substring(1, selfSig.length() - 1);
        }
        if ((thisModifiers & ACC_STATIC) != 0) {
            if (fwdOp != INVOKESTATIC) {
                // receiver has explicit self, fwd is dotted.
                fwdSig = Naming.removeNthSigParameter(fwdSig, selfIndex);
            }
        } else if (fwdOp == INVOKESTATIC) {
            thisSig = Naming.removeNthSigParameter(thisSig, selfIndex);
        }
    } else if (selfIndex >= 0 && (thisModifiers & ACC_STATIC) != 0) {
        // Dropping explicit self parameter, so remove from signature.
        fwdSig = Naming.removeNthSigParameter(fwdSig, selfIndex);
    }

    if (forceCastParam0 != null) {
        fwdSig = Naming.replaceNthSigParameter(fwdSig, 0, Naming.internalToDesc(forceCastParam0));
    }

    // System.err.println("Forwarding "+thisName+":"+thisSig+
    //                    " arity "+nparamsIncludingSelf+"\n"+
    //                    "  to       "+fwdClass+"."+fwdName+":"+fwdSig);
    MethodVisitor mv = cw.visitMethod(thisModifiers, thisName, thisSig, null, null);
    mv.visitCode();

    SignatureParser sp = new SignatureParser(fwdSig);

    int parsed_arg_cursor = 0;

    if (pushSelf) {
        mv.visitVarInsn(ALOAD, selfIndex);
        if (selfSig != null)
            mv.visitTypeInsn(CHECKCAST, selfSig);
        if (fwdOp == INVOKESTATIC)
            parsed_arg_cursor++;
    }

    pushParamsNotSelf(selfIndex, nparamsIncludingSelf, forceCastParam0, mv, sp, parsed_arg_cursor);

    mv.visitMethodInsn(fwdOp, fwdClass, fwdName, fwdSig);
    // optional CAST here for tuple and arrow
    String tyName = Naming.sigRet(thisSig);
    if (tyName.startsWith(Naming.TUPLE_OX) || tyName.startsWith(Naming.ARROW_OX) || castReturn) {
        String tyNameFrom = Naming.sigRet(fwdSig);
        InstantiatingClassloader.generalizedCastTo(mv, tyName);
    }

    mv.visitInsn(ARETURN);

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

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

License:Open Source License

/**
 * Generates an interface method (public, abstract) with specified name
 * and signature./*from  w  w  w .j  a va  2 s  . com*/
 * 
 * @param cw
 * @param m
 * @param sig
 */
private static void interfaceMethod(ManglingClassWriter cw, String m, String sig) {
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_ABSTRACT, m, sig, null, null);
    mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
    mv.visitEnd();
}

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

License:Open Source License

/**
 * Generate a trivial init method.// ww  w.  j a  v  a2  s  . com
 * 
 * @param cw
 * @param _super
 */
private static void simpleInitMethod(ManglingClassWriter cw, String _super) {
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, _super, "<init>", "()V");
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
}

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

License:Open Source License

/**
 * Creates the interface for an Arrow type.  An Arrow interface includes
 * 2 or 3 methods.  One is the simple domain-to-range "apply", where domain
 * is the determined by the parameters of the generic, taken as is.
 * The next "apply" method replaces all types in the domain and range
 * with java/lang/Object, for use in certain contexts (coerced arrows
 * for casts, also for dynamically instantiated generic functions).  The
 * third apply method is generated if there is more than parameter to the
 * function, in which case the parameters are wrapped in a tuple, or if the
 * first parameter is a Tuple, in which case they will be unwrapped.
 * /* w  ww  .  j  av a  2  s. c  om*/
 * For example, Arrow[\T;U;V\] will have the apply methods (ignore
 * both Fortress and JVM dangerous characters mangling issues for now):
 * 
 * apply(LT;LU;)LV;
 * 
 * apply(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
 * 
 * apply(LTuple[\T;U\];)LV
 * 
 * @param name
 * @param parameters
 * @return
 */

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

    // newer boilerplate copied from abstract arrow and wrapped arrow
    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 tuple_type = 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("Arrow", flat_obj_params_and_ret);
    String norm_obj_sig = stringListToGeneric("Arrow", norm_obj_params_and_ret);

    boolean is_all_objects = flat_obj_params_and_ret.equals(flat_params_and_ret);
    // might need to make Tuple also subtype Object
    String[] super_interfaces = null;
    if (!is_all_objects) {
        super_interfaces = new String[] { norm_obj_sig };
    } else {
        super_interfaces = new String[] { "fortress/AnyType$Any" };
    }

    cw.visit(JVM_BYTECODE_VERSION, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE, name, null, "java/lang/Object",
            super_interfaces);

    /* If more than one domain parameter, then also include the tupled apply method. */
    int l = parameters.size();
    if (tupled_params_and_ret != null) {
        String sig = arrowParamsToJVMsig(tupled_params_and_ret);
        if (LOG_LOADS)
            System.err.println(name + ".apply" + sig + " abstract");
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, Naming.APPLY_METHOD, sig, null, null);
        mv.visitEnd();
    }

    {
        String sig;
        if (parameters.size() == 2 && parameters.get(0).equals(Naming.INTERNAL_SNOWMAN))
            sig = arrowParamsToJVMsig(parameters.subList(1, 2));
        else
            sig = arrowParamsToJVMsig(flat_params_and_ret);
        if (LOG_LOADS)
            System.err.println(name + ".apply" + sig + " abstract");
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, Naming.APPLY_METHOD, sig, null, null);
        mv.visitEnd();
    }
    {
        String sig = "()" + Naming.internalToDesc(norm_obj_sig);
        if (LOG_LOADS)
            System.err.println(name + ".getWrappee" + sig + " abstract");
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, getWrappee, sig, null, null);
        mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
}

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

License:Open Source License

private static byte[] instantiateWrappedArrow(String name, List<String> parameters) {
    ManglingClassWriter cw = new ManglingClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
    /*/*from   www  .  j a  va 2s . co  m*/
     * extends AbstractArrow[\parameters\]
     * 
     * private final Arrow[\Object...Object\] wrappee
     * 
     * Arrow[\Object...Object\] getWrappee()
     * 
     * WrappedArrow[\parameters\](Arrow[\Object...Object\] _wrappee)
     * 
     * public range_parameter apply( domain_parameters ) = 
     *   (range_parameter) wrappee.apply( domain_parameters )
     */
    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 extendsClass = stringListToGeneric(ABSTRACT_ARROW, norm_params_and_ret);

    // List<String> objectified_parameters = Useful.applyToAll(flat_params_and_ret, toJLO);
    //String obj_sig = stringListToGeneric("AbstractArrow", objectified_parameters);
    String obj_intf_sig = stringListToGeneric(Naming.ARROW_TAG, norm_obj_params_and_ret);
    String wrappee_name = "wrappee";

    //extends AbstractArrow[\parameters\]
    cw.visit(JVM_BYTECODE_VERSION, ACC_PUBLIC + ACC_SUPER, name, null, extendsClass, null);

    // private final Arrow[\Object...Object\] wrappee
    cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, wrappee_name, Naming.internalToDesc(obj_intf_sig),
            null /* for non-generic */, null /* instance has no value */);

    // WrappedArrow[\parameters\](Arrow[\Object...Object\] _wrappee)
    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(" + Naming.internalToDesc(obj_intf_sig) + ")V",
            null, null);
    mv.visitCode();
    // super()
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKESPECIAL, extendsClass, "<init>", "()V");
    // this.wrappee = wrappee
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitFieldInsn(PUTFIELD, name, wrappee_name, Naming.internalToDesc(obj_intf_sig));
    // done
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();

    // getWrappee

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

    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, name, wrappee_name, Naming.internalToDesc(obj_intf_sig));
    mv.visitInsn(ARETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();

    //  public range_parameter apply( domain_parameters ) = 
    //    (range_parameter) wrappee.apply( domain_parameters )

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

    String obj_apply_sig = arrowParamsToJVMsig(flat_obj_params_and_ret);

    mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, flattened_apply_sig, null, null);
    mv.visitCode();

    // load wrappee for delegation
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, name, wrappee_name, Naming.internalToDesc(obj_intf_sig));

    // Push parameters.
    // i is indexed so that it corresponds to parameters pushed, even though
    // the types are ignored here (for now).
    for (int i = 0; i < flat_params_and_ret.size() - 1; i++) {
        String t = flat_params_and_ret.get(i);
        if (!t.equals(Naming.INTERNAL_SNOWMAN)) {
            mv.visitVarInsn(ALOAD, i + 1);
        } else {
            /* we are calling the object-interface version of this,
             * we need something on the stack, or else it will fail.
             * 
             * This is also a naming/refactoring FAIL; this information
             * needs to come from somewhere else.
            */
            mv.visitInsn(Opcodes.ACONST_NULL);
            //                mv.visitMethodInsn(Opcodes.INVOKESTATIC,
            //                        Naming.runtimeValues + "FVoid", "make",
            //                        "()" + Naming.internalToDesc(Naming.runtimeValues + "FVoid"));
        }
    }

    mv.visitMethodInsn(INVOKEINTERFACE, obj_intf_sig, Naming.APPLY_METHOD, obj_apply_sig);

    // mv.visitTypeInsn(Opcodes.CHECKCAST, parameters.get(parameters.size()-1));
    generalizedCastTo(mv, flat_params_and_ret.get(flat_params_and_ret.size() - 1));

    // done
    mv.visitInsn(ARETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();

    //getRTTI - forwards to wrapped arrow
    {
        mv = cw.visitMethod(ACC_PUBLIC, Naming.RTTI_GETTER, "()" + Naming.RTTI_CONTAINER_DESC, null, null);
        mv.visitCode();
        // load wrappee for delegation
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(GETFIELD, name, wrappee_name, Naming.internalToDesc(obj_intf_sig));

        //invoke interface getRTTI method
        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, Naming.ANY_TYPE_CLASS, Naming.RTTI_GETTER,
                Naming.STATIC_PARAMETER_GETTER_SIG);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

    }
    cw.visitEnd();

    return cw.toByteArray();

}