Show
Ignore:
Timestamp:
10/23/09 14:40:53 (5 weeks ago)
Author:
jmaessen
Message:

[codegen] Refactored forwarding method generation into
InstantiatingClassloader so that we don't have 3 (and soon more)
copies of basically the same code. That said, the code is a wee bit
fiddly.

Location:
trunk/ProjectFortress/src/com/sun/fortress
Files:
4 modified

Legend:

Unmodified
Added
Removed
  • trunk/ProjectFortress/src/com/sun/fortress/compiler/codegen/CodeGen.java

    r4254 r4283  
    629629 
    630630    private void generateGenericMethodClass(FnDecl x, IdOrOp name, 
    631                                              
    632631                                            int selfIndex) { 
    633632        /* 
     
    756755         */ 
    757756 
    758         modifiers = Opcodes.ACC_PUBLIC; 
    759  
    760         cg = new CodeGen(this); 
    761  
    762         String osig = sig; 
    763  
    764         String selfSig =  Naming.nthSigParameter(osig,0); 
    765         selfSig = Useful.substring(selfSig, 1, -1); 
    766         // Get rid of explicit self parameter. 
    767         sig = Naming.removeNthSigParameter(sig, 0); 
    768  
    769         // TODO different collision rules for top-level and for 
    770         // methods. 
    771         // SAME MNAME 
    772  
    773         // trait default OR top level. 
    774  
    775         cg.mv = cw.visitCGMethod(modifiers, mname, sig, null, null); 
    776         cg.mv.visitCode(); 
    777  
    778         // We received "self" in parameter 0 
    779         cg.mv.visitVarInsn(ALOAD, 0); 
    780         // Need to downcast, maybe. this may only matter for weird primitive types. 
    781         cg.mv.visitTypeInsn(Opcodes.CHECKCAST, selfSig);//NamingCzar.jvmTypeDesc(ty, ifNone, false)); 
    782  
    783         for (int i = 0; i < params.size(); i++) { 
    784             // 0 1 2 
    785             // a self b 
    786             // self a b 
    787             if (i < selfIndex) { 
    788                 cg.mv.visitVarInsn(ALOAD, i+1); 
    789             } else if (i > selfIndex) { 
    790                 cg.mv.visitVarInsn(ALOAD, i); 
    791             } 
    792  
    793         } 
    794         cg.mv.visitMethodInsn(INVOKESTATIC, 
    795                               springBoardClass, 
    796                               mname, 
    797                               osig); 
    798  
    799  
    800         methodReturnAndFinish(cg); 
     757        // Dotted method; downcast self and 
     758        // forward to static method in springboard class 
     759        // with explicit self parameter. 
     760        InstantiatingClassloader.forwardingMethod(cw, mname, ACC_PUBLIC, 0, 
     761                                                  springBoardClass, mname, INVOKESTATIC, 
     762                                                  sig, params.size(), true); 
    801763    } 
    802764 
     
    878840 
    879841        body.accept(this); 
    880         exitMethodScope(selfIndex, this, selfVar, paramsGen); 
     842        exitMethodScope(selfIndex, selfVar, paramsGen); 
    881843    } 
    882844 
     
    11931155     * @param paramsGen 
    11941156     */ 
    1195     private void exitMethodScope(int selfIndex, CodeGen cg, VarCodeGen selfVar, 
    1196             List<VarCodeGen> paramsGen) { 
     1157    private void exitMethodScope(int selfIndex, VarCodeGen selfVar, List<VarCodeGen> paramsGen) { 
    11971158        for (int i = paramsGen.size() - 1; i >= 0; i--) { 
    11981159            if (i != selfIndex) { 
    11991160                VarCodeGen v = paramsGen.get(i); 
    1200                 v.outOfScope(cg.mv); 
     1161                v.outOfScope(mv); 
    12011162            } 
    12021163        } 
    12031164        if (selfVar != null) 
    1204             selfVar.outOfScope(cg.mv); 
    1205  
    1206         methodReturnAndFinish(cg); 
     1165            selfVar.outOfScope(mv); 
     1166 
     1167        methodReturnAndFinish(); 
    12071168    } 
    12081169 
     
    12201181                                         com.sun.fortress.nodes.Type returnType, 
    12211182                                         boolean savedInATrait) { 
    1222         int modifiers = Opcodes.ACC_PUBLIC; 
    1223  
    1224         CodeGen cg = new CodeGen(this); 
    1225         // Just a wrapper around the body itself 
    1226         modifiers |= Opcodes.ACC_STATIC; 
     1183        int modifiers = Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC; 
    12271184        String sig = 
    12281185            NamingCzar.jvmSignatureFor(NodeUtil.getParamType(x), returnType, 
    12291186                                       component.getName()); 
    12301187 
    1231         String dottedSig = Naming.removeNthSigParameter(sig, selfIndex); 
    1232  
    12331188        // TODO different collision rules for top-level and for methods. 
    12341189        String mname = nonCollidingSingleName(name, sig); 
    12351190        String dottedName = fmDottedName(singleName(name), selfIndex); 
    12361191 
    1237         cg.mv = cw.visitCGMethod(modifiers, mname, sig, null, null); 
    1238         cg.mv.visitCode(); 
    1239  
    1240         // Now inside method body. Generate code for the method body. 
    1241         // Start by binding the parameters and setting up the initial 
    1242         // locals. 
    1243         VarCodeGen selfVar = null; 
    1244         List<VarCodeGen> paramsGen = 
    1245             new ArrayList<VarCodeGen>(params.size()); 
    1246  
    1247         // Invoke the dotted method, thank you very much. 
    1248         // ----------- 
    1249  
    1250         // TODO will have to get smarter with unboxing 
    1251         cg.mv.visitVarInsn(ALOAD, selfIndex); 
    1252         for (int i = 0; i < params.size(); i++) { 
    1253             if (i != selfIndex) 
    1254                 cg.mv.visitVarInsn(ALOAD, i); 
    1255  
    1256         } 
    1257         cg.mv.visitMethodInsn(savedInATrait ? INVOKEINTERFACE 
    1258                 : INVOKEVIRTUAL, traitOrObjectName, dottedName, 
    1259                 dottedSig); 
    1260  
    1261         // ----------- 
    1262         // Method body is complete except for returning final result if any. 
    1263         // TODO: Fancy footwork here later on if we need to return a 
    1264         // non-pointer; for now every fortress functional returns a single 
    1265         // pointer result. 
    1266         methodReturnAndFinish(cg); 
    1267         // Method body complete, cg now invalid. 
     1192        int invocation = savedInATrait ? INVOKEINTERFACE : INVOKEVIRTUAL; 
     1193 
     1194        InstantiatingClassloader.forwardingMethod(cw, 
     1195                         mname, modifiers, selfIndex, 
     1196                         traitOrObjectName, dottedName, invocation, 
     1197                         sig, params.size(), true); 
     1198 
    12681199    } 
    12691200 
     
    12711202     * @param cg 
    12721203     */ 
    1273     private void methodReturnAndFinish(CodeGen cg) { 
    1274         cg.mv.visitInsn(Opcodes.ARETURN); 
    1275         cg.mv.visitMaxs(NamingCzar.ignore, NamingCzar.ignore); 
    1276         cg.mv.visitEnd(); 
     1204    private void methodReturnAndFinish() { 
     1205        mv.visitInsn(Opcodes.ARETURN); 
     1206        mv.visitMaxs(NamingCzar.ignore, NamingCzar.ignore); 
     1207        mv.visitEnd(); 
    12771208    } 
    12781209 
     
    13401271        body.accept(cg); 
    13411272 
    1342         methodReturnAndFinish(cg); 
     1273        cg.methodReturnAndFinish(); 
    13431274        cg.dumpClass(className); 
    13441275 
  • trunk/ProjectFortress/src/com/sun/fortress/compiler/codegen/ManglingMethodVisitor.java

    r4252 r4283  
    3131 
    3232public class ManglingMethodVisitor extends MethodAdapter { 
    33    
     33 
    3434 
    3535    public ManglingMethodVisitor(MethodVisitor mvisitor) { 
    3636        super(mvisitor); 
    37       
     37 
    3838    } 
    3939 
     
    4646    public void visitFieldInsn(int opcode, String owner, String name, 
    4747            String desc) { 
    48          
     48 
    4949        owner = Naming.mangleFortressIdentifier(owner); 
    5050        name = Naming.mangleMemberName(name); 
     
    5757    public void visitLocalVariable(String name, String desc, String signature, 
    5858            Label start, Label end, int index) { 
    59          
     59 
    6060        signature = Naming.mangleFortressIdentifier(signature); 
    6161        name = Naming.mangleMemberName(name); 
  • trunk/ProjectFortress/src/com/sun/fortress/compiler/nativeInterface/FortressMethodAdapter.java

    r4153 r4283  
    162162        SignatureParser sp = new SignatureParser(desc); 
    163163        String fsig = sp.getFortressifiedSignature(); 
     164 
     165        // FORWARDING METHOD, only with type conversions on the way in/out! 
    164166        MethodVisitor mv = cv.visitMethod(access, name, fsig, signature, 
    165167                exceptions); 
  • trunk/ProjectFortress/src/com/sun/fortress/runtimeSystem/InstantiatingClassloader.java

    r4272 r4283  
    354354 
    355355            if (LOG_LOADS) System.err.println(name + ".apply" + sig + " concrete\nparams = " + parameters); 
    356             mv = cw.visitMethod(ACC_PUBLIC, Naming.APPLY_METHOD, sig, null, null); 
    357             mv.visitCode(); 
    358             // Is this right?  What about a 2-arg function that takes a void as its second arg? 
    359             // This can happen with generic instantiations of various sorts (esp the default 
    360             // seq implementation!). 
    361             for (int i = 1; i < parameters.size();i++) { 
    362                 String param = parameters.get(i-1); 
    363                 if (! param.equals(Naming.INTERNAL_SNOWMAN)) 
    364                     mv.visitVarInsn(ALOAD, i); 
    365  
     356 
     357            int sz = parameters.size(); 
     358            // Last parameter is actually result type! 
     359            // But we need to include an extra arg in sz to represent the closure itself (this). 
     360            if (sz==2 && Naming.INTERNAL_SNOWMAN.equals(parameters.get(0))) { 
     361                // Arity 1 (sz 2) with void parameter should actually be arity 0 (sz 1). 
     362                sz = 1; 
    366363            } 
    367             mv.visitMethodInsn(INVOKESTATIC, staticClass, fn, sig); 
    368             // ARETURN if not void... 
    369             mv.visitInsn(ARETURN); 
    370  
    371             mv.visitMaxs(2, 3); 
    372             mv.visitEnd(); 
    373         } 
     364 
     365            forwardingMethod(cw, Naming.APPLY_METHOD, ACC_PUBLIC, 0, 
     366                             staticClass, fn, INVOKESTATIC, 
     367                             sig, sz, false); 
     368        } 
     369    } 
     370 
     371    /** Create forwarding method that re-pushes its arguments and 
     372     * chains to another method in another class. 
     373     * When selfIndex == -1, all arguments are pushed exactly in the order given, 
     374     * and the input and output signatures are assumed to be the same (so this can 
     375     * also be used to pass along a self parameter without mucking about). 
     376     * Otherwise selfIndex indicates the index of a self parameter; when pushSelf 
     377     * is true this index is pushed first. 
     378     * 
     379     * How do we determine incoming and outgoing signatures? 
     380     */ 
     381    public static void forwardingMethod(ClassWriter cw, 
     382                                        String thisName, int thisModifiers, int selfIndex, 
     383                                        String fwdClass, String fwdName, int fwdOp, 
     384                                        String maximalSig, 
     385                                        int nparamsIncludingSelf, boolean pushSelf) { 
     386        String thisSig = maximalSig; 
     387        String fwdSig = maximalSig; 
     388        String selfSig = null; 
     389        if (pushSelf) { 
     390            selfSig = Naming.nthSigParameter(maximalSig, selfIndex); 
     391            selfSig = selfSig.substring(1, selfSig.length()-1); 
     392            if ((thisModifiers & ACC_STATIC) != 0) { 
     393                if (fwdOp != INVOKESTATIC) { 
     394                    // receiver has explicit self, fwd is dotted. 
     395                    fwdSig = Naming.removeNthSigParameter(maximalSig, selfIndex); 
     396                } 
     397            } else if (fwdOp == INVOKESTATIC) { 
     398                thisSig = Naming.removeNthSigParameter(maximalSig, selfIndex); 
     399            } 
     400        } else if (selfIndex >= 0 && (thisModifiers & ACC_STATIC) != 0) { 
     401            // Dropping explicit self parameter, so remove from signature. 
     402            fwdSig = Naming.removeNthSigParameter(maximalSig, selfIndex); 
     403        } 
     404        // System.err.println("Forwarding "+thisName+":"+thisSig+ 
     405        //                    " arity "+nparamsIncludingSelf+"\n"+ 
     406        //                    "  to       "+fwdClass+"."+fwdName+":"+fwdSig); 
     407        MethodVisitor mv = cw.visitMethod(thisModifiers, thisName, thisSig, null, null); 
     408        mv.visitCode(); 
     409        if (pushSelf) { 
     410            mv.visitVarInsn(ALOAD, selfIndex); 
     411            mv.visitTypeInsn(CHECKCAST, selfSig); 
     412        } 
     413        for (int i = 0; i < nparamsIncludingSelf; i++) { 
     414            if (i==selfIndex) continue; 
     415            mv.visitVarInsn(ALOAD, i); 
     416        } 
     417        mv.visitMethodInsn(fwdOp, fwdClass, fwdName, fwdSig); 
     418        mv.visitInsn(ARETURN); 
     419 
     420        mv.visitMaxs(2, 3); 
     421        mv.visitEnd(); 
    374422    } 
    375423