Example usage for org.objectweb.asm MethodVisitor visitMethodInsn

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

Introduction

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

Prototype

@Deprecated
public void visitMethodInsn(final int opcode, final String owner, final String name, final String descriptor) 

Source Link

Document

Visits a method instruction.

Usage

From source file:com.sixrr.metrics.profile.instanceHolder.MetricInstanceHolder.java

License:Apache License

private void loadMetricsFromProviders() {
    for (MetricProvider provider : MetricProvider.EXTENSION_POINT_NAME.getExtensions()) {
        final List<Class<? extends Metric>> classesForProvider = provider.getMetricClasses();

        for (Class<? extends Metric> aClass : classesForProvider) {
            try {
                myMetricInstances.put(aClass.getName(), aClass.newInstance());
            } catch (InstantiationException e) {
                MetricInstanceHolder.LOGGER.error(e);
            } catch (IllegalAccessException e) {
                MetricInstanceHolder.LOGGER.error(e);
            }//  w ww .j a  v a2s.  co m
        }
    }

    for (Metric metric : Metric.EP_NAME.getExtensions()) {
        myMetricInstances.put(metric.getClass().getName(), metric);
    }

    // add some magic
    // in Profiles it stored by ClassName. Line Of code is can be handle without new metrics, need only extends  LinesOfCodeProjectMetric with
    // new name
    for (LineOfCodeFileTypeProviderEP ep : LineOfCodeFileTypeProviderEP.EP_NAME.getExtensions()) {
        FileType fileTypeByFileName = FileTypeRegistry.getInstance().findFileTypeByName(ep.fileType);

        if (fileTypeByFileName == null) {
            LOGGER.error("File type is unknown: " + ep.fileType);
            fileTypeByFileName = PlainTextFileType.INSTANCE;
        }
        String lineOfCodeClass = Type.getInternalName(LinesOfCodeProjectMetric.class);
        String className = lineOfCodeClass + "$" + ep.fileType;

        ClassWriter writer = new ClassWriter(Opcodes.F_FULL);
        writer.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, className, null, lineOfCodeClass, null);

        String desc = Type.getConstructorDescriptor(LinesOfCodeProjectMetric.class.getConstructors()[0]);
        MethodVisitor methodVisitor = writer.visitMethod(Opcodes.ACC_PUBLIC, "<init>", desc, null, null);

        methodVisitor.visitMaxs(2, 2);
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);
        methodVisitor.visitVarInsn(Opcodes.ALOAD, 1);
        methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, lineOfCodeClass, "<init>", desc);
        methodVisitor.visitInsn(Opcodes.RETURN);
        methodVisitor.visitEnd();
        writer.visitEnd();

        Class<?> aClass = defineClass(className.replace("/", "."), writer.toByteArray());

        try {
            myMetricInstances.put(aClass.getName(),
                    (Metric) aClass.getConstructors()[0].newInstance(fileTypeByFileName));
        } catch (InstantiationException e) {
            LOGGER.error(e);
        } catch (IllegalAccessException e) {
            LOGGER.error(e);
        } catch (InvocationTargetException e) {
            LOGGER.error(e);
        }
    }
}

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

License:Open Source License

public void toAsm(MethodVisitor mv) {
    mv.visitMethodInsn(opcode, owner, _name, desc);
}

From source file:com.sun.fortress.compiler.codegen.CodeGen.java

License:Open Source License

/**
 * //from   w w w .  j  a va  2s  .  c o  m
 * Deals with overloading and narrowed signatures in the mapping
 * from Fortress methods to Java methods.
 * 
 * The problem comes, e.g., if
 * trait T 
 *   m(T):T
 * end
 * 
 * object O extends T
 *   m(T):O
 * end
 * 
 * In the translation to Java, O's m has a different return type from T's m,
 * thus it has a different signature, thus it does not properly override it
 * in the generated bytecodes.  This has to be detected, and a forwarding 
 * method for O.(T):T has to be created so that calls to T.m(T):T will
 * arrive at O.(T):O.
 * 
 * There are variants of this problem created when T defines a non-abstract
 * m(T), and O defines m(O) -- in that case, there needs to be O.m(x:T) that
 * performs the overloading.
 * 
 *   if (x instanceof O)
 *   then O.m((O)x)
 *   else T.m(x)
 *   Note that because the overloading is only valid in the case
 *   that T defined a method with a body, T.m(x) is expressed as
 *   T$defaultTraitMethods(self, x).
 * 
 * 
 * @param superInterfaces
 * @param includeCurrent
 * @return 
 */

private Map<IdOrOpOrAnonymousName, MultiMap<Integer, Functional>> dumpOverloadedMethodChaining(
        String[] superInterfaces, boolean includeCurrent) {
    Map<IdOrOpOrAnonymousName, MultiMap<Integer, Functional>> overloadedMethods = new HashMap<IdOrOpOrAnonymousName, MultiMap<Integer, Functional>>();

    /*
     * If the number of supertraits is 0, there is nothing to override.
     */
    if (superInterfaces.length < 1)
        return overloadedMethods;

    TraitType currentTraitObjectType = STypesUtil.declToTraitTypeEnhanced(currentTraitObjectDecl);
    // TraitType currentTraitObjectType = STypesUtil.declToTraitType(currentTraitObjectDecl);
    List<TraitTypeWhere> extendsClause = NodeUtil.getExtendsClause(currentTraitObjectDecl);

    OverloadingOracle oa = new OverloadingOracle(typeAnalyzer);

    /*
     * properlyInheritedMethods is supposed to return methods that are
     * (potentially) inherited by this trait.  The declaration from the
     * most specific trait declaring a given method signature should be
     * what is returned; HOWEVER, there is a bug, in that return types
     * are apparently ignored, so two methods with same domain but different
     * return types will only result in a single method.  This can cause
     * a problem in the case that a method is available from parent and
     * from great-grandparent, AND if the parent-inheritance is not first
     * position (otherwise, a default implementation appears from the
     * parent, though this might not be the correct one).
     * 
     * Note that extends clauses should be minimal by this point, or at
     * least as-if minimal; we don't want to be dealing with duplicated
     * methods that would not trigger overriding by the meet rule (if the
     * extends clause is minimal, and a method is defined twice in the
     * extends clause, then it needs to be disambiguated in this type).
     */
    if (DEBUG_OVERLOADED_METHOD_CHAINING)
        System.err.println("Considering overloads for " + currentTraitObjectType + ", extended="
                + Useful.listTranslatedInDelimiters("[", extendsClause, "]", ",", TTWtoString));

    Relation<IdOrOpOrAnonymousName, scala.Tuple3<Functional, StaticTypeReplacer, TraitType>> toConsider = STypesUtil
            .properlyInheritedMethodsNotIdenticallyCovered(currentTraitObjectType.getName(), typeAnalyzer);

    MultiMap<IdOrOpOrAnonymousName, scala.Tuple3<Functional, StaticTypeReplacer, TraitType>> toConsiderFixed = new MultiMap<IdOrOpOrAnonymousName, scala.Tuple3<Functional, StaticTypeReplacer, TraitType>>();

    for (edu.rice.cs.plt.tuple.Pair<IdOrOpOrAnonymousName, scala.Tuple3<Functional, StaticTypeReplacer, TraitType>> assoc : toConsider) {
        IdOrOpOrAnonymousName n = assoc.first();
        scala.Tuple3<Functional, StaticTypeReplacer, TraitType> tup = assoc.second();

        Functional fnl = tup._1();
        StaticTypeReplacer inst = tup._2();
        TraitType tupTrait = tup._3();

        IdOrOpOrAnonymousName nn = inst.replaceIn(n);

        toConsiderFixed.putItem(nn, tup);

    }

    if (DEBUG_OVERLOADED_METHOD_CHAINING) {
        System.err.println("properlyInheritedMethods  (orig)=" + toConsider);
        System.err.println("properlyInheritedMethods (fixed)=" + toConsiderFixed);
    }

    TraitIndex ti = (TraitIndex) typeAnalyzer.traits().typeCons(currentTraitObjectType.getName()).unwrap();

    // This is used to fix the type annotation in type_info; it lacks
    // constraints on static parameters.
    StaticTypeReplacer local_inst = new StaticTypeReplacer(ti.staticParameters(),
            STypesUtil.staticParamsToArgsEnhanced(ti.staticParameters()));

    MultiMap<IdOrOpOrAnonymousName, Functional> nameToFSets = new MultiMap<IdOrOpOrAnonymousName, Functional>();

    // Sort defined methods into map from single names to sets of defs
    for (Map.Entry<Id, FieldGetterMethod> ent : ti.getters().entrySet()) {
        nameToFSets.putItem(ent.getKey(), ent.getValue());
    }
    for (Map.Entry<Id, FieldSetterMethod> ent : ti.setters().entrySet()) {
        nameToFSets.putItem(ent.getKey(), ent.getValue());
    }
    /*
     *  There's a glitch here, with the names of functional methods,
     *  vs their names as implemented methods.  Static analyzer works with
     *  names-as-written; code generation wishes to mangle them.
     */
    for (edu.rice.cs.plt.tuple.Pair<IdOrOpOrAnonymousName, FunctionalMethod> ent : ti.functionalMethods()) {
        nameToFSets.putItem(ent.first(), ent.second());
    }
    for (edu.rice.cs.plt.tuple.Pair<IdOrOpOrAnonymousName, DeclaredMethod> ent : ti.dottedMethods()) {
        nameToFSets.putItem(ent.first(), ent.second());
    }

    /*
     * The subtype-defined methods can overlap in several ways.
     * Classified by D->R (Domain, Range), the following relationships are
     * possible:
     * 
     * EQ -> EQ means Java dispatch works. (shadowed)
     * 
     * EQ -> LT means that the name is wrong;
     *          the (Java) EQ->EQ method must be included.
     *          (EQ->EQ cannot exist in (Fortress) subtype)
     *          
     * LT -> EQ means that there is an overloading.
     *          (EQ -> LT cannot exist in (Fortress) subtype; EQ->EQ can)
     *          
     * LT -> LT means that there is an overloading.
     *          EQ -> LT or EQ -> EQ can exist in subtype;
     *          LT -> EQ can exist in super, if it does,
     *          then it is covered in a diff relationship by EQ -> LT above.
     *          
     * EX -> ... means there is an excluding overloading
     *          
     * 
     * There may also be overloadings present in
     * the methods defined by this trait or object.
     * 
     * Forwarded methods are those that are in EQ -> LT relationship
     * with some super method.
     * 
     * Overload sets contain all methods in the subtype plus all the 
     * unshadowed, unforwarded methods from super.
     * 
     * As overloads, these are similar to function overloads, except that
     * the parameters come in 1-n instead of 0-(n-1), and the invocation
     * varies -- supertype invocation dispatches to the default-methods
     * class, subtype invocation goes, where? (to the static, if subtype
     * is a trait, otherwise, we need to dance the name out of the way).
     * 
     */

    for (Map.Entry<IdOrOpOrAnonymousName, Set<Functional>> ent : nameToFSets.entrySet()) {
        IdOrOpOrAnonymousName name = ent.getKey();
        Set<Functional> funcs = ent.getValue();

        // initial set of potential overloads is this trait/object's methods
        Set<Functional> perhapsOverloaded = new HashSet<Functional>(funcs);

        for (scala.Tuple3<Functional, StaticTypeReplacer, TraitType> overridden : toConsiderFixed
                .getEmptyIfMissing(name)) {
            // toConsider.matchFirst(name)) {
            Functional super_func = overridden._1();
            StaticTypeReplacer super_inst = overridden._2();

            if (super_func instanceof ParametricOperator) {
                // TODO -- substitute and compare, I think.
                continue;
            }

            TraitType traitDeclaringMethod = overridden._3();
            if (typeAnalyzer.equiv(traitDeclaringMethod, currentTraitObjectType))
                continue;

            boolean shadowed = false; // EQ -> EQ seen
            boolean narrowed = false; // EQ -> LT seen
            Functional narrowed_func = null;

            Type raw_super_ret = oa.getRangeType(super_func);

            int super_self_index = NodeUtil.selfParameterIndex(super_func.parameters());
            Type raw_super_noself_domain = oa.getNoSelfDomainType(super_func);
            Type super_noself_domain_possibly_no_params = super_inst
                    .replaceInEverything(raw_super_noself_domain);
            List<StaticParam> better_super_params = new ArrayList<StaticParam>();

            /*
             * Combine all the static params for super, preferring the definitions from the
             * subtype when names match (those may be narrower).
             */
            for (StaticParam bsp : super_noself_domain_possibly_no_params.getInfo().getStaticParams()) {
                boolean use_bsp = true;
                for (StaticParam sp : currentTraitObjectDecl.getHeader().getStaticParams()) {
                    if (sp.getName().equals(bsp.getName())) {
                        better_super_params.add(sp);
                        use_bsp = false;
                        break;
                    }
                }
                if (use_bsp)
                    better_super_params.add(bsp);
            }
            for (StaticParam sp : currentTraitObjectDecl.getHeader().getStaticParams()) {
                boolean use_sp = true;
                for (StaticParam bsp : super_noself_domain_possibly_no_params.getInfo().getStaticParams()) {
                    if (sp.getName().equals(bsp.getName())) {
                        use_sp = false;
                        break;
                    }
                }
                if (use_sp)
                    better_super_params.add(sp);
            }

            Type super_noself_domain = STypesUtil.insertStaticParams(
                    STypesUtil.clearStaticParams(super_noself_domain_possibly_no_params), better_super_params);

            Type pre_super_ret = super_inst.replaceInEverything(raw_super_ret);

            Type super_ret = STypesUtil.insertStaticParams(STypesUtil.clearStaticParams(pre_super_ret),
                    better_super_params);
            //          super_noself_domain_possibly_no_params.getInfo().getStaticParams().isEmpty() ?
            //          STypesUtil.insertStaticParams(super_noself_domain_possibly_no_params,     // Aha!  GLS 6/12/12
            //                    currentTraitObjectDecl.getHeader().getStaticParams()) :
            //          super_noself_domain_possibly_no_params;

            for (Functional func : funcs) {
                Type ret = local_inst.replaceInEverything(oa.getRangeType(func));
                int self_index = NodeUtil.selfParameterIndex(func.parameters());
                if (self_index != super_self_index) {
                    /*
                     * Not sure we see this ever; it is a bit of a mistake,
                     * and will require further tinkering when we sort out
                     * the overloads.  We DON'T want to attempt a type
                     * comparison of dissimilar-selfed functions.
                     */
                    continue;
                }

                /*
                 * See above comment -- I think this is the wrong instantiater,
                 * but it is not far wrong.
                 */
                Type raw_noself_domain = oa.getNoSelfDomainType(func);
                Type noself_domain = local_inst.replaceInEverything(raw_noself_domain);

                // Classify potential override

                /*
                 * Funny business with "self_index" --
                 *   the overloading oracle / type analyzer believes that
                 *   subtype_SELF more specific than supertype_SELF.
                 *   
                 *   This is not what we want for purposes of spotting
                 *   shadowing and collisions.
                 *  
                 */
                if (DEBUG_OVERLOADED_METHOD_CHAINING && name.toString().contains("seq")) {
                    System.out.println("******* " + noself_domain.toStringReadable() + " { "
                            + noself_domain.getInfo().getStaticParams() + " } " + "\nvs super "
                            + super_noself_domain.toStringReadable() + " { "
                            + super_noself_domain.getInfo().getStaticParams() + " }");
                    System.out.println("** raw super is " + raw_super_noself_domain.toStringReadable() + " { "
                            + raw_super_noself_domain.getInfo().getStaticParams() + " }");

                    System.out.println(
                            "******* " + ret.toStringReadable() + " { " + ret.getInfo().getStaticParams()
                                    + " } " + "\nvs super " + super_ret.toStringReadable() + " { "
                                    + super_ret.getInfo().getStaticParams() + " }");
                    System.out.println("** raw super is " + raw_super_ret.toStringReadable() + " { "
                            + raw_super_ret.getInfo().getStaticParams() + " }");
                    // super_noself_domain_possibly_no_params
                    System.out.println("** super pnp is "
                            + super_noself_domain_possibly_no_params.toStringReadable() + " { "
                            + super_noself_domain_possibly_no_params.getInfo().getStaticParams() + " }");
                    System.out.println("** replacer is " + super_inst);
                    System.out.println("** better super params is { " + better_super_params + " }");
                    boolean d_a_le_b = oa.lteq(noself_domain, super_noself_domain);
                    boolean d_b_le_a = oa.lteq(super_noself_domain, noself_domain);
                    boolean r_a_le_b = oa.lteq(ret, super_ret);
                    boolean r_b_le_a = oa.lteq(super_ret, ret);
                    System.err.println(
                            "" + func + " ?? " + super_func + " " + d_a_le_b + d_b_le_a + r_a_le_b + r_b_le_a);
                    System.out.println("**** END");
                }
                boolean d_a_le_b = oa.lteq(noself_domain, super_noself_domain);
                boolean d_b_le_a = oa.lteq(super_noself_domain, noself_domain);

                boolean r_a_le_b = oa.lteq(ret, super_ret);
                boolean r_b_le_a = oa.lteq(super_ret, ret);

                if (DEBUG_OVERLOADED_METHOD_CHAINING) {
                    System.err.println(
                            "" + func + " ?? " + super_func + " " + d_a_le_b + d_b_le_a + r_a_le_b + r_b_le_a);
                }

                boolean schema_narrowed = false;
                if (func.staticParameters().size() > 0) {
                    int selfIndex = ((HasSelfType) super_func).selfPosition();
                    String from_name = genericMethodName(super_func, selfIndex);
                    String to_name = genericMethodName(func, selfIndex);
                    schema_narrowed = !from_name.equals(to_name);
                }

                if (d_a_le_b && d_b_le_a) {
                    // equal domains
                    if (r_a_le_b) { // sub is LE
                        if (r_b_le_a) {
                            // eq
                            // note that GENERIC methods all have same Java return type,
                            // hence "equal".
                            if (schema_narrowed) {
                                narrowed = true; // could "continue" here
                                narrowed_func = func;
                                if (DEBUG_OVERLOADED_METHOD_CHAINING)
                                    System.err.println("  " + func + " schema-narrows " + super_func);
                            } else {
                                shadowed = true; // could "continue" here
                                if (DEBUG_OVERLOADED_METHOD_CHAINING)
                                    System.err.println("  " + func + " shadows " + super_func);
                            }

                        } else {
                            // lt
                            narrowed = true;
                            narrowed_func = func;
                            if (DEBUG_OVERLOADED_METHOD_CHAINING)
                                System.err.println("  " + func + " narrows " + super_func);

                        }
                    }
                }
            }

            if (shadowed)
                continue;
            if (narrowed) {
                //          System.out.println("generateForwardingFor:");
                //          System.out.println("  super_func = " + super_func);
                //          System.out.println("  narrowed_func = " + narrowed_func);
                //          System.out.println("  super_inst = " + super_inst);
                //          System.out.println("  currentTraitObjectType = " + currentTraitObjectType);
                if (narrowed_func.staticParameters().size() > 0) {
                    if (DEBUG_OVERLOADED_METHOD_CHAINING)
                        System.err.println("Generic narrowing, " + narrowed_func + " narrows " + super_func);
                    int selfIndex = ((HasSelfType) super_func).selfPosition();
                    String from_name = genericMethodName(super_func, selfIndex);
                    String to_name = genericMethodName(narrowed_func, selfIndex);
                    String sig = genericMethodClosureFinderSig;
                    int arity = 3; // Magic number, number of parameters to generic method closure finder
                    // TODO This could be bogus, but for now, let's try it.
                    String receiverClass = NamingCzar.jvmTypeDescAsTrait(currentTraitObjectType,
                            component.getName());

                    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, from_name, sig, null, null);
                    mv.visitCode();

                    mv.visitVarInsn(ALOAD, 0);
                    mv.visitVarInsn(LLOAD, 1);
                    mv.visitVarInsn(ALOAD, 3);
                    mv.visitMethodInsn(inATrait ? INVOKEINTERFACE : INVOKEVIRTUAL, receiverClass, to_name,
                            genericMethodClosureFinderSig);

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

                } else {
                    generateForwardingFor(super_func, narrowed_func, false, super_inst, currentTraitObjectType,
                            currentTraitObjectType, true); // swapped
                }
                continue;
            }
            perhapsOverloaded.add((Functional) (((HasSelfType) super_func)
                    .instantiateTraitStaticParameters(ti.staticParameters(), super_inst))); // GLS 3/12/2012
        }

        // need to refine the overloaded methods check because of exclusion
        MultiMap<Integer, Functional> partitionedByArgCount = partitionByMethodArgCount(oa, perhapsOverloaded);

        if (partitionedByArgCount.size() > 0) {

            overloadedMethods.put(name, partitionedByArgCount);
            if (DEBUG_OVERLOADED_METHOD_CHAINING)
                System.err.println(" Method " + name + " has overloads " + perhapsOverloaded);
        }
        // TODO now emit necessary overloads, if any.

    }
    return overloadedMethods;
}

From source file:com.sun.fortress.compiler.codegen.CodeGen.java

License:Open Source License

/**
 * Generates the method that is called to find the closure for a generic method.
 * The method name is some minor frob on the Fortress method name, but it needs
 * the schema to help avoid overloading conflicts on the name.
 * /*  ww w .j a v  a2s.  c o m*/
 *  <pre>
 *  private static BAlongTree sampleLookupTable = new BAlongTree();
 *  public Object sampleLookup(long hashcode, String signature) {
 *  Object o = sampleLookupTable.get(hashcode);
 *  if (o == null) 
 *     o = findGenericMethodClosure(hashcode,
 *                                  sampleLookupTable,
 *                                  "template_class_name",
 *                                  signature);
 *  return o;
 *  }
 *  </pre>
 * @param method_name - may be mangled to avoid a name clash
 * @param table_name - always the unmangled version of the method_name
 * @param template_class_name
 * @param savedInATrait 
 */
public void generateGenericMethodClosureFinder(String method_name, final String table_name,
        String template_class_name, final String class_file, boolean savedInATrait) {

    initializedStaticFields_TO.add(new InitializedStaticField() {

        @Override
        public void forClinit(MethodVisitor my_mv) {
            my_mv.visitTypeInsn(NEW, Naming.CACHE_TABLE_TYPE);
            my_mv.visitInsn(DUP);
            my_mv.visitMethodInsn(INVOKESPECIAL, Naming.CACHE_TABLE_TYPE, "<init>", "()V");
            my_mv.visitFieldInsn(PUTSTATIC, class_file, table_name,
                    Naming.internalToDesc(Naming.CACHE_TABLE_TYPE));
        }

        @Override
        public String asmName() {
            return table_name;
        }

        @Override
        public String asmSignature() {
            return Naming.internalToDesc(Naming.CACHE_TABLE_TYPE);
        }

    });

    int hashOff = savedInATrait ? 0 : 1;
    int stringOff = hashOff + 2;
    int tmpOff = stringOff + 1;

    int access = savedInATrait ? ACC_PUBLIC + ACC_STATIC : ACC_PUBLIC;
    if (savedInATrait)
        method_name = method_name + Naming.GENERIC_METHOD_FINDER_SUFFIX_IN_TRAIT;

    List<StaticParam> to_sparams = this.currentTraitObjectDecl.getHeader().getStaticParams();

    CodeGenMethodVisitor mv = cw.visitCGMethod(access, method_name, genericMethodClosureFinderSig, null, null);
    mv.visitCode();
    Label l0 = new Label();
    mv.visitLabel(l0);
    //mv.visitLineNumber(1331, l0);
    mv.visitFieldInsn(GETSTATIC, class_file, table_name, Naming.internalToDesc(Naming.CACHE_TABLE_TYPE));
    mv.visitVarInsn(LLOAD, hashOff);
    mv.visitMethodInsn(INVOKEVIRTUAL, Naming.CACHE_TABLE_TYPE, "get", "(J)Ljava/lang/Object;");
    mv.visitVarInsn(ASTORE, tmpOff);
    Label l1 = new Label();
    mv.visitLabel(l1);
    //mv.visitLineNumber(1332, l1);
    mv.visitVarInsn(ALOAD, tmpOff);
    Label l2 = new Label();
    mv.visitJumpInsn(IFNONNULL, l2);
    Label l3 = new Label();
    mv.visitLabel(l3);
    //mv.visitLineNumber(1333, l3);
    mv.visitVarInsn(LLOAD, hashOff);
    mv.visitFieldInsn(GETSTATIC, class_file, table_name, Naming.internalToDesc(Naming.CACHE_TABLE_TYPE));
    mv.visitLdcInsn(template_class_name);
    mv.visitVarInsn(ALOAD, stringOff);
    // if in a generic trait/object, need to call different method and include one more parameter.
    if (to_sparams.size() == 0) {
        mv.visitMethodInsn(INVOKESTATIC, Naming.RT_HELPERS, "findGenericMethodClosure",
                "(JLcom/sun/fortress/runtimeSystem/BAlongTree;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
    } else {
        // Need to use the substitute-at-load string operation.
        String string_sargs = NamingCzar.genericDecoration(null, to_sparams, null, thisApi());
        String loadString = Naming.opForString(Naming.stringMethod, string_sargs);
        mv.visitMethodInsn(INVOKESTATIC, Naming.magicInterpClass, loadString, "()Ljava/lang/String;");
        mv.visitMethodInsn(INVOKESTATIC, Naming.RT_HELPERS, "findGenericMethodClosure",
                "(JLcom/sun/fortress/runtimeSystem/BAlongTree;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
    }
    mv.visitVarInsn(ASTORE, tmpOff);
    mv.visitLabel(l2);
    //mv.visitLineNumber(1335, l2);
    mv.visitFrame(F_APPEND, 1, new Object[] { "java/lang/Object" }, 0, null);
    mv.visitVarInsn(ALOAD, tmpOff);
    mv.visitInsn(ARETURN);
    Label l4 = new Label();
    mv.visitLabel(l4);

    if (!savedInATrait)
        mv.visitLocalVariable("this", Naming.internalToDesc(class_file), null, l0, l4, 0);

    mv.visitLocalVariable("hashcode", "J", null, l0, l4, hashOff);
    mv.visitLocalVariable("signature", "Ljava/lang/String;", null, l0, l4, stringOff);
    mv.visitLocalVariable("o", "Ljava/lang/Object;", null, l1, l4, tmpOff);
    // 6,6 if in a generic trait.
    //        mv.visitMaxs(5, 5);
    mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
    mv.visitEnd();
}

From source file:com.sun.fortress.compiler.codegen.CodeGen.java

License:Open Source License

/**
 * Newspeak for forwarding; the old forwarding method code is too atrocious for words.
 * //from  w  ww. j ava 2 s. c om
 * @param cw
 * @param generated_method_name
 * @param generated_method_sig
 * @param invoked_method_trait_object
 * @param invoked_method_name
 * @param self_index
 * @param n_params_including_self
 * @param is_a_trait
 */
static void functionalForwardingMethod(ClassWriter cw, String generated_method_name,
        String generated_method_sig, String invoked_method_trait_object, String invoked_method_name,
        int self_index, int n_params_including_self, boolean is_a_trait) {
    String invoked_method_sig = Naming.removeNthSigParameter(generated_method_sig, self_index);
    String self_sig = Naming.nthSigParameter(generated_method_sig, self_index);
    self_sig.substring(1, self_sig.length() - 1); // Strip off L;

    String ret_type = Naming.sigRet(invoked_method_sig);

    MethodVisitor mv = cw.visitMethod(ACC_STATIC + ACC_PUBLIC, generated_method_name, generated_method_sig,
            null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, self_index);
    // If the self_sig does not match the type that we are about to invoke,
    // cast it.
    if (!self_sig.equals(invoked_method_trait_object)) {
        InstantiatingClassloader.generalizedCastTo(mv, invoked_method_trait_object);
    }
    // push parameters, except for self
    for (int i = 0; i < n_params_including_self; i++)
        if (i != self_index) {
            mv.visitVarInsn(ALOAD, i);
        }

    // invoke
    mv.visitMethodInsn(is_a_trait ? INVOKEINTERFACE : INVOKEVIRTUAL, invoked_method_trait_object,
            invoked_method_name, invoked_method_sig);

    // This will need to generalize for covariant types, I expect
    if (ret_type.startsWith(Naming.TUPLE_OX) || ret_type.startsWith(Naming.ARROW_OX)) {
        InstantiatingClassloader.generalizedCastTo(mv, ret_type);
    }
    mv.visitInsn(ARETURN);

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

}

From source file:com.sun.fortress.compiler.codegen.CodeGen.java

License:Open Source License

public void forObjectDeclPrePass(ObjectDecl x) {
    debug("Begin forObjectDeclPrePass for ", x);
    TraitTypeHeader header = x.getHeader();
    List<TraitTypeWhere> extendsC = header.getExtendsClause();

    boolean canCompile =
            // x.getParams().isNone() &&             // no parameters
            // header.getStaticParams().isEmpty() && // no static parameter
            header.getWhereClause().isNone() && // no where clause
                    header.getThrowsClause().isNone() && // no throws clause
                    header.getContract().isNone() && // no contract
                    //            header.getDecls().isEmpty() &&        // no members
                    Modifiers.ObjectMod.containsAll(header.getMods())
    // ( extendsC.size() <= 1 ); // 0 or 1 super trait
    ;/*from  ww  w  . jav a2  s .co  m*/

    if (!canCompile)
        throw sayWhat(x);

    // Map<String, String> xlation = new HashMap<String, String>();
    List<String> splist = new ArrayList<String>();
    final List<StaticParam> original_static_params = header.getStaticParams();
    Option<List<Param>> original_params = NodeUtil.getParams(x);

    Naming.XlationData xldata = xlationData(Naming.OBJECT_GENERIC_TAG);

    boolean savedInAnObject = inAnObject;
    inAnObject = true;
    Id classId = NodeUtil.getName(x);

    final ClassNameBundle cnb = new_ClassNameBundle(classId, original_static_params, xldata);

    String erasedSuperI = (EMIT_ERASED_GENERICS && cnb.isGeneric) ? cnb.stemClassName : "";
    String[] superInterfaces = NamingCzar.extendsClauseToInterfaces(extendsC, component.getName(),
            erasedSuperI);

    if (EMIT_ERASED_GENERICS && cnb.isGeneric) {
        emitErasedClassFor(cnb, (TraitObjectDecl) x);
    }

    String abstractSuperclass;
    if (superInterfaces.length > 0) {
        abstractSuperclass = superInterfaces[0] + NamingCzar.springBoard;
    } else {
        abstractSuperclass = NamingCzar.internalObject;
    }

    traitOrObjectName = cnb.className;
    debug("forObjectDeclPrePass ", x, " classFile = ", traitOrObjectName);

    boolean isSingletonObject = NodeUtil.getParams(x).isNone();
    List<Param> params;
    if (!isSingletonObject) {
        params = NodeUtil.getParams(x).unwrap(); //TUPLE CONSTRUCTOR PROBLEM
        String init_sig = NamingCzar.jvmSignatureFor(params, "V", thisApi());

        // Generate the factory method
        String sig = NamingCzar.jvmSignatureFor(params, cnb.classDesc, thisApi());

        String mname;

        CodeGen cg = this;
        String PCN = null;
        String PCNOuter = null;

        ArrayList<InitializedStaticField> isf_list = new ArrayList<InitializedStaticField>();

        if (cnb.isGeneric) {
            ArrowType at = FnNameInfo.typeAndParamsToArrow(NodeUtil.getSpan(x),
                    NodeFactory.makeTraitType(classId, STypesUtil.staticParamsToArgs(original_static_params)),
                    original_params.unwrap());
            String generic_arrow_type = NamingCzar.jvmTypeDesc(at, thisApi(), false);

            PCNforClosure pair = nonCollidingClosureName(generic_arrow_type, Naming.NO_SELF,
                    (IdOrOp) x.getHeader().getName(), original_static_params, this.packageAndClassName);

            PCN = pair.PCN;
            PCNOuter = pair.PCNOuter;
            xldata = pair.xldata;

            cg = new CodeGen(this);
            cg.cw = new CodeGenClassWriter(ClassWriter.COMPUTE_FRAMES, cw);

            // This creates the closure bits
            // The name is disambiguated by the class in which it appears.
            mname = InstantiatingClassloader.closureClassPrefix(PCN, cg.cw, PCN, sig, null, isf_list);
        } else {
            mname = nonCollidingSingleName(x.getHeader().getName(), sig, "");
        }

        CodeGenClassWriter cw = cg.cw;
        CodeGenMethodVisitor mv = cw.visitCGMethod(ACC_STATIC + ACC_PUBLIC, mname, sig, null, null);

        mv.visitTypeInsn(NEW, cnb.className);
        mv.visitInsn(DUP);

        // iterate, pushing parameters, beginning at zero.
        // TODO actually handle N>0 parameters.

        int numParams = params.size();
        //if only a single parameter which is a tuple, signature will give them individually
        if (numParams == 1 && (params.get(0).getIdType().unwrap() instanceof TupleType)) {
            Param p0 = params.get(0);
            TupleType tuple_type = ((TupleType) p0.getIdType().unwrap());
            List<Type> tuple_types = tuple_type.getElements();
            numParams = tuple_types.size();
        }
        for (int stack_offset = 0; stack_offset < numParams; stack_offset++) {
            // when we unbox, this will be type-dependent
            mv.visitVarInsn(ALOAD, stack_offset);
        }

        mv.visitMethodInsn(INVOKESPECIAL, cnb.className, "<init>", init_sig);
        mv.visitInsn(ARETURN);
        mv.visitMaxs(Naming.ignoredMaxsParameter, Naming.ignoredMaxsParameter);
        mv.visitEnd();

        if (cnb.isGeneric) {
            InstantiatingClassloader.optionalStaticsAndClassInitForTO(isf_list, cg.cw);

            cg.cw.dumpClass(PCNOuter, xldata);
        }

    } else { // singleton
        params = Collections.<Param>emptyList();
    }

    CodeGenClassWriter prev = cw;

    /* Yuck, ought to allocate a new codegen here. */

    initializedStaticFields_TO = new ArrayList<InitializedStaticField>();

    cw = new CodeGenClassWriter(ClassWriter.COMPUTE_FRAMES, cw);
    cw.visitSource(NodeUtil.getSpan(x).begin.getFileName(), null);

    // Until we resolve the directory hierarchy problem.
    //            cw.visit( V1_5, ACC_PUBLIC + ACC_SUPER+ ACC_FINAL,
    //                      classFile, null, NamingCzar.internalObject, new String[] { parent });
    cw.visit(InstantiatingClassloader.JVM_BYTECODE_VERSION, ACC_PUBLIC + ACC_SUPER + ACC_FINAL, cnb.className,
            null, abstractSuperclass, superInterfaces);

    if (isSingletonObject) {

        initializedStaticFields_TO.add(new InitializedStaticField() {

            @Override
            public void forClinit(MethodVisitor imv) {
                imv.visitTypeInsn(NEW, cnb.className);
                imv.visitInsn(DUP);
                imv.visitMethodInsn(INVOKESPECIAL, cnb.className, "<init>", Naming.voidToVoid);
                imv.visitFieldInsn(PUTSTATIC, cnb.className, NamingCzar.SINGLETON_FIELD_NAME, cnb.classDesc);
            }

            @Override
            public String asmName() {
                return NamingCzar.SINGLETON_FIELD_NAME;
            }

            @Override
            public String asmSignature() {
                return cnb.classDesc;
            }

        });

        /* Used to pass splist to the static-parametered form
         * but it was always empty.  Tests work like that.
         * Bit of a WTF, keep an eye on this.
         * Repurpose splist (non-null) for the computation and
         * caching of RTTI, which also goes in a static.
         */
        addStaticVar(new VarCodeGen.StaticBinding(classId, NodeFactory.makeTraitType(classId),
                cnb.stemClassName, NamingCzar.SINGLETON_FIELD_NAME, cnb.classDesc));

        //            // Singleton; generate field in class to hold sole instance.
        //            cw.visitField(ACC_PUBLIC + ACC_STATIC + ACC_FINAL,
        //                          NamingCzar.SINGLETON_FIELD_NAME, cnb.classDesc,
        //                          null /* for non-generic */, null /* instance has no value */);
    }

    currentTraitObjectDecl = x;
    //create CodeGen for init method
    // has different set of parameter variables in scope
    CodeGen initCodeGen = initializeInitMethod(params);

    initCodeGen.initializedInstanceFields_O = new ArrayList<InitializedInstanceField>();
    //        List<Binding> fieldsForEnv = new ArrayList<Binding>();
    initCodeGen.instanceFields = new InstanceFields();

    BATree<String, VarCodeGen> savedLexEnv = lexEnv.copy();

    // for each parameter
    // 1) add field to the class
    // 2) add field along with initializer to list of instance fields to put in the constructor
    // 3) add parameter to local scope of init method
    // 4) add field to scope for use in methods
    for (int i = 0; i < params.size(); i++) {
        Param p = params.get(i);

        String paramName = p.getName().getText();
        Type paramType = (Type) p.getIdType().unwrap();
        String typeDesc = NamingCzar.jvmBoxedTypeDesc(paramType, thisApi());
        Id id = NodeFactory.makeId(NodeUtil.getSpan(p.getName()), paramName);
        VarCodeGen vcg = new VarCodeGen.FieldVar(id, paramType, cnb.className, paramName, typeDesc);

        //1) add field to class
        cw.visitField(ACC_PUBLIC + ACC_FINAL, paramName, typeDesc, null /* for non-generic */,
                null /* instance has no value */);

        //2) add field with initializer as a refernce to the parameter
        initCodeGen.instanceFields.put(vcg, ExprFactory.makeVarRef(id));

        //3) add param to scope for init method only
        initCodeGen.addStaticVar(new VarCodeGen.ParamVar(id, paramType, initCodeGen));

        //4) add field to scope for method codegen
        addStaticVar(vcg);
    }

    // find declared fields in the list of decls and
    // 1) add field to the class
    // 2) add field along with initializer to list of instance fields to put in the constructor
    // 3) add field to scope for use in methods
    for (Decl d : header.getDecls()) {
        if (d instanceof VarDecl) {
            // TODO need to spot for "final" fields.  Right now we assume mutable, not final.
            final VarDecl vd = (VarDecl) d;
            final CodeGen cg = this;
            int numDecls = vd.getLhs().size();
            for (int i = 0; i < numDecls; i++) {
                LValue l = vd.getLhs().get(i);
                String fieldName = l.getName().getText();
                Type fieldType = (Type) l.getIdType().unwrap();
                String typeDesc = NamingCzar.jvmBoxedTypeDesc(fieldType, thisApi());
                Id id = NodeFactory.makeId(NodeUtil.getSpan(l.getName()), fieldName);
                VarCodeGen fieldVcg = new VarCodeGen.MutableFieldVar(id, fieldType, cnb.className, fieldName,
                        typeDesc);

                //1) add field to class
                cw.visitField(ACC_PUBLIC, fieldName, typeDesc, null /* for non-generic */,
                        null /* instance has no value */);

                //2) set up initializer
                if (vd.getInit().isNone())
                    sayWhat(vd, "no initializer for declared field(s)");
                Expr init = vd.getInit().unwrap();

                if (numDecls != 1 && init instanceof TupleExpr) {
                    List<Expr> tupleExprs = ((TupleExpr) init).getExprs();
                    if (tupleExprs.size() != numDecls)
                        sayWhat(vd, "incorrect initialization for declared fields tuple");
                    init = tupleExprs.get(i);
                }
                initCodeGen.instanceFields.put(fieldVcg, init);

                //3) add field to scope for method codegen
                addStaticVar(fieldVcg);
            }
        }
    }

    debug("Dump overloaded method chaining for ", x);
    Map<IdOrOpOrAnonymousName, MultiMap<Integer, Functional>> overloads = dumpOverloadedMethodChaining(
            superInterfaces, false);
    if (OVERLOADED_METHODS)
        typeLevelOverloadedNamesAndSigs = generateTopLevelOverloads(thisApi(), overloads, typeAnalyzer, cw,
                this, new OverloadSet.TraitOrObjectFactory(Opcodes.INVOKEVIRTUAL, cnb, this));
    debug("End of dump overloaded method chaining for ", x);

    debug("Process declarations for ", x);
    for (Decl d : header.getDecls()) {
        // This does not work yet.
        d.accept(this);
    }
    debug("End of processing declarations for ", x);

    initCodeGen.instanceInitForObject(abstractSuperclass);

    debug("Dump method chaining for ", x);
    dumpMethodChaining(superInterfaces, false);
    // dumpErasedMethodChaining(superInterfaces, false);
    debug("End of dump method chaining for ", x);

    /* RTTI stuff */
    mv = cw.visitCGMethod(Opcodes.ACC_PUBLIC, // acccess
            Naming.RTTI_GETTER, // name
            Naming.STATIC_PARAMETER_GETTER_SIG, // sig
            null, // generics sig?
            null); // exceptions
    mv.visitCode();
    mv.visitFieldInsn(GETSTATIC, cnb.className, Naming.RTTI_FIELD, Naming.RTTI_CONTAINER_DESC);

    areturnEpilogue();

    emitRttiField(cnb);
    /* end RTTI stuff */

    lexEnv = savedLexEnv;

    optionalStaticsAndClassInitForTO(classId, cnb, isSingletonObject);

    if (cnb.isGeneric) {
        cw.dumpClass(cnb.fileName, xldata.setTraitObjectTag(Naming.OBJECT_GENERIC_TAG));
    } else {
        cw.dumpClass(cnb.className);
    }
    cw = prev;
    initializedInstanceFields_O = null;
    initializedStaticFields_TO = null;
    currentTraitObjectDecl = null;

    traitOrObjectName = null;

    inAnObject = savedInAnObject;

    // Needed (above) to embed a reference to the Rtti information for this type.
    RttiClassAndInterface(x, cnb, xldata);
    debug("End forObjectDeclPrePass for ", x);
}

From source file:com.sun.fortress.compiler.environments.TopLevelEnvGen.java

License:Open Source License

/**
 * Generate the default constructor for this class.
 * This constructors calls the method setToplevel().
 * If this environment is not a top-level environment, then a default
 * constructor does not need to be created.  (ASM will generate a
 * default constructor)./*from  w w  w.  j  a  v  a 2s  . co  m*/
 */
private static void writeMethodInit(ClassWriter cw, String className) {
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
    mv.visitCode();
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getType(BaseEnv.class).getInternalName(), "<init>", "()V");
    mv.visitVarInsn(Opcodes.ALOAD, 0);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, "setTopLevel", "()V");
    mv.visitInsn(Opcodes.RETURN);
    // See comment above on ClassWriter.COMPUTE_FRAMES
    mv.visitMaxs(1, 1);
    mv.visitEnd();
}

From source file:com.sun.fortress.compiler.environments.TopLevelEnvGen.java

License:Open Source License

/**
 * Implementing "static reflection" for the method getFooRaw so the
 * interpreter uses a switch instruction for ***GetRaw
 * based on the hash values of String names in this namespace.
 *///  w  w w.j  av a  2s . c om
private static void writeMethodGetRaw(ClassWriter cw, String className, String methodName,
        EnvironmentClass environmentClass, EnvSymbolNames symbolNames) {
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, methodName,
            "(Ljava/lang/String;)" + environmentClass.descriptor(), null, null);
    mv.visitCode();

    Label beginFunction = new Label();
    mv.visitLabel(beginFunction);

    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "hashCode", "()I");
    mv.visitVarInsn(Opcodes.ISTORE, 2);
    Label beginLoop = new Label();
    mv.visitLabel(beginLoop);

    Relation<String, Integer> hashCodeRelation = symbolNames.makeHashCodeRelation(environmentClass);
    ArrayList<Integer> sortedCodes = new ArrayList<Integer>(hashCodeRelation.secondSet());
    Collections.sort(sortedCodes);
    Label returnNull = new Label();

    getRawHelper(mv, className, hashCodeRelation, environmentClass, sortedCodes, returnNull);

    mv.visitLabel(returnNull);
    mv.visitInsn(Opcodes.ACONST_NULL);
    mv.visitInsn(Opcodes.ARETURN);

    Label endFunction = new Label();
    mv.visitLabel(endFunction);
    mv.visitLocalVariable("this", Naming.internalToDesc(className), null, beginFunction, endFunction, 0);
    mv.visitLocalVariable("queryString", "Ljava/lang/String;", null, beginFunction, endFunction, 1);
    mv.visitLocalVariable("queryHashCode", "I", null, beginLoop, endFunction, 2);
    // See comment above on ClassWriter.COMPUTE_FRAMES
    mv.visitMaxs(2, 3);
    mv.visitEnd();
}

From source file:com.sun.fortress.compiler.environments.TopLevelEnvGen.java

License:Open Source License

private static void getRawBaseCase(MethodVisitor mv, String className,
        Relation<String, Integer> hashCodeRelation, EnvironmentClass environmentClass, int code,
        Label returnNull) {//from w  w w.j ava2 s .c o  m

    PredicateSet<String> strings = hashCodeRelation.matchSecond(code);
    for (String testString : strings) {
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitLdcInsn(testString);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
        Label afterReturn = new Label();
        mv.visitJumpInsn(Opcodes.IFEQ, afterReturn);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        String idString = testString + environmentClass.namespace();
        mv.visitFieldInsn(Opcodes.GETFIELD, className, Naming.mangleIdentifier(idString),
                environmentClass.descriptor());
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitLabel(afterReturn);
    }
    mv.visitJumpInsn(Opcodes.GOTO, returnNull);
}

From source file:com.sun.fortress.compiler.environments.TopLevelEnvGen.java

License:Open Source License

/**
 * Implementing "static reflection" for the method putRaw so the
 * interpreter uses a switch instruction for ***PutRaw
 * based on the hash values of String names in this namespace.
 *//*www .j a  va2  s.  c  o m*/
private static void writeMethodPutRaw(ClassWriter cw, String className, String methodName,
        EnvironmentClass environmentClass, EnvSymbolNames symbolNames) {
    MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, methodName,
            "(" + STRING_DESCRIPTOR + environmentClass.descriptor() + ")V", null, null);
    mv.visitCode();

    Label beginFunction = new Label();
    mv.visitLabel(beginFunction);
    mv.visitVarInsn(Opcodes.ALOAD, 1);
    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, STRING_INTERNALNAME, "hashCode", "()I");
    mv.visitVarInsn(Opcodes.ISTORE, 3);
    Label beginLoop = new Label();
    mv.visitLabel(beginLoop);

    Relation<String, Integer> hashCodeRelation = symbolNames.makeHashCodeRelation(environmentClass);
    ArrayList<Integer> sortedCodes = new ArrayList<Integer>(hashCodeRelation.secondSet());
    Collections.sort(sortedCodes);
    Label notFound = new Label();
    putRawHelper(mv, className, environmentClass, hashCodeRelation, sortedCodes, notFound);
    mv.visitLabel(notFound);
    mv.visitInsn(Opcodes.RETURN);
    Label endFunction = new Label();
    mv.visitLabel(endFunction);
    mv.visitLocalVariable("this", Naming.internalToDesc(className), null, beginFunction, endFunction, 0);
    mv.visitLocalVariable("queryString", STRING_DESCRIPTOR, null, beginFunction, endFunction, 1);
    mv.visitLocalVariable("value", environmentClass.descriptor(), null, beginFunction, endFunction, 2);
    mv.visitLocalVariable("queryHashCode", "I", null, beginLoop, endFunction, 3);
    // See comment above on ClassWriter.COMPUTE_FRAMES
    mv.visitMaxs(2, 4);
    mv.visitEnd();
}