Source Code Cross Referenced for MemberCodeGen.java in  » Byte-Code » Javassist » javassist » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Byte Code » Javassist » javassist.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Javassist, a Java-bytecode translator toolkit.
0003:         * Copyright (C) 1999-2006 Shigeru Chiba. All Rights Reserved.
0004:         *
0005:         * The contents of this file are subject to the Mozilla Public License Version
0006:         * 1.1 (the "License"); you may not use this file except in compliance with
0007:         * the License.  Alternatively, the contents of this file may be used under
0008:         * the terms of the GNU Lesser General Public License Version 2.1 or later.
0009:         *
0010:         * Software distributed under the License is distributed on an "AS IS" basis,
0011:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0012:         * for the specific language governing rights and limitations under the
0013:         * License.
0014:         */
0015:
0016:        package javassist.compiler;
0017:
0018:        import javassist.*;
0019:        import javassist.bytecode.*;
0020:        import javassist.compiler.ast.*;
0021:
0022:        import java.util.ArrayList;
0023:
0024:        /* Code generator methods depending on javassist.* classes.
0025:         */
0026:        public class MemberCodeGen extends CodeGen {
0027:            protected MemberResolver resolver;
0028:            protected CtClass this Class;
0029:            protected MethodInfo this Method;
0030:
0031:            protected boolean resultStatic;
0032:
0033:            public MemberCodeGen(Bytecode b, CtClass cc, ClassPool cp) {
0034:                super (b);
0035:                resolver = new MemberResolver(cp);
0036:                this Class = cc;
0037:                this Method = null;
0038:            }
0039:
0040:            /**
0041:             * Records the currently compiled method.
0042:             */
0043:            public void setThisMethod(CtMethod m) {
0044:                this Method = m.getMethodInfo2();
0045:                if (typeChecker != null)
0046:                    typeChecker.setThisMethod(this Method);
0047:            }
0048:
0049:            public CtClass getThisClass() {
0050:                return this Class;
0051:            }
0052:
0053:            /**
0054:             * Returns the JVM-internal representation of this class name.
0055:             */
0056:            protected String getThisName() {
0057:                return MemberResolver.javaToJvmName(this Class.getName());
0058:            }
0059:
0060:            /**
0061:             * Returns the JVM-internal representation of this super class name.
0062:             */
0063:            protected String getSuperName() throws CompileError {
0064:                return MemberResolver.javaToJvmName(MemberResolver
0065:                        .getSuperclass(this Class).getName());
0066:            }
0067:
0068:            protected void insertDefaultSuperCall() throws CompileError {
0069:                bytecode.addAload(0);
0070:                bytecode.addInvokespecial(MemberResolver
0071:                        .getSuperclass(this Class), "<init>", "()V");
0072:            }
0073:
0074:            static class JsrHook extends ReturnHook {
0075:                ArrayList jsrList;
0076:                int var;
0077:
0078:                JsrHook(CodeGen gen) {
0079:                    super (gen);
0080:                    jsrList = new ArrayList();
0081:                    var = gen.getMaxLocals();
0082:                    gen.incMaxLocals(1);
0083:                }
0084:
0085:                private void jsrJmp(Bytecode b) {
0086:                    b.addOpcode(JSR);
0087:                    jsrList.add(new Integer(b.currentPc()));
0088:                    b.addIndex(0);
0089:                }
0090:
0091:                protected void doit(Bytecode b, int opcode) {
0092:                    switch (opcode) {
0093:                    case Opcode.RETURN:
0094:                        jsrJmp(b);
0095:                        break;
0096:                    case ARETURN:
0097:                        b.addAstore(var);
0098:                        jsrJmp(b);
0099:                        b.addAload(var);
0100:                        break;
0101:                    case IRETURN:
0102:                        b.addIstore(var);
0103:                        jsrJmp(b);
0104:                        b.addIload(var);
0105:                        break;
0106:                    case LRETURN:
0107:                        b.addLstore(var);
0108:                        jsrJmp(b);
0109:                        b.addLload(var);
0110:                        break;
0111:                    case DRETURN:
0112:                        b.addDstore(var);
0113:                        jsrJmp(b);
0114:                        b.addDload(var);
0115:                        break;
0116:                    case FRETURN:
0117:                        b.addFstore(var);
0118:                        jsrJmp(b);
0119:                        b.addFload(var);
0120:                        break;
0121:                    default:
0122:                        throw new RuntimeException("fatal");
0123:                    }
0124:                }
0125:            }
0126:
0127:            protected void atTryStmnt(Stmnt st) throws CompileError {
0128:                Bytecode bc = bytecode;
0129:                Stmnt body = (Stmnt) st.getLeft();
0130:                if (body == null)
0131:                    return;
0132:
0133:                ASTList catchList = (ASTList) st.getRight().getLeft();
0134:                Stmnt finallyBlock = (Stmnt) st.getRight().getRight().getLeft();
0135:                ArrayList gotoList = new ArrayList();
0136:
0137:                JsrHook jsrHook = null;
0138:                if (finallyBlock != null)
0139:                    jsrHook = new JsrHook(this );
0140:
0141:                int start = bc.currentPc();
0142:                body.accept(this );
0143:                int end = bc.currentPc();
0144:                if (start == end)
0145:                    throw new CompileError("empty try block");
0146:
0147:                boolean tryNotReturn = !hasReturned;
0148:                if (tryNotReturn) {
0149:                    bc.addOpcode(Opcode.GOTO);
0150:                    gotoList.add(new Integer(bc.currentPc()));
0151:                    bc.addIndex(0); // correct later
0152:                }
0153:
0154:                int var = getMaxLocals();
0155:                incMaxLocals(1);
0156:                while (catchList != null) {
0157:                    // catch clause
0158:                    Pair p = (Pair) catchList.head();
0159:                    catchList = catchList.tail();
0160:                    Declarator decl = (Declarator) p.getLeft();
0161:                    Stmnt block = (Stmnt) p.getRight();
0162:
0163:                    decl.setLocalVar(var);
0164:
0165:                    CtClass type = resolver.lookupClassByJvmName(decl
0166:                            .getClassName());
0167:                    decl.setClassName(MemberResolver.javaToJvmName(type
0168:                            .getName()));
0169:                    bc.addExceptionHandler(start, end, bc.currentPc(), type);
0170:                    bc.growStack(1);
0171:                    bc.addAstore(var);
0172:                    hasReturned = false;
0173:                    if (block != null)
0174:                        block.accept(this );
0175:
0176:                    if (!hasReturned) {
0177:                        bc.addOpcode(Opcode.GOTO);
0178:                        gotoList.add(new Integer(bc.currentPc()));
0179:                        bc.addIndex(0); // correct later
0180:                        tryNotReturn = true;
0181:                    }
0182:                }
0183:
0184:                int pcFinally = -1;
0185:                if (finallyBlock != null) {
0186:                    jsrHook.remove(this );
0187:                    // catch (any) clause
0188:                    int pcAnyCatch = bc.currentPc();
0189:                    bc.addExceptionHandler(start, pcAnyCatch, pcAnyCatch, 0);
0190:                    bc.growStack(1);
0191:                    bc.addAstore(var);
0192:                    bc.addOpcode(JSR);
0193:                    int pcJsrIndex = bc.currentPc();
0194:                    bc.addIndex(0); // correct later
0195:                    bc.addAload(var);
0196:                    bc.addOpcode(ATHROW);
0197:
0198:                    // finally clause
0199:                    pcFinally = bc.currentPc();
0200:                    bc.write16bit(pcJsrIndex, pcFinally - pcJsrIndex + 1);
0201:                    int retAddr = getMaxLocals();
0202:                    incMaxLocals(1);
0203:                    bc.growStack(1); // return address
0204:                    bc.addAstore(retAddr);
0205:                    hasReturned = false;
0206:                    finallyBlock.accept(this );
0207:                    if (!hasReturned) {
0208:                        bc.addOpcode(RET);
0209:                        bc.add(retAddr);
0210:                    }
0211:                }
0212:
0213:                int pcEnd = bc.currentPc();
0214:                patchGoto(gotoList, pcEnd);
0215:                if (finallyBlock != null) {
0216:                    patchGoto(jsrHook.jsrList, pcFinally);
0217:                    if (tryNotReturn) {
0218:                        bc.addOpcode(JSR);
0219:                        bc.addIndex(pcFinally - pcEnd);
0220:                    }
0221:                }
0222:
0223:                hasReturned = !tryNotReturn;
0224:            }
0225:
0226:            public void atNewExpr(NewExpr expr) throws CompileError {
0227:                if (expr.isArray())
0228:                    atNewArrayExpr(expr);
0229:                else {
0230:                    CtClass clazz = resolver.lookupClassByName(expr
0231:                            .getClassName());
0232:                    String cname = clazz.getName();
0233:                    ASTList args = expr.getArguments();
0234:                    bytecode.addNew(cname);
0235:                    bytecode.addOpcode(DUP);
0236:
0237:                    atMethodCallCore(clazz, MethodInfo.nameInit, args, false,
0238:                            true, -1, null);
0239:
0240:                    exprType = CLASS;
0241:                    arrayDim = 0;
0242:                    className = MemberResolver.javaToJvmName(cname);
0243:                }
0244:            }
0245:
0246:            public void atNewArrayExpr(NewExpr expr) throws CompileError {
0247:                int type = expr.getArrayType();
0248:                ASTList size = expr.getArraySize();
0249:                ASTList classname = expr.getClassName();
0250:                ArrayInit init = expr.getInitializer();
0251:                if (size.length() > 1) {
0252:                    if (init != null)
0253:                        throw new CompileError(
0254:                                "sorry, multi-dimensional array initializer "
0255:                                        + "for new is not supported");
0256:
0257:                    atMultiNewArray(type, classname, size);
0258:                    return;
0259:                }
0260:
0261:                ASTree sizeExpr = size.head();
0262:                atNewArrayExpr2(type, sizeExpr, Declarator.astToClassName(
0263:                        classname, '/'), init);
0264:            }
0265:
0266:            private void atNewArrayExpr2(int type, ASTree sizeExpr,
0267:                    String jvmClassname, ArrayInit init) throws CompileError {
0268:                if (init == null)
0269:                    if (sizeExpr == null)
0270:                        throw new CompileError("no array size");
0271:                    else
0272:                        sizeExpr.accept(this );
0273:                else if (sizeExpr == null) {
0274:                    int s = init.length();
0275:                    bytecode.addIconst(s);
0276:                } else
0277:                    throw new CompileError(
0278:                            "unnecessary array size specified for new");
0279:
0280:                String elementClass;
0281:                if (type == CLASS) {
0282:                    elementClass = resolveClassName(jvmClassname);
0283:                    bytecode.addAnewarray(MemberResolver
0284:                            .jvmToJavaName(elementClass));
0285:                } else {
0286:                    elementClass = null;
0287:                    int atype = 0;
0288:                    switch (type) {
0289:                    case BOOLEAN:
0290:                        atype = T_BOOLEAN;
0291:                        break;
0292:                    case CHAR:
0293:                        atype = T_CHAR;
0294:                        break;
0295:                    case FLOAT:
0296:                        atype = T_FLOAT;
0297:                        break;
0298:                    case DOUBLE:
0299:                        atype = T_DOUBLE;
0300:                        break;
0301:                    case BYTE:
0302:                        atype = T_BYTE;
0303:                        break;
0304:                    case SHORT:
0305:                        atype = T_SHORT;
0306:                        break;
0307:                    case INT:
0308:                        atype = T_INT;
0309:                        break;
0310:                    case LONG:
0311:                        atype = T_LONG;
0312:                        break;
0313:                    default:
0314:                        badNewExpr();
0315:                        break;
0316:                    }
0317:
0318:                    bytecode.addOpcode(NEWARRAY);
0319:                    bytecode.add(atype);
0320:                }
0321:
0322:                if (init != null) {
0323:                    int s = init.length();
0324:                    ASTList list = init;
0325:                    for (int i = 0; i < s; i++) {
0326:                        bytecode.addOpcode(DUP);
0327:                        bytecode.addIconst(i);
0328:                        list.head().accept(this );
0329:                        if (!isRefType(type))
0330:                            atNumCastExpr(exprType, type);
0331:
0332:                        bytecode.addOpcode(getArrayWriteOp(type, 0));
0333:                        list = list.tail();
0334:                    }
0335:                }
0336:
0337:                exprType = type;
0338:                arrayDim = 1;
0339:                className = elementClass;
0340:            }
0341:
0342:            private static void badNewExpr() throws CompileError {
0343:                throw new CompileError("bad new expression");
0344:            }
0345:
0346:            protected void atArrayVariableAssign(ArrayInit init, int varType,
0347:                    int varArray, String varClass) throws CompileError {
0348:                atNewArrayExpr2(varType, null, varClass, init);
0349:            }
0350:
0351:            public void atArrayInit(ArrayInit init) throws CompileError {
0352:                throw new CompileError("array initializer is not supported");
0353:            }
0354:
0355:            protected void atMultiNewArray(int type, ASTList classname,
0356:                    ASTList size) throws CompileError {
0357:                int count, dim;
0358:                dim = size.length();
0359:                for (count = 0; size != null; size = size.tail()) {
0360:                    ASTree s = size.head();
0361:                    if (s == null)
0362:                        break; // int[][][] a = new int[3][4][];
0363:
0364:                    ++count;
0365:                    s.accept(this );
0366:                    if (exprType != INT)
0367:                        throw new CompileError("bad type for array size");
0368:                }
0369:
0370:                String desc;
0371:                exprType = type;
0372:                arrayDim = dim;
0373:                if (type == CLASS) {
0374:                    className = resolveClassName(classname);
0375:                    desc = toJvmArrayName(className, dim);
0376:                } else
0377:                    desc = toJvmTypeName(type, dim);
0378:
0379:                bytecode.addMultiNewarray(desc, count);
0380:            }
0381:
0382:            public void atCallExpr(CallExpr expr) throws CompileError {
0383:                String mname = null;
0384:                CtClass targetClass = null;
0385:                ASTree method = expr.oprand1();
0386:                ASTList args = (ASTList) expr.oprand2();
0387:                boolean isStatic = false;
0388:                boolean isSpecial = false;
0389:                int aload0pos = -1;
0390:
0391:                MemberResolver.Method cached = expr.getMethod();
0392:                if (method instanceof  Member) {
0393:                    mname = ((Member) method).get();
0394:                    targetClass = this Class;
0395:                    if (inStaticMethod || (cached != null && cached.isStatic()))
0396:                        isStatic = true; // should be static
0397:                    else {
0398:                        aload0pos = bytecode.currentPc();
0399:                        bytecode.addAload(0); // this
0400:                    }
0401:                } else if (method instanceof  Keyword) { // constructor
0402:                    isSpecial = true;
0403:                    mname = MethodInfo.nameInit; // <init>
0404:                    targetClass = this Class;
0405:                    if (inStaticMethod)
0406:                        throw new CompileError("a constructor cannot be static");
0407:                    else
0408:                        bytecode.addAload(0); // this
0409:
0410:                    if (((Keyword) method).get() == SUPER)
0411:                        targetClass = MemberResolver.getSuperclass(targetClass);
0412:                } else if (method instanceof  Expr) {
0413:                    Expr e = (Expr) method;
0414:                    mname = ((Symbol) e.oprand2()).get();
0415:                    int op = e.getOperator();
0416:                    if (op == MEMBER) { // static method
0417:                        targetClass = resolver.lookupClass(((Symbol) e
0418:                                .oprand1()).get(), false);
0419:                        isStatic = true;
0420:                    } else if (op == '.') {
0421:                        ASTree target = e.oprand1();
0422:                        if (target instanceof  Keyword)
0423:                            if (((Keyword) target).get() == SUPER)
0424:                                isSpecial = true;
0425:
0426:                        try {
0427:                            target.accept(this );
0428:                        } catch (NoFieldException nfe) {
0429:                            if (nfe.getExpr() != target)
0430:                                throw nfe;
0431:
0432:                            // it should be a static method.
0433:                            exprType = CLASS;
0434:                            arrayDim = 0;
0435:                            className = nfe.getField(); // JVM-internal
0436:                            resolver.recordPackage(className);
0437:                            isStatic = true;
0438:                        }
0439:
0440:                        if (arrayDim > 0)
0441:                            targetClass = resolver.lookupClass(javaLangObject,
0442:                                    true);
0443:                        else if (exprType == CLASS /* && arrayDim == 0 */)
0444:                            targetClass = resolver
0445:                                    .lookupClassByJvmName(className);
0446:                        else
0447:                            badMethod();
0448:                    } else
0449:                        badMethod();
0450:                } else
0451:                    fatal();
0452:
0453:                atMethodCallCore(targetClass, mname, args, isStatic, isSpecial,
0454:                        aload0pos, cached);
0455:            }
0456:
0457:            private static void badMethod() throws CompileError {
0458:                throw new CompileError("bad method");
0459:            }
0460:
0461:            /*
0462:             * atMethodCallCore() is also called by doit() in NewExpr.ProceedForNew
0463:             *
0464:             * @param targetClass       the class at which method lookup starts.
0465:             * @param found         not null if the method look has been already done.
0466:             */
0467:            public void atMethodCallCore(CtClass targetClass, String mname,
0468:                    ASTList args, boolean isStatic, boolean isSpecial,
0469:                    int aload0pos, MemberResolver.Method found)
0470:                    throws CompileError {
0471:                int nargs = getMethodArgsLength(args);
0472:                int[] types = new int[nargs];
0473:                int[] dims = new int[nargs];
0474:                String[] cnames = new String[nargs];
0475:
0476:                if (!isStatic && found != null && found.isStatic()) {
0477:                    bytecode.addOpcode(POP);
0478:                    isStatic = true;
0479:                }
0480:
0481:                int stack = bytecode.getStackDepth();
0482:
0483:                // generate code for evaluating arguments.
0484:                atMethodArgs(args, types, dims, cnames);
0485:
0486:                // used by invokeinterface
0487:                int count = bytecode.getStackDepth() - stack + 1;
0488:
0489:                if (found == null)
0490:                    found = resolver.lookupMethod(targetClass, this Class,
0491:                            this Method, mname, types, dims, cnames);
0492:
0493:                if (found == null) {
0494:                    String msg;
0495:                    if (mname.equals(MethodInfo.nameInit))
0496:                        msg = "constructor not found";
0497:                    else
0498:                        msg = "Method " + mname + " not found in "
0499:                                + targetClass.getName();
0500:
0501:                    throw new CompileError(msg);
0502:                }
0503:
0504:                atMethodCallCore2(targetClass, mname, isStatic, isSpecial,
0505:                        aload0pos, count, found);
0506:            }
0507:
0508:            private void atMethodCallCore2(CtClass targetClass, String mname,
0509:                    boolean isStatic, boolean isSpecial, int aload0pos,
0510:                    int count, MemberResolver.Method found) throws CompileError {
0511:                CtClass declClass = found.declaring;
0512:                MethodInfo minfo = found.info;
0513:                String desc = minfo.getDescriptor();
0514:                int acc = minfo.getAccessFlags();
0515:
0516:                if (mname.equals(MethodInfo.nameInit)) {
0517:                    isSpecial = true;
0518:                    if (declClass != targetClass)
0519:                        throw new CompileError("no such a constructor");
0520:
0521:                    if (declClass != this Class && AccessFlag.isPrivate(acc)) {
0522:                        desc = getAccessibleConstructor(desc, declClass, minfo);
0523:                        bytecode.addOpcode(Opcode.ACONST_NULL); // the last parameter
0524:                    }
0525:                } else if (AccessFlag.isPrivate(acc))
0526:                    if (declClass == this Class)
0527:                        isSpecial = true;
0528:                    else {
0529:                        isSpecial = false;
0530:                        isStatic = true;
0531:                        String origDesc = desc;
0532:                        if ((acc & AccessFlag.STATIC) == 0)
0533:                            desc = Descriptor.insertParameter(declClass
0534:                                    .getName(), origDesc);
0535:
0536:                        acc = AccessFlag.setPackage(acc) | AccessFlag.STATIC;
0537:                        mname = getAccessiblePrivate(mname, origDesc, desc,
0538:                                minfo, declClass);
0539:                    }
0540:
0541:                boolean popTarget = false;
0542:                if ((acc & AccessFlag.STATIC) != 0) {
0543:                    if (!isStatic) {
0544:                        /* this method is static but the target object is
0545:                           on stack.  It must be popped out.  If aload0pos >= 0,
0546:                           then the target object was pushed by aload_0.  It is
0547:                           overwritten by NOP.
0548:                         */
0549:                        isStatic = true;
0550:                        if (aload0pos >= 0)
0551:                            bytecode.write(aload0pos, NOP);
0552:                        else
0553:                            popTarget = true;
0554:                    }
0555:
0556:                    bytecode.addInvokestatic(declClass, mname, desc);
0557:                } else if (isSpecial) // if (isSpecial && notStatic(acc))
0558:                    bytecode.addInvokespecial(declClass, mname, desc);
0559:                else if (declClass.isInterface())
0560:                    bytecode.addInvokeinterface(declClass, mname, desc, count);
0561:                else if (isStatic)
0562:                    throw new CompileError(mname + " is not static");
0563:                else
0564:                    bytecode.addInvokevirtual(declClass, mname, desc);
0565:
0566:                setReturnType(desc, isStatic, popTarget);
0567:            }
0568:
0569:            /*
0570:             * Finds (or adds if necessary) a hidden accessor if the method
0571:             * is in an enclosing class.
0572:             *
0573:             * @param desc          the descriptor of the method.
0574:             * @param declClass     the class declaring the method.
0575:             */
0576:            protected String getAccessiblePrivate(String methodName,
0577:                    String desc, String newDesc, MethodInfo minfo,
0578:                    CtClass declClass) throws CompileError {
0579:                if (isEnclosing(declClass, this Class)) {
0580:                    AccessorMaker maker = declClass.getAccessorMaker();
0581:                    if (maker != null)
0582:                        return maker.getMethodAccessor(methodName, desc,
0583:                                newDesc, minfo);
0584:                }
0585:
0586:                throw new CompileError("Method " + methodName + " is private");
0587:            }
0588:
0589:            /*
0590:             * Finds (or adds if necessary) a hidden constructor if the given
0591:             * constructor is in an enclosing class.
0592:             *
0593:             * @param desc          the descriptor of the constructor.
0594:             * @param declClass     the class declaring the constructor.
0595:             * @param minfo         the method info of the constructor.
0596:             * @return the descriptor of the hidden constructor.
0597:             */
0598:            protected String getAccessibleConstructor(String desc,
0599:                    CtClass declClass, MethodInfo minfo) throws CompileError {
0600:                if (isEnclosing(declClass, this Class)) {
0601:                    AccessorMaker maker = declClass.getAccessorMaker();
0602:                    if (maker != null)
0603:                        return maker.getConstructor(declClass, desc, minfo);
0604:                }
0605:
0606:                throw new CompileError("the called constructor is private in "
0607:                        + declClass.getName());
0608:            }
0609:
0610:            private boolean isEnclosing(CtClass outer, CtClass inner) {
0611:                try {
0612:                    while (inner != null) {
0613:                        inner = inner.getDeclaringClass();
0614:                        if (inner == outer)
0615:                            return true;
0616:                    }
0617:                } catch (NotFoundException e) {
0618:                }
0619:                return false;
0620:            }
0621:
0622:            public int getMethodArgsLength(ASTList args) {
0623:                return ASTList.length(args);
0624:            }
0625:
0626:            public void atMethodArgs(ASTList args, int[] types, int[] dims,
0627:                    String[] cnames) throws CompileError {
0628:                int i = 0;
0629:                while (args != null) {
0630:                    ASTree a = args.head();
0631:                    a.accept(this );
0632:                    types[i] = exprType;
0633:                    dims[i] = arrayDim;
0634:                    cnames[i] = className;
0635:                    ++i;
0636:                    args = args.tail();
0637:                }
0638:            }
0639:
0640:            void setReturnType(String desc, boolean isStatic, boolean popTarget)
0641:                    throws CompileError {
0642:                int i = desc.indexOf(')');
0643:                if (i < 0)
0644:                    badMethod();
0645:
0646:                char c = desc.charAt(++i);
0647:                int dim = 0;
0648:                while (c == '[') {
0649:                    ++dim;
0650:                    c = desc.charAt(++i);
0651:                }
0652:
0653:                arrayDim = dim;
0654:                if (c == 'L') {
0655:                    int j = desc.indexOf(';', i + 1);
0656:                    if (j < 0)
0657:                        badMethod();
0658:
0659:                    exprType = CLASS;
0660:                    className = desc.substring(i + 1, j);
0661:                } else {
0662:                    exprType = MemberResolver.descToType(c);
0663:                    className = null;
0664:                }
0665:
0666:                int etype = exprType;
0667:                if (isStatic) {
0668:                    if (popTarget) {
0669:                        if (is2word(etype, dim)) {
0670:                            bytecode.addOpcode(DUP2_X1);
0671:                            bytecode.addOpcode(POP2);
0672:                            bytecode.addOpcode(POP);
0673:                        } else if (etype == VOID)
0674:                            bytecode.addOpcode(POP);
0675:                        else {
0676:                            bytecode.addOpcode(SWAP);
0677:                            bytecode.addOpcode(POP);
0678:                        }
0679:                    }
0680:                }
0681:            }
0682:
0683:            protected void atFieldAssign(Expr expr, int op, ASTree left,
0684:                    ASTree right, boolean doDup) throws CompileError {
0685:                CtField f = fieldAccess(left, false);
0686:                boolean is_static = resultStatic;
0687:                if (op != '=' && !is_static)
0688:                    bytecode.addOpcode(DUP);
0689:
0690:                int fi;
0691:                if (op == '=') {
0692:                    FieldInfo finfo = f.getFieldInfo2();
0693:                    setFieldType(finfo);
0694:                    AccessorMaker maker = isAccessibleField(f, finfo);
0695:                    if (maker == null)
0696:                        fi = addFieldrefInfo(f, finfo);
0697:                    else
0698:                        fi = 0;
0699:                } else
0700:                    fi = atFieldRead(f, is_static);
0701:
0702:                int fType = exprType;
0703:                int fDim = arrayDim;
0704:                String cname = className;
0705:
0706:                atAssignCore(expr, op, right, fType, fDim, cname);
0707:
0708:                boolean is2w = is2word(fType, fDim);
0709:                if (doDup) {
0710:                    int dup_code;
0711:                    if (is_static)
0712:                        dup_code = (is2w ? DUP2 : DUP);
0713:                    else
0714:                        dup_code = (is2w ? DUP2_X1 : DUP_X1);
0715:
0716:                    bytecode.addOpcode(dup_code);
0717:                }
0718:
0719:                atFieldAssignCore(f, is_static, fi, is2w);
0720:
0721:                exprType = fType;
0722:                arrayDim = fDim;
0723:                className = cname;
0724:            }
0725:
0726:            /* If fi == 0, the field must be a private field in an enclosing class.
0727:             */
0728:            private void atFieldAssignCore(CtField f, boolean is_static,
0729:                    int fi, boolean is2byte) throws CompileError {
0730:                if (fi != 0) {
0731:                    if (is_static) {
0732:                        bytecode.add(PUTSTATIC);
0733:                        bytecode.growStack(is2byte ? -2 : -1);
0734:                    } else {
0735:                        bytecode.add(PUTFIELD);
0736:                        bytecode.growStack(is2byte ? -3 : -2);
0737:                    }
0738:
0739:                    bytecode.addIndex(fi);
0740:                } else {
0741:                    CtClass declClass = f.getDeclaringClass();
0742:                    AccessorMaker maker = declClass.getAccessorMaker();
0743:                    // make should be non null.
0744:                    FieldInfo finfo = f.getFieldInfo2();
0745:                    MethodInfo minfo = maker.getFieldSetter(finfo, is_static);
0746:                    bytecode.addInvokestatic(declClass, minfo.getName(), minfo
0747:                            .getDescriptor());
0748:                }
0749:            }
0750:
0751:            /* overwritten in JvstCodeGen.
0752:             */
0753:            public void atMember(Member mem) throws CompileError {
0754:                atFieldRead(mem);
0755:            }
0756:
0757:            protected void atFieldRead(ASTree expr) throws CompileError {
0758:                CtField f = fieldAccess(expr, true);
0759:                if (f == null) {
0760:                    atArrayLength(expr);
0761:                    return;
0762:                }
0763:
0764:                boolean is_static = resultStatic;
0765:                ASTree cexpr = TypeChecker.getConstantFieldValue(f);
0766:                if (cexpr == null)
0767:                    atFieldRead(f, is_static);
0768:                else {
0769:                    cexpr.accept(this );
0770:                    setFieldType(f.getFieldInfo2());
0771:                }
0772:            }
0773:
0774:            private void atArrayLength(ASTree expr) throws CompileError {
0775:                if (arrayDim == 0)
0776:                    throw new CompileError(".length applied to a non array");
0777:
0778:                bytecode.addOpcode(ARRAYLENGTH);
0779:                exprType = INT;
0780:                arrayDim = 0;
0781:            }
0782:
0783:            /**
0784:             * Generates bytecode for reading a field value.
0785:             * It returns a fieldref_info index or zero if the field is a private
0786:             * one declared in an enclosing class. 
0787:             */
0788:            private int atFieldRead(CtField f, boolean isStatic)
0789:                    throws CompileError {
0790:                FieldInfo finfo = f.getFieldInfo2();
0791:                boolean is2byte = setFieldType(finfo);
0792:                AccessorMaker maker = isAccessibleField(f, finfo);
0793:                if (maker != null) {
0794:                    MethodInfo minfo = maker.getFieldGetter(finfo, isStatic);
0795:                    bytecode.addInvokestatic(f.getDeclaringClass(), minfo
0796:                            .getName(), minfo.getDescriptor());
0797:                    return 0;
0798:                } else {
0799:                    int fi = addFieldrefInfo(f, finfo);
0800:                    if (isStatic) {
0801:                        bytecode.add(GETSTATIC);
0802:                        bytecode.growStack(is2byte ? 2 : 1);
0803:                    } else {
0804:                        bytecode.add(GETFIELD);
0805:                        bytecode.growStack(is2byte ? 1 : 0);
0806:                    }
0807:
0808:                    bytecode.addIndex(fi);
0809:                    return fi;
0810:                }
0811:            }
0812:
0813:            /**
0814:             * Returns null if the field is accessible.  Otherwise, it throws
0815:             * an exception or it returns AccessorMaker if the field is a private
0816:             * one declared in an enclosing class.
0817:             */
0818:            private AccessorMaker isAccessibleField(CtField f, FieldInfo finfo)
0819:                    throws CompileError {
0820:                if (AccessFlag.isPrivate(finfo.getAccessFlags())
0821:                        && f.getDeclaringClass() != this Class) {
0822:                    CtClass declClass = f.getDeclaringClass();
0823:                    if (isEnclosing(declClass, this Class)) {
0824:                        AccessorMaker maker = declClass.getAccessorMaker();
0825:                        if (maker != null)
0826:                            return maker;
0827:                        else
0828:                            throw new CompileError("fatal error.  bug?");
0829:                    } else
0830:                        throw new CompileError("Field " + f.getName() + " in "
0831:                                + declClass.getName() + " is private.");
0832:                }
0833:
0834:                return null; // accessible field
0835:            }
0836:
0837:            /**
0838:             * Sets exprType, arrayDim, and className.
0839:             *
0840:             * @return true if the field type is long or double. 
0841:             */
0842:            private boolean setFieldType(FieldInfo finfo) throws CompileError {
0843:                String type = finfo.getDescriptor();
0844:
0845:                int i = 0;
0846:                int dim = 0;
0847:                char c = type.charAt(i);
0848:                while (c == '[') {
0849:                    ++dim;
0850:                    c = type.charAt(++i);
0851:                }
0852:
0853:                arrayDim = dim;
0854:                exprType = MemberResolver.descToType(c);
0855:
0856:                if (c == 'L')
0857:                    className = type.substring(i + 1, type.indexOf(';', i + 1));
0858:                else
0859:                    className = null;
0860:
0861:                boolean is2byte = (c == 'J' || c == 'D');
0862:                return is2byte;
0863:            }
0864:
0865:            private int addFieldrefInfo(CtField f, FieldInfo finfo) {
0866:                ConstPool cp = bytecode.getConstPool();
0867:                String cname = f.getDeclaringClass().getName();
0868:                int ci = cp.addClassInfo(cname);
0869:                String name = finfo.getName();
0870:                String type = finfo.getDescriptor();
0871:                return cp.addFieldrefInfo(ci, name, type);
0872:            }
0873:
0874:            protected void atFieldPlusPlus(int token, boolean isPost,
0875:                    ASTree oprand, Expr expr, boolean doDup)
0876:                    throws CompileError {
0877:                CtField f = fieldAccess(oprand, false);
0878:                boolean is_static = resultStatic;
0879:                if (!is_static)
0880:                    bytecode.addOpcode(DUP);
0881:
0882:                int fi = atFieldRead(f, is_static);
0883:                int t = exprType;
0884:                boolean is2w = is2word(t, arrayDim);
0885:
0886:                int dup_code;
0887:                if (is_static)
0888:                    dup_code = (is2w ? DUP2 : DUP);
0889:                else
0890:                    dup_code = (is2w ? DUP2_X1 : DUP_X1);
0891:
0892:                atPlusPlusCore(dup_code, doDup, token, isPost, expr);
0893:                atFieldAssignCore(f, is_static, fi, is2w);
0894:            }
0895:
0896:            /* This method also returns a value in resultStatic.
0897:             *
0898:             * @param acceptLength      true if array length is acceptable
0899:             */
0900:            protected CtField fieldAccess(ASTree expr, boolean acceptLength)
0901:                    throws CompileError {
0902:                if (expr instanceof  Member) {
0903:                    String name = ((Member) expr).get();
0904:                    CtField f = null;
0905:                    try {
0906:                        f = this Class.getField(name);
0907:                    } catch (NotFoundException e) {
0908:                        // EXPR might be part of a static member access?
0909:                        throw new NoFieldException(name, expr);
0910:                    }
0911:
0912:                    boolean is_static = Modifier.isStatic(f.getModifiers());
0913:                    if (!is_static)
0914:                        if (inStaticMethod)
0915:                            throw new CompileError(
0916:                                    "not available in a static method: " + name);
0917:                        else
0918:                            bytecode.addAload(0); // this
0919:
0920:                    resultStatic = is_static;
0921:                    return f;
0922:                } else if (expr instanceof  Expr) {
0923:                    Expr e = (Expr) expr;
0924:                    int op = e.getOperator();
0925:                    if (op == MEMBER) {
0926:                        /* static member by # (extension by Javassist)
0927:                         * For example, if int.class is parsed, the resulting tree
0928:                         * is (# "java.lang.Integer" "TYPE"). 
0929:                         */
0930:                        CtField f = resolver.lookupField(((Symbol) e.oprand1())
0931:                                .get(), (Symbol) e.oprand2());
0932:                        resultStatic = true;
0933:                        return f;
0934:                    } else if (op == '.') {
0935:                        CtField f = null;
0936:                        try {
0937:                            e.oprand1().accept(this );
0938:                            /* Don't call lookupFieldByJvmName2().
0939:                             * The left operand of . is not a class name but
0940:                             * a normal expression.
0941:                             */
0942:                            if (exprType == CLASS && arrayDim == 0)
0943:                                f = resolver.lookupFieldByJvmName(className,
0944:                                        (Symbol) e.oprand2());
0945:                            else if (acceptLength
0946:                                    && arrayDim > 0
0947:                                    && ((Symbol) e.oprand2()).get().equals(
0948:                                            "length"))
0949:                                return null; // expr is an array length.
0950:                            else
0951:                                badLvalue();
0952:
0953:                            boolean is_static = Modifier.isStatic(f
0954:                                    .getModifiers());
0955:                            if (is_static)
0956:                                bytecode.addOpcode(POP);
0957:
0958:                            resultStatic = is_static;
0959:                            return f;
0960:                        } catch (NoFieldException nfe) {
0961:                            if (nfe.getExpr() != e.oprand1())
0962:                                throw nfe;
0963:
0964:                            /* EXPR should be a static field.
0965:                             * If EXPR might be part of a qualified class name,
0966:                             * lookupFieldByJvmName2() throws NoFieldException.
0967:                             */
0968:                            Symbol fname = (Symbol) e.oprand2();
0969:                            String cname = nfe.getField();
0970:                            f = resolver.lookupFieldByJvmName2(cname, fname,
0971:                                    expr);
0972:                            resolver.recordPackage(cname);
0973:                            resultStatic = true;
0974:                            return f;
0975:                        }
0976:                    } else
0977:                        badLvalue();
0978:                } else
0979:                    badLvalue();
0980:
0981:                resultStatic = false;
0982:                return null; // never reach
0983:            }
0984:
0985:            private static void badLvalue() throws CompileError {
0986:                throw new CompileError("bad l-value");
0987:            }
0988:
0989:            public CtClass[] makeParamList(MethodDecl md) throws CompileError {
0990:                CtClass[] params;
0991:                ASTList plist = md.getParams();
0992:                if (plist == null)
0993:                    params = new CtClass[0];
0994:                else {
0995:                    int i = 0;
0996:                    params = new CtClass[plist.length()];
0997:                    while (plist != null) {
0998:                        params[i++] = resolver.lookupClass((Declarator) plist
0999:                                .head());
1000:                        plist = plist.tail();
1001:                    }
1002:                }
1003:
1004:                return params;
1005:            }
1006:
1007:            public CtClass[] makeThrowsList(MethodDecl md) throws CompileError {
1008:                CtClass[] clist;
1009:                ASTList list = md.getThrows();
1010:                if (list == null)
1011:                    return null;
1012:                else {
1013:                    int i = 0;
1014:                    clist = new CtClass[list.length()];
1015:                    while (list != null) {
1016:                        clist[i++] = resolver.lookupClassByName((ASTList) list
1017:                                .head());
1018:                        list = list.tail();
1019:                    }
1020:
1021:                    return clist;
1022:                }
1023:            }
1024:
1025:            /* Converts a class name into a JVM-internal representation.
1026:             *
1027:             * It may also expand a simple class name to java.lang.*.
1028:             * For example, this converts Object into java/lang/Object.
1029:             */
1030:            protected String resolveClassName(ASTList name) throws CompileError {
1031:                return resolver.resolveClassName(name);
1032:            }
1033:
1034:            /* Expands a simple class name to java.lang.*.
1035:             * For example, this converts Object into java/lang/Object.
1036:             */
1037:            protected String resolveClassName(String jvmName)
1038:                    throws CompileError {
1039:                return resolver.resolveJvmClassName(jvmName);
1040:            }
1041:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.