Source Code Cross Referenced for FieldAccessModifier.java in  » Database-ORM » Speedo_1.4.5 » org » objectweb » speedo » generation » enhancer » pc » 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 » Database ORM » Speedo_1.4.5 » org.objectweb.speedo.generation.enhancer.pc 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * Copyright (C) 2001-2005 France Telecom R&D
003:         *
004:         * This library is free software; you can redistribute it and/or
005:         * modify it under the terms of the GNU Lesser General Public
006:         * License as published by the Free Software Foundation; either
007:         * version 2 of the License, or (at your option) any later version.
008:         *
009:         * This library is distributed in the hope that it will be useful,
010:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
011:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012:         * Lesser General Public License for more details.
013:         *
014:         * You should have received a copy of the GNU Lesser General Public
015:         * License along with this library; if not, write to the Free Software
016:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
017:         */package org.objectweb.speedo.generation.enhancer.pc;
018:
019:        import org.objectweb.asm.CodeAdapter;
020:        import org.objectweb.asm.CodeVisitor;
021:        import org.objectweb.asm.Constants;
022:        import org.objectweb.asm.ClassVisitor;
023:        import org.objectweb.asm.Label;
024:        import org.objectweb.asm.Type;
025:        import org.objectweb.asm.Attribute;
026:        import org.objectweb.speedo.lib.Personality;
027:        import org.objectweb.speedo.metadata.SpeedoField;
028:        import org.objectweb.speedo.metadata.SpeedoClass;
029:        import org.objectweb.speedo.metadata.SpeedoMetaInfo;
030:        import org.objectweb.speedo.generation.enhancer.common.LoggedClassAdapter;
031:        import org.objectweb.speedo.generation.enhancer.common.Util;
032:        import org.objectweb.speedo.generation.lib.NamingRules;
033:        import org.objectweb.util.monolog.api.Logger;
034:        import org.objectweb.util.monolog.api.BasicLevel;
035:
036:        import java.util.List;
037:        import java.util.ArrayList;
038:        import java.util.Collection;
039:
040:        /**
041:         * Replaces field accesses by calls to getter and setter methods.
042:         *
043:         * Adapted from modifyMethods and replaceInstruction in EnhancerTool.
044:         */
045:        public class FieldAccessModifier extends LoggedClassAdapter {
046:
047:            /**
048:             * Stack size variation corresponding to each JVM instruction. This stack
049:             * variation is equal to the size of the values produced by an instruction,
050:             * minus the size of the values consumed by this instruction.
051:             */
052:
053:            final static int[] SIZE;
054:
055:            /**
056:             * Computes the stack size variation corresponding to each JVM instruction.
057:             * Copied from the org.objectweb.asm.CodeWriter class.
058:             */
059:
060:            static {
061:                int i;
062:                int[] b = new int[202];
063:                String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDDCDCDEEEEEEEEE"
064:                        + "EEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCDCDCEEEEDDDDDDDCDCDCEFEF"
065:                        + "DDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFEDDDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
066:                for (i = 0; i < b.length; ++i) {
067:                    b[i] = s.charAt(i) - 'E';
068:                }
069:                SIZE = b;
070:            }
071:
072:            /**
073:             * A collections of SpeedoXMLDescriptors describing known persistent classes.
074:             */
075:            private final SpeedoClass speedoClass;
076:            private final SpeedoMetaInfo smi;;
077:
078:            /**
079:             * Internal name of the visited class.
080:             */
081:            final String owner;
082:
083:            /**
084:             * Internal name of the corresponding "XXXFields" class.
085:             */
086:            final String fieldsOwner;
087:
088:            final int nbfields;
089:
090:            /**
091:             * Constructs a new {@link FieldAccessModifier}.
092:             *
093:             * @param cv the class visitor to be used to generate the modified class
094:             * @param sc is the SpeedoMeta object representing the persistent class 
095:             * visited
096:             * @param p is the personality of Speedo 
097:             */
098:            public FieldAccessModifier(final ClassVisitor cv,
099:                    final SpeedoClass sc, Logger logger, Personality p) {
100:                super (cv, p, logger);
101:                this .speedoClass = sc;
102:                this .smi = speedoClass.moPackage.xmlDescriptor.smi;
103:                owner = getJVMClassName(sc.getFQName());
104:                nbfields = speedoClass.computeFieldNumbers();
105:                fieldsOwner = NamingRules.fieldsName(owner);
106:            }
107:
108:            // IMPLEMENTATION OF THE ClassVisitor INTERFACE //
109:            // ---------------------------------------------//
110:
111:            public void visit(final int version, final int access,
112:                    final String name, final String super Name,
113:                    final String[] interfaces, final String sourceFile) {
114:                cv.visit(version, access, name, super Name, interfaces,
115:                        sourceFile);
116:            }
117:
118:            public CodeVisitor visitMethod(final int access, final String name,
119:                    final String desc, final String[] exceptions,
120:                    final Attribute attrs) {
121:                CodeVisitor covis = this .cv.visitMethod(access, name, desc,
122:                        exceptions, attrs);
123:                if ((access & Constants.ACC_ABSTRACT) != 0) {
124:                    // nothing to be modified for abstract methods
125:                    logger.log(BasicLevel.DEBUG, "ignore the abstract method "
126:                            + name + " " + desc);
127:                    return covis;
128:                }
129:                if (name.startsWith("jdo") && !name.equals("jdoPreDelete")
130:                        && !name.equals("jdoPreStore")
131:                        && !name.equals("jdoPreClear")
132:                        && !name.equals("jdoPostLoad")) {
133:                    // do not modify the accessor methods generated by the enhancer
134:                    logger.log(BasicLevel.DEBUG, "ignoe the method " + name
135:                            + " " + desc);
136:                    return covis;
137:                }
138:                if (name.equals("<clinit>")
139:                        || (access & Constants.ACC_STATIC) != 0) {
140:                    // for static methods replace accesses to fields by calls to
141:                    // accessor methods.
142:                    return new DefaultCodeAccessorModifier(desc, false, covis,
143:                            name, this );
144:                } else {
145:                    // Fields accessing to 'this' are replaced by field accesses to
146:                    // the state object (the added actual parameter), and a header
147:                    // is added to call speedoReadIntention or speedoWriteIntention. In case of the
148:                    // constructor the call to speedoReadIntention or speedoWriteIntention is added
149:                    // after the super call.
150:                    return new OptimisticCodeAccessorModifier(desc, covis,
151:                            name, this );
152:                }
153:            }
154:
155:            // OTHER METHODS //
156:            // --------------//
157:
158:            /**
159:             * Looks for a specific <code>SpeedoField</code> in the object model.
160:             *
161:             * @param name the name of the field to be fetched
162:             * @param className the complete class name that the field belongs to
163:             * @return the corresponding SpeedoField if it exists, null either
164:             */
165:            SpeedoField fetchJDOField(final String name, final String className) {
166:                SpeedoClass c = smi.getSpeedoClass(className);
167:                if (c != null) {
168:                    SpeedoField speedoField = null;
169:                    //try to find the field in the current class
170:                    // and in its parents (if any)
171:                    while (speedoField == null && c != null) {
172:                        speedoField = (SpeedoField) c.fields.get(name);
173:                        c = c.getSuper();
174:                    }
175:                    return speedoField;
176:                } else {
177:                    return null;
178:                }
179:            }
180:
181:        }
182:
183:        /**
184:         * The default method code modifier, used for constructors, static methods
185:         * and class initializers. This code modifier does not modify accesses to
186:         * 'this' fields, but replaces accesses to other fields by calls to accessor
187:         * methods.
188:         */
189:        class DefaultCodeAccessorModifier extends CodeAdapter {
190:
191:            /**
192:             * Descriptor of the visited method
193:             */
194:            protected String desc;
195:
196:            /**
197:             * Types of the parameters of the visited method
198:             */
199:            protected Type[] types;
200:
201:            /**
202:             * Total size of the formal parameters of the visited method
203:             */
204:            protected int params;
205:
206:            /**
207:             * A label that designates the start of the original method code
208:             */
209:            private Label start;
210:
211:            /**
212:             * A label that designates the start of the header added to the method
213:             */
214:            private Label header;
215:
216:            /**
217:             * A list of instructions that have been visited but not yet regenerated
218:             * through {@link #cv cv}. This list is a list of Insn objects. It is
219:             * used to be able to modify an ALOAD 0 instruction long after it has
220:             * been visited by this visitor, when a GETFIELD or PUTFIELD instruction
221:             * is encountered.
222:             */
223:            protected List insns;
224:
225:            /**
226:             * Symbolic state of the execution stack at the current bytecode
227:             * instruction. The last element corresponds to the top of the stack.
228:             * Each element is either <tt>null</tt> or an Integer object. The last
229:             * case signifies that, at execution time, and at the current bytecode
230:             * instruction, this stack element will contain 'this'. Moreover the
231:             * integer value indicates the index in 'insns' of the instruction that
232:             * pushed this value on the stack.
233:             */
234:            protected List stack;
235:
236:            /**
237:             * Indicates the fields that the visited method may read on 'this'.
238:             * If the i-th bit is set to 1, then the i-th field may be read.
239:             */
240:            protected long[] readFields;
241:
242:            /**
243:             * Indicates the fields that the visited method may write on 'this'.
244:             * If the i-th bit is set to 1, then the i-th field may be witten.
245:             */
246:            protected long[] writtenFields;
247:
248:            boolean isConstructor;
249:
250:            boolean firstIns = false;
251:
252:            FieldAccessModifier cam;
253:
254:            /**
255:             * Constructs a new {@link DefaultCodeAccessorModifier}.
256:             *
257:             * @param desc the descriptor of the visited method
258:             * @param hasHeader indicates if a header must be added to the visited
259:             * method
260:             * @param cv the code visitor to be used to generate the modified method
261:             */
262:            public DefaultCodeAccessorModifier(final String desc,
263:                    final boolean hasHeader, final CodeVisitor cv,
264:                    final String name, final FieldAccessModifier _cam) {
265:                super (cv);
266:                this .cam = _cam;
267:                isConstructor = name.equals("<init>");
268:                cam.getLogger()
269:                        .log(
270:                                BasicLevel.INFO,
271:                                "visit the method " + name + " " + desc
272:                                        + " (const=" + isConstructor
273:                                        + ", header=" + hasHeader + ")");
274:                firstIns = true;
275:                int size = (cam.nbfields / 64)
276:                        + ((cam.nbfields % 64) > 0 ? 1 : 0);
277:                writtenFields = new long[size];
278:                readFields = new long[size];
279:                this .desc = desc;
280:                this .types = Type.getArgumentTypes(desc);
281:                params = 1;
282:                for (int i = 0; i < types.length; ++i) {
283:                    params += types[i].getSize();
284:                }
285:                this .insns = new ArrayList();
286:                this .stack = new ArrayList();
287:                if (hasHeader && !isConstructor) {
288:                    cam.getLogger().log(BasicLevel.DEBUG,
289:                            "Add Jump at the begin of method: " + name);
290:                    addJumpHeader();
291:                }
292:            }
293:
294:            protected void addJumpHeader() {
295:                start = new Label();
296:                header = new Label();
297:                flushInsns();
298:                cv.visitJumpInsn(Constants.GOTO, header);
299:                visitLabel(start);
300:            }
301:
302:            // IMPLEMENTATION OF THE CodeVisitor INTERFACE //
303:            // --------------------------------------------//
304:
305:            public void visitInsn(final int opcode) {
306:                if ((opcode >= Constants.IRETURN && opcode <= Constants.RETURN)
307:                        || opcode == Constants.ATHROW) {
308:                    flushInsns();
309:                    cv.visitInsn(opcode);
310:                } else {
311:                    if (opcode == Constants.DUP && stack.size() > 0) {
312:                        // optimization for DUP
313:                        stack.add(stack.get(stack.size() - 1));
314:                        cam.getLogger().log(BasicLevel.DEBUG, "stack=" + stack);
315:                    } else {
316:                        updateStack(FieldAccessModifier.SIZE[opcode]);
317:                    }
318:                    insns.add(new Insn(opcode));
319:                }
320:            }
321:
322:            public void visitIntInsn(final int opcode, final int operand) {
323:                updateStack(FieldAccessModifier.SIZE[opcode]);
324:                insns.add(new Insn(true, opcode, operand));
325:            }
326:
327:            public void visitVarInsn(final int opcode, final int var) {
328:                if (opcode == Constants.RET) {
329:                    flushInsns();
330:                    cv.visitVarInsn(opcode, var);
331:                } else {
332:                    if (opcode == Constants.ALOAD && var == 0) {
333:                        stack.add(new Integer(insns.size()));
334:                        cam.getLogger().log(BasicLevel.DEBUG, "stack=" + stack);
335:                    } else {
336:                        updateStack(FieldAccessModifier.SIZE[opcode]);
337:                    }
338:                    insns.add(new Insn(false, opcode, var));
339:                }
340:            }
341:
342:            public void visitTypeInsn(final int opcode, final String desc) {
343:                updateStack(FieldAccessModifier.SIZE[opcode]);
344:                insns.add(new Insn(opcode, desc));
345:            }
346:
347:            public void visitFieldInsn(final int opcode, final String owner,
348:                    final String name, final String desc) {
349:                SpeedoField field = cam.fetchJDOField(name, owner.replace('/',
350:                        '.'));
351:                char c = desc.charAt(0);
352:                int fieldSize = (c == 'D' || c == 'J' ? 2 : 1);
353:                //Calculate if the field type is reference to a persistence object
354:                // (use an accessor) or primitive field (direct access)
355:                // primitive fields or java.lang.* or java.math.*
356:                boolean directFieldAccess = c != 'L'
357:                        || desc.startsWith("Ljava/lang/")
358:                        || desc.startsWith("Ljava/math/");
359:                int stackSizeVariation;
360:                int this InsnIndex = -1;
361:                switch (opcode) {
362:                case Constants.GETSTATIC:
363:                    stackSizeVariation = fieldSize;
364:                    //No modification
365:                    break;
366:                case Constants.PUTSTATIC:
367:                    stackSizeVariation = -fieldSize;
368:                    //No modification
369:                    break;
370:                case Constants.GETFIELD:
371:                    stackSizeVariation = fieldSize - 1;
372:                    if (field == null) {
373:                        break;
374:                    }
375:                    if (directFieldAccess) {
376:                        this InsnIndex = getThisInsnIndex(0);
377:                        //If the field holder is not 'this' then use a getter
378:                        directFieldAccess = this InsnIndex != -1;
379:                    }
380:                    if (directFieldAccess) { //direct field access
381:                        readFields[field.number / 64] |= (1L << (field.number % 64));
382:                        visitThisFieldInsn(opcode, owner, name, desc,
383:                                this InsnIndex);
384:                        cam.getLogger().log(BasicLevel.DEBUG,
385:                                "direct field use: " + name);
386:                    } else { //use an getter
387:                        String getterName = NamingRules.getterName(field);
388:                        String getterDesc = "()" + desc;
389:                        insns.add(new Insn(Constants.INVOKEVIRTUAL, owner,
390:                                getterName, getterDesc));
391:                        cam.getLogger().log(BasicLevel.DEBUG,
392:                                "getter assignment: " + getterName);
393:                    }
394:                    updateStack(stackSizeVariation);
395:                    return;
396:                case Constants.PUTFIELD:
397:                    stackSizeVariation = 0 - (fieldSize + 1);
398:                    if (field == null) {
399:                        break;
400:                    }
401:                    if (directFieldAccess) {
402:                        this InsnIndex = getThisInsnIndex(fieldSize);
403:                        //If the field holder is not 'this' then use a setter
404:                        directFieldAccess = this InsnIndex != -1;
405:                    }
406:                    if (directFieldAccess) { // direct field access
407:                        writtenFields[field.number / 64] |= (1L << (field.number % 64));
408:                        visitThisFieldInsn(opcode, owner, name, desc,
409:                                this InsnIndex);
410:                        cam.getLogger().log(BasicLevel.DEBUG,
411:                                "direct field assignment: " + name);
412:                    } else { //use an setter
413:                        String setterName = NamingRules.setterName(field);
414:                        String setterDesc = "(" + desc + ")V";
415:                        insns.add(new Insn(Constants.INVOKEVIRTUAL, owner,
416:                                setterName, setterDesc));
417:                        cam.getLogger().log(BasicLevel.DEBUG,
418:                                "setter assignment: " + setterName);
419:                    }
420:                    updateStack(stackSizeVariation);
421:                    return;
422:                default:
423:                    stackSizeVariation = -fieldSize - 1;
424:                }
425:                updateStack(stackSizeVariation);
426:                insns.add(new Insn(opcode, owner, name, desc));
427:            }
428:
429:            /**
430:             * Calculates the index of the ALOAD0 instruction with the field index
431:             * @param fieldidx
432:             * @return -1 if not ALOAD0 found, otherwise an integer value
433:             */
434:            private int getThisInsnIndex(int fieldidx) {
435:                int stackSize = stack.size();
436:                if (stackSize > 0 && stackSize > fieldidx) {
437:                    Integer i = (Integer) stack.get(stackSize - 1 - fieldidx);
438:                    if (i != null) {
439:                        return i.intValue();
440:                    } else {
441:                        cam.getLogger().log(BasicLevel.DEBUG,
442:                                "i is null (stack: " + stack + ")");
443:                    }
444:                } else {
445:                    cam.getLogger().log(BasicLevel.DEBUG,
446:                            "stack size: " + stackSize);
447:                }
448:                return -1;
449:            }
450:
451:            public void visitMethodInsn(final int opcode, final String owner,
452:                    final String name, final String desc) {
453:                // computes the stack size variation
454:                int size = opcode == Constants.INVOKESTATIC ? 0 : 1;
455:                int c = 1;
456:                while (true) {
457:                    char car = desc.charAt(c++);
458:                    if (car == ')') {
459:                        car = desc.charAt(c);
460:                        if (car == 'V') {
461:                            size = -size;
462:                        } else {
463:                            size = (car == 'D' || car == 'J' ? 2 : 1) - size;
464:                        }
465:                        break;
466:                    } else if (car == 'L') {
467:                        while (desc.charAt(c++) != ';') {
468:                        }
469:                        size += 1;
470:                    } else if (car == '[') {
471:                        while ((car = desc.charAt(c)) == '[') {
472:                            ++c;
473:                        }
474:                        if (car == 'D' || car == 'J') {
475:                            size -= 1;
476:                        }
477:                    } else if (car == 'D' || car == 'J') {
478:                        size += 2;
479:                    } else {
480:                        size += 1;
481:                    }
482:                }
483:                updateStack(size);
484:                insns.add(new Insn(opcode, owner, name, desc));
485:                if (firstIns && isConstructor) {
486:                    if (opcode == Constants.INVOKESPECIAL) {
487:                        firstIns = false;
488:                        generateConstructorHeader();
489:                    }
490:                }
491:            }
492:
493:            public void visitJumpInsn(final int opcode, final Label label) {
494:                flushInsns();
495:                cv.visitJumpInsn(opcode, label);
496:            }
497:
498:            public void visitLabel(final Label label) {
499:                insns.add(new Insn(label));
500:            }
501:
502:            public void visitLdcInsn(final Object cst) {
503:                int size;
504:                if (cst instanceof  Double || cst instanceof  Long) {
505:                    size = 2;
506:                } else {
507:                    size = 1;
508:                }
509:                updateStack(size);
510:                insns.add(new Insn(cst));
511:            }
512:
513:            public void visitIincInsn(final int var, final int increment) {
514:                // no stack change
515:                insns.add(new Insn(var, increment));
516:            }
517:
518:            public void visitTableSwitchInsn(final int min, final int max,
519:                    final Label dflt, final Label labels[]) {
520:                flushInsns();
521:                cv.visitTableSwitchInsn(min, max, dflt, labels);
522:            }
523:
524:            public void visitLookupSwitchInsn(final Label dflt,
525:                    final int keys[], final Label labels[]) {
526:                flushInsns();
527:                cv.visitLookupSwitchInsn(dflt, keys, labels);
528:            }
529:
530:            public void visitMultiANewArrayInsn(final String desc,
531:                    final int dims) {
532:                updateStack(1 - dims);
533:                insns.add(new Insn(desc, dims));
534:            }
535:
536:            public void visitTryCatchBlock(final Label start, final Label end,
537:                    final Label handler, final String type) {
538:                flushInsns();
539:                super .visitTryCatchBlock(start, end, handler, type);
540:            }
541:
542:            public void visitMaxs(final int maxStack, final int maxLocals) {
543:                flushInsns();
544:                if (header != null) {
545:                    cv.visitLabel(header);
546:                    generateMethodHeader();
547:                    cv.visitJumpInsn(Constants.GOTO, start);
548:                }
549:                cv.visitMaxs(maxStack, maxLocals);
550:            }
551:
552:            public void visitLocalVariable(final String name,
553:                    final String desc, final Label start, final Label end,
554:                    final int index) {
555:                flushInsns();
556:                super .visitLocalVariable(name, desc, start, end, index);
557:            }
558:
559:            public void visitLineNumber(final int line, final Label start) {
560:                flushInsns();
561:                super .visitLineNumber(line, start);
562:            }
563:
564:            // OTHER METHODS //
565:            // --------------//
566:
567:            /**
568:             * Generates a header which is added at the begining of the the visited
569:             * method. The default implementation of this method does nothing.
570:             */
571:            protected void generateMethodHeader() {
572:                // does nothing
573:            }
574:
575:            protected void generateConstructorHeader() {
576:                // does nothing
577:            }
578:
579:            /**
580:             * Visits field access instruction on 'this'.
581:             *
582:             * @param opcode GETFIELD or PUTFIELD
583:             * @param owner internal name of the owner class of the field
584:             * @param name name of the field
585:             * @param desc type descriptor of te field
586:             * @param pushThisInsn index in {@link #insns insns} of the ALOAD 0
587:             * instruction that pushed the 'this' value which is, at this bytecode
588:             * instruction, at the top (for GETFIELD) or just under the top (for
589:             * PUTFIELD) of the stack.
590:             */
591:            protected void visitThisFieldInsn(final int opcode,
592:                    final String owner, final String name, final String desc,
593:                    final int pushThisInsn) {
594:                // keeps the field access instructions on 'this' unchanged
595:                insns.add(new Insn(opcode, owner, name, desc));
596:            }
597:
598:            /**
599:             * Makes {@link #cv cv} visit the instructions stored in {@link #insns
600:             * insns}, and then clear this list, as well as the stack. This method
601:             * is used when the end of method is encountered, but also each time
602:             * a jump or return statement is visited, because we can not easily know
603:             * the stack state at the next instruction (this is possible but
604:             * complicated: we prefer to keep the algorithm simple. The cost of this
605:             * simplification is that some field accesses on 'this' will not be
606:             * statically detected, and will therefore be replaced by calls to
607:             * accessor methods, which is less efficient but safe).
608:             */
609:            protected void flushInsns() {
610:                int n = insns.size();
611:                for (int i = 0; i < n; ++i) {
612:                    ((Insn) insns.get(i)).accept(cv);
613:                }
614:                insns.clear();
615:                stack.clear();
616:                cam.getLogger().log(BasicLevel.DEBUG, "stack=" + stack);
617:            }
618:
619:            /**
620:             * Pushes some <tt>null</tt> elements on the stack, or pops some
621:             * elements.
622:             * @param n the number of elements to be pushed (if n is positive), or
623:             * to be popped (if n is negative).
624:             */
625:            private void updateStack(final int n) {
626:                int size = stack.size();
627:                if (n > 0) {
628:                    for (int i = 0; i < n; ++i) {
629:                        stack.add(null);
630:                        cam.getLogger().log(BasicLevel.DEBUG, "stack=" + stack);
631:                    }
632:                } else {
633:                    int m = -n;
634:                    if (m >= size) {
635:                        stack.clear();
636:                        cam.getLogger().log(BasicLevel.DEBUG, "stack=" + stack);
637:                    } else {
638:                        for (int i = 0; i < m; ++i) {
639:                            stack.remove(--size);
640:                            cam.getLogger().log(BasicLevel.DEBUG,
641:                                    "stack=" + stack);
642:                        }
643:                    }
644:                }
645:            }
646:        }
647:
648:        /**
649:         * The method code modifier used for all non static methods. This code modifier
650:         * replaces accesses to 'this' fields by accesses to the 'state' object, and
651:         * replaces accesses to other fields by calls to accessor methods. It also
652:         * adds a header to the method to call speedoReadIntention or speedoWriteIntention.
653:         */
654:        class OptimisticCodeAccessorModifier extends
655:                DefaultCodeAccessorModifier {
656:
657:            /**
658:             * Constructs a new {@link OptimisticCodeAccessorModifier}.
659:             *
660:             * @param desc the descriptor of the PESSIMISTIC method, and not of
661:             * the optimistic one
662:             * @param cv the code visitor to be used to generate the modified method
663:             */
664:            public OptimisticCodeAccessorModifier(final String desc,
665:                    final CodeVisitor cv, String name, FieldAccessModifier cam) {
666:                super (desc, true, cv, name, cam);
667:            }
668:
669:            // OVERRIDEN METHODS //
670:            // ------------------//
671:
672:            public void visitVarInsn(final int opcode, final int var) {
673:                // shifts local variables that are just after the original actual
674:                // parameters (ie without counting the added formal paramter), to
675:                // make room for the added actual parameter
676:                super .visitVarInsn(opcode, var >= params ? var + 1 : var);
677:            }
678:
679:            public void visitIincInsn(final int var, final int increment) {
680:                // shifts local variables that are just after the original actual
681:                // parameters (ie without counting the added formal paramter), to
682:                // make room for the added actual parameter
683:                super .visitIincInsn(var >= params ? var + 1 : var, increment);
684:            }
685:
686:            public void visitMaxs(final int maxStack, final int maxLocals) {
687:                boolean allUnmodified = true;
688:                for (int i = 0; allUnmodified && i < cam.nbfields; i++) {
689:                    allUnmodified &= readFields[i / 64] == 0
690:                            & writtenFields[i / 64] == 0;
691:                }
692:                if (allUnmodified) {
693:                    super .visitMaxs(maxStack, maxLocals + (cam.nbfields / 64)
694:                            + 1);
695:                } else {
696:                    super .visitMaxs(Math.max(maxStack, 4), maxLocals
697:                            + (cam.nbfields / 64) + 1);
698:                }
699:            }
700:
701:            protected void generateConstructorHeader() {
702:                cam
703:                        .getLogger()
704:                        .log(BasicLevel.DEBUG,
705:                                "Create reference state after the super in the constructor");
706:                flushInsns();
707:
708:                //if (speedoGetReferenceState() == null) {
709:                cv.visitVarInsn(Constants.ALOAD, 0);
710:                cv.visitMethodInsn(Constants.INVOKEVIRTUAL, cam.owner,
711:                        "speedoGetReferenceState",
712:                        "()Lorg/objectweb/speedo/mim/api/StateItf;");
713:                Label afterSetState = new Label();
714:                cv.visitJumpInsn(Constants.IFNONNULL, afterSetState);
715:
716:                //creating the reference state by calling
717:                // 'speedoSetReferenceState(speedoCreateState())'
718:                cv.visitVarInsn(Constants.ALOAD, 0);
719:                cv.visitVarInsn(Constants.ALOAD, 0);
720:                cv.visitMethodInsn(Constants.INVOKEVIRTUAL, cam.owner,
721:                        "speedoCreateState",
722:                        "()Lorg/objectweb/speedo/mim/api/StateItf;");
723:                cv.visitMethodInsn(Constants.INVOKEVIRTUAL, cam.owner,
724:                        "speedoSetReferenceState",
725:                        "(Lorg/objectweb/speedo/mim/api/StateItf;)V");
726:
727:                cv.visitLabel(afterSetState);
728:
729:                //Load the reference state in a local variable
730:                cv.visitVarInsn(Constants.ALOAD, 0);
731:                cv.visitMethodInsn(Constants.INVOKEVIRTUAL, cam.owner,
732:                        "speedoGetReferenceState",
733:                        "()Lorg/objectweb/speedo/mim/api/StateItf;");
734:                cv.visitTypeInsn(Constants.CHECKCAST, NamingRules
735:                        .fieldsName(cam.owner));
736:                cv.visitVarInsn(Constants.ASTORE, params);
737:            }
738:
739:            protected void generateMethodHeader() {
740:                boolean allUnmodified = true;
741:                boolean hasWritten = false;
742:                for (int i = 0; allUnmodified && i < cam.nbfields; i++) {
743:                    hasWritten |= writtenFields[i / 64] != 0;
744:                    allUnmodified &= readFields[i / 64] == 0
745:                            & writtenFields[i / 64] == 0;
746:                }
747:                cam.getLogger().log(BasicLevel.DEBUG,
748:                        "allUnmodified=" + allUnmodified);
749:                if (allUnmodified) {
750:                    return;
751:                }
752:                // generate code corresponding to
753:                // 'XXXFields state = speedoRead/WriteIntention(fieldIds);'
754:                cv.visitVarInsn(Constants.ALOAD, 0);
755:                // we always use readFields, even for a writeIntention
756:                // (fields that are written but not read do not need to be loaded
757:                // from the database before being used)
758:
759:                // define the long[] value such as new long[]{56L, 45L, 45646163}
760:                Util.visitIntConstant(cv, readFields.length);
761:                cv.visitIntInsn(Constants.NEWARRAY, Constants.T_LONG);
762:                StringBuffer sb = new StringBuffer();
763:                sb.append(hasWritten ? "speedoWriteIntention"
764:                        : "speedoReadIntention");
765:                sb.append("(new long[]{");
766:                String sep = "";
767:                for (int i = 0; i < readFields.length; i++) {
768:                    cv.visitInsn(Constants.DUP);
769:                    Util.visitIntConstant(cv, i);
770:                    Util
771:                            .visitLongConstant(cv, readFields[i]
772:                                    | writtenFields[i]);
773:                    sb.append(sep);
774:                    sep = ", ";
775:                    sb.append(readFields[i] | writtenFields[i]);
776:                    sb.append("L");
777:                    cv.visitInsn(Constants.LASTORE);
778:                }
779:                sb.append(")");
780:                cam.getLogger().log(BasicLevel.INFO, sb.toString());
781:                cv.visitMethodInsn(Constants.INVOKEVIRTUAL, cam.owner,
782:                        hasWritten ? "speedoWriteIntention"
783:                                : "speedoReadIntention",
784:                        "([J)Lorg/objectweb/speedo/mim/api/StateItf;");
785:                //Store return value
786:                cv.visitTypeInsn(Constants.CHECKCAST, NamingRules
787:                        .fieldsName(cam.owner));
788:                cv.visitVarInsn(Constants.ASTORE, params);
789:            }
790:
791:            protected void visitThisFieldInsn(final int opcode,
792:                    final String owner, final String name, final String desc,
793:                    final int pushThisInsn) {
794:                // replaces the field access instructions on 'this' by field
795:                // access instructions on the state object
796:                cam.getLogger().log(BasicLevel.DEBUG,
797:                        "replace ALOAD0 at " + pushThisInsn);
798:                insns.set(pushThisInsn,
799:                        new Insn(false, Constants.ALOAD, params));
800:                insns.add(new Insn(opcode, cam.fieldsOwner, name, desc));
801:            }
802:        }
803:
804:        /**
805:         * Object representation of a sequential bytecode instruction. A sequential
806:         * bytecode instruction is any instruction that is not a jump, a return,
807:         * a ret or a switch instruction. A single class is used to represent
808:         * several types of bytecode instruction, in order to minimize the size of
809:         * the outer class.
810:         */
811:        class Insn {
812:
813:            // the sequential bytecode instruction types
814:            final static int INSN = 1;
815:            final static int INT_INSN = 2;
816:            final static int VAR_INSN = 3;
817:            final static int TYPE_INSN = 4;
818:            final static int FIELD_INSN = 5;
819:            final static int METH_INSN = 6;
820:            final static int LABEL_INSN = 7;
821:            final static int LDC_INSN = 8;
822:            final static int IINC_INSN = 9;
823:            final static int MANA_INSN = 10;
824:
825:            /**
826:             * Type of this instruction
827:             */
828:            private int type;
829:
830:            /**
831:             * Opcode of this instruction
832:             */
833:            private int opcode;
834:
835:            // operand(s) of this instruction
836:
837:            private int int1, int2;
838:            private String str1, str2, str3;
839:            private Object obj;
840:
841:            public Insn(final int opcode) {
842:                this .type = INSN;
843:                this .opcode = opcode;
844:            }
845:
846:            public Insn(final boolean intInsn, final int opcode, final int val) {
847:                this .type = intInsn ? INT_INSN : VAR_INSN;
848:                this .opcode = opcode;
849:                this .int1 = val;
850:            }
851:
852:            public Insn(final int opcode, final String desc) {
853:                this .type = TYPE_INSN;
854:                this .opcode = opcode;
855:                this .str1 = desc;
856:            }
857:
858:            public Insn(final int opcode, final String owner,
859:                    final String name, final String desc) {
860:                this .type = opcode <= Constants.PUTFIELD ? FIELD_INSN
861:                        : METH_INSN;
862:                this .opcode = opcode;
863:                this .str1 = owner;
864:                this .str2 = name;
865:                this .str3 = desc;
866:            }
867:
868:            public Insn(final Label label) {
869:                this .type = LABEL_INSN;
870:                this .obj = label;
871:            }
872:
873:            public Insn(final Object cst) {
874:                this .type = LDC_INSN;
875:                this .obj = cst;
876:            }
877:
878:            public Insn(final int var, final int inc) {
879:                this .type = IINC_INSN;
880:                this .int1 = var;
881:                this .int2 = inc;
882:            }
883:
884:            public Insn(final String desc, final int dims) {
885:                this .type = MANA_INSN;
886:                this .str1 = desc;
887:                this .int1 = dims;
888:            }
889:
890:            /**
891:             * Makes the given code visitor visit this instruction.
892:             *
893:             * @param cv a code visitor
894:             */
895:            public void accept(final CodeVisitor cv) {
896:                switch (type) {
897:                case INSN:
898:                    cv.visitInsn(opcode);
899:                    break;
900:                case INT_INSN:
901:                    cv.visitIntInsn(opcode, int1);
902:                    break;
903:                case VAR_INSN:
904:                    cv.visitVarInsn(opcode, int1);
905:                    break;
906:                case TYPE_INSN:
907:                    cv.visitTypeInsn(opcode, str1);
908:                    break;
909:                case FIELD_INSN:
910:                    cv.visitFieldInsn(opcode, str1, str2, str3);
911:                    break;
912:                case METH_INSN:
913:                    cv.visitMethodInsn(opcode, str1, str2, str3);
914:                    break;
915:                case LABEL_INSN:
916:                    cv.visitLabel((Label) obj);
917:                    break;
918:                case LDC_INSN:
919:                    cv.visitLdcInsn(obj);
920:                    break;
921:                case IINC_INSN:
922:                    cv.visitIincInsn(int1, int2);
923:                    break;
924:                default:
925:                    cv.visitMultiANewArrayInsn(str1, int1);
926:                }
927:            }
928:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.