List of usage examples for org.objectweb.asm MethodVisitor visitMethodInsn
@Deprecated public void visitMethodInsn(final int opcode, final String owner, final String name, final String descriptor)
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(); }