Source Code Cross Referenced for MethodWeaver.java in  » Byte-Code » PROSE » ch » ethz » prose » jvmai » jikesrvm » advice_weaver » 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 » PROSE » ch.ethz.prose.jvmai.jikesrvm.advice_weaver 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        //
002:        //  This file is part of the prose package.
003:        //
004:        //  The contents of this file are subject to the Mozilla Public License
005:        //  Version 1.1 (the "License"); you may not use this file except in
006:        //  compliance with the License. You may obtain a copy of the License at
007:        //  http://www.mozilla.org/MPL/
008:        //
009:        //  Software distributed under the License is distributed on an "AS IS" basis,
010:        //  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
011:        //  for the specific language governing rights and limitations under the
012:        //  License.
013:        //
014:        //  The Original Code is prose.
015:        //
016:        //  The Initial Developer of the Original Code is Angela Nicoara. Portions
017:        //  created by Angela Nicoara are Copyright (C) 2002 Angela Nicoara.
018:        //  All Rights Reserved.
019:        //
020:        //  Contributor(s):
021:        //  $Id$
022:        //  =====================================================================
023:        //
024:        //  (history at end)
025:        //
026:
027:        package ch.ethz.prose.jvmai.jikesrvm.advice_weaver;
028:
029:        import java.io.*;
030:        import java.lang.reflect.Field;
031:        import java.lang.reflect.Method;
032:        import java.util.*;
033:
034:        import org.apache.bcel.Constants;
035:        import org.apache.bcel.Repository;
036:        import org.apache.bcel.classfile.*;
037:        import org.apache.bcel.generic.*;
038:        import org.apache.bcel.verifier.*;
039:
040:        import com.ibm.JikesRVM.classloader.VM_ClassEvolution;
041:        import com.ibm.JikesRVM.classloader.VM_Field;
042:
043:        /**
044:         * Modifies a given method to support advice execution. For each activated join
045:         * point an advice is woven into the bytecode of the method and then installed
046:         * in the VM using the services of VM_ClassEvolution.
047:         * 
048:         * @version	$Revision$
049:         * @author  Johann Gyger
050:         * @author	Angela Nicoara
051:         */
052:        public class MethodWeaver {
053:
054:            /**
055:             * String representation of the JVMAI class.
056:             */
057:            public static final String JVMAI_CLASS = "ch.ethz.prose.jvmai.jikesrvm.advice_weaver.AdviceJVMAI";
058:
059:            /**
060:             * Should the bytecodes be verified before installing them into the VM?
061:             */
062:            protected static final boolean verifyBytecodes;
063:
064:            static {
065:                String p = System.getProperty(
066:                        "ch.ethz.prose.jikesrvm.MethodWeaver.verifyBytecodes",
067:                        "");
068:                verifyBytecodes = p.toLowerCase().equals("true");
069:            }
070:
071:            /**
072:             * Collection of all method weavers. For each method there exists exactly one
073:             * method weaver in the system.
074:             */
075:            protected static Map weavers = new HashMap();
076:
077:            /**
078:             * Get a unique method weaver for `target'.
079:             * 
080:             * @param target method that will be woven
081:             */
082:            public static synchronized MethodWeaver getWeaver(Method target) {
083:                if (target == null)
084:                    throw new NullPointerException(
085:                            "Parameter `target' must not be null.");
086:
087:                MethodWeaver result = (MethodWeaver) weavers.get(target
088:                        .toString());
089:                if (result == null) {
090:                    result = new MethodWeaver(target);
091:                    weavers.put(target.toString(), result);
092:                }
093:
094:                return result;
095:            };
096:
097:            /**
098:             * Re-weave all modified methods and activate them in the VM.
099:             */
100:            public static synchronized void commit() {
101:                Iterator it = weavers.values().iterator();
102:                while (it.hasNext()) {
103:                    MethodWeaver mw = (MethodWeaver) it.next();
104:                    if (mw.modified) {
105:                        //System.out.println("MethodWeaver.commit(): " + mw.target);
106:                        mw.weave();
107:                    }
108:                }
109:
110:                VM_ClassEvolution.commit();
111:            }
112:
113:            /**
114:             * Reset all woven methods.
115:             */
116:            public static synchronized void resetAll() {
117:                Iterator it = weavers.values().iterator();
118:                while (it.hasNext()) {
119:                    MethodWeaver mw = (MethodWeaver) it.next();
120:                    if (mw.woven) {
121:                        //System.out.println("MethodWeaver.resetAll(): " + mw.target);
122:                        VM_ClassEvolution.redefineMethod(mw.target,
123:                                mw.originalCode);
124:                    }
125:                }
126:
127:                VM_ClassEvolution.commit();
128:                weavers = new HashMap();
129:            }
130:
131:            /**
132:             * Method bound to this weaver.
133:             */
134:            protected Method target;
135:
136:            /**
137:             * Method identifier;
138:             */
139:            protected int targetId;
140:
141:            /**
142:             * Declaring class of `target'.
143:             */
144:            protected Class targetClass;
145:
146:            /**
147:             * Original bytecode of `target'.
148:             */
149:            protected byte[] originalCode;
150:
151:            /**
152:             * Redefine advice method.
153:             */
154:            protected Method redefineAdvice;
155:
156:            /**
157:             * Is method entry join point activated?
158:             */
159:            protected boolean methodEntryEnabled;
160:
161:            /**
162:             * Is method exit join point activated?
163:             */
164:            protected boolean methodExitEnabled;
165:
166:            /**
167:             * Watched field accesses.
168:             */
169:            protected Map fieldAccessors = new HashMap();
170:
171:            /**
172:             * Watched field modifications.
173:             */
174:            protected Map fieldModifiers = new HashMap();
175:
176:            /**
177:             * Is a re-weaving of the method in this weaver necessary?
178:             */
179:            protected boolean modified;
180:
181:            /**
182:             * Was the method in this weaver woven at least once?
183:             */
184:            protected boolean woven;
185:
186:            /**
187:             * BCEL constant pool generator used during the weaving process.
188:             */
189:            protected ConstantPoolGen cpGen;
190:
191:            /**
192:             * BCEL instruction factory used during the weaving process.
193:             */
194:            protected InstructionFactory instructionFactory;
195:
196:            /**
197:             * BCEL method generator used during the weaving process.
198:             */
199:            protected MethodGen methodGen;
200:
201:            /**
202:             * BCEL instructions that make up the method body (used during weaving
203:             * process).
204:             */
205:            protected InstructionList instructions;
206:
207:            /**
208:             * Create a new method weaver. Use the static method
209:             * {@link #getWeaver(Method)}to obtain a weaver.
210:             * 
211:             * @param target method that will be woven
212:             */
213:            protected MethodWeaver(Method target) {
214:                this .target = target;
215:                targetClass = target.getDeclaringClass();
216:                targetId = java.lang.reflect.JikesRVMSupport
217:                        .getMethodOf(target).getId();
218:                originalCode = VM_ClassEvolution.getMethodCode(target);
219:            }
220:
221:            /**
222:             * Redefine the method in this weaver.
223:             * 
224:             * @param advice method that will be called instead
225:             */
226:            public void setRedefineAdvice(Method advice) {
227:                redefineAdvice = advice;
228:                modified = true;
229:            }
230:
231:            /**
232:             * Enable method entry join point.
233:             * 
234:             * @param flag enable/disable
235:             */
236:            public void setMethodEntryEnabled(boolean flag) {
237:                methodEntryEnabled = flag;
238:                modified = true;
239:            }
240:
241:            /**
242:             * Enable method entry join point.
243:             * 
244:             * @param flag enable/disable
245:             */
246:            public void setMethodExitEnabled(boolean flag) {
247:                methodExitEnabled = flag;
248:                modified = true;
249:            }
250:
251:            /**
252:             * Add a field for which a callback should be woven (for each access).
253:             * 
254:             * @param f watched field
255:             */
256:            public void addFieldAccessor(java.lang.reflect.Field f) {
257:                String key = f.getDeclaringClass().getName() + "#"
258:                        + f.getName();
259:
260:                if (!fieldAccessors.containsKey(key)) {
261:                    //System.out.println("MethodWeaver.addFieldAccessor(): " + target + " / " + f);
262:                    fieldAccessors.put(key, f);
263:                    modified = true;
264:                }
265:            }
266:
267:            /**
268:             * Remove a field for which a callback was woven (for each access).
269:             * 
270:             * @param f watched field
271:             */
272:            public void removeFieldAccessor(java.lang.reflect.Field f) {
273:                String key = f.getDeclaringClass().getName() + "#"
274:                        + f.getName();
275:
276:                if (fieldAccessors.containsKey(key)) {
277:                    fieldAccessors.remove(key);
278:                    modified = true;
279:                }
280:            }
281:
282:            /**
283:             * Add a field for which a callback should be woven (for each modification).
284:             * 
285:             * @param f watched field
286:             */
287:            public void addFieldModifier(java.lang.reflect.Field f) {
288:                String key = f.getDeclaringClass().getName() + "#"
289:                        + f.getName();
290:
291:                if (!fieldModifiers.containsKey(key)) {
292:                    //System.out.println("MethodWeaver.addFieldModifier(): " + target + " / " + f);
293:                    fieldModifiers.put(key, f);
294:                    modified = true;
295:                }
296:            }
297:
298:            /**
299:             * Remove a field for which a callback was woven (for each modification).
300:             * 
301:             * @param f watched field
302:             */
303:            public void removeFieldModifier(java.lang.reflect.Field f) {
304:                String key = f.getDeclaringClass().getName() + "#"
305:                        + f.getName();
306:
307:                if (fieldModifiers.containsKey(key)) {
308:                    fieldModifiers.remove(key);
309:                    modified = true;
310:                }
311:            }
312:
313:            public String debugString() {
314:                StringBuffer sb = new StringBuffer();
315:
316:                sb.append("MethodWeaver for: ");
317:                sb.append(target);
318:                sb.append("\n\tredefineAdvice: ");
319:                sb.append(redefineAdvice);
320:                sb.append("\n\tmethodEntryEnabled: ");
321:                sb.append(methodEntryEnabled);
322:                sb.append("\n\tmethodExitEnabled:  ");
323:                sb.append(methodExitEnabled);
324:                sb.append("\n\tfieldAccessors: ");
325:                sb.append(fieldAccessors.values());
326:                sb.append("\n\tfieldModifiers: ");
327:                sb.append(fieldModifiers.values());
328:                sb.append("\n\tmodified:       ");
329:                sb.append(modified);
330:
331:                return sb.toString();
332:            }
333:
334:            /**
335:             * Weave advice that are associated with the method in this weaver.
336:             */
337:            protected void weave() {
338:                initWeaving();
339:
340:                if (redefineAdvice != null)
341:                    weaveRedefineAdvice();
342:
343:                weaveFieldAdvice();
344:
345:                if (methodEntryEnabled)
346:                    weaveMethodEntryAdvice();
347:
348:                if (methodExitEnabled)
349:                    weaveMethodExitAdvice();
350:
351:                installBytecode();
352:
353:                finishWeaving();
354:            }
355:
356:            /**
357:             * Prepare for weaving by initializing the corresponding fields.
358:             */
359:            protected void initWeaving() {
360:                byte[] code = VM_ClassEvolution
361:                        .getConstantPoolCode(targetClass);
362:                ConstantPool target_cp = ProseSupport.getConstantPool(code);
363:                cpGen = new ConstantPoolGen(target_cp);
364:                instructionFactory = new InstructionFactory(cpGen);
365:                //System.out.println("MethodWever.initWeaving(): " + cpGen.getSize() + " entries in constant pool.");
366:
367:                org.apache.bcel.classfile.Method bm = ProseSupport.getMethod(
368:                        originalCode, target_cp);
369:                //System.out.println("MethodWeaver.initWeaving(): Redefining method: " + target);
370:                //System.out.println(bm);
371:                //System.out.println(bm.getCode());
372:                methodGen = new MethodGen(bm, targetClass.getName(), cpGen);
373:                instructions = methodGen.getInstructionList();
374:            }
375:
376:            /**
377:             * Clean up weaving process.
378:             */
379:            protected void finishWeaving() {
380:                modified = false;
381:                woven = true;
382:                cpGen = null;
383:                methodGen = null;
384:                instructionFactory = null;
385:                instructions = null;
386:            }
387:
388:            /**
389:             * Weave all registered field accesses/modifications.
390:             */
391:            protected void weaveFieldAdvice() {
392:                for (InstructionHandle h = instructions.getStart(); h != null; h = h
393:                        .getNext()) {
394:                    Instruction instr = h.getInstruction();
395:
396:                    if (instr instanceof  FieldInstruction) {
397:                        FieldInstruction fi = (FieldInstruction) instr;
398:                        String key = fi.getClassName(cpGen) + "#"
399:                                + fi.getName(cpGen);
400:
401:                        if ((instr instanceof  GETSTATIC || instr instanceof  GETFIELD)
402:                                && fieldAccessors.containsKey(key)) {
403:                            Field field = (Field) fieldAccessors.get(key);
404:                            VM_Field vm_field = java.lang.reflect.JikesRVMSupport
405:                                    .getFieldOf(field);
406:
407:                            //System.out.println("MethodWeaver.weaveFieldAdvice(): " + target + " GET " + field);
408:                            instructions.insert(h, createFieldAdviceCallback(
409:                                    "onFieldAccess", vm_field));
410:                        } else if ((instr instanceof  PUTSTATIC || instr instanceof  PUTFIELD)
411:                                && fieldModifiers.containsKey(key)) {
412:                            Field field = (Field) fieldModifiers.get(key);
413:                            VM_Field vm_field = java.lang.reflect.JikesRVMSupport
414:                                    .getFieldOf(field);
415:
416:                            // Store new value
417:                            Type field_type = fi.getFieldType(cpGen);
418:                            int local_index = methodGen.getMaxLocals();
419:                            instructions.insert(h, InstructionFactory
420:                                    .createStore(field_type, local_index));
421:                            methodGen.setMaxLocals(local_index
422:                                    + field_type.getSize());
423:
424:                            //System.out.println("MethodWeaver.weaveFieldAdvice(): " + target + " PUT " + field);
425:                            instructions.insert(h, createFieldAdviceCallback(
426:                                    "onFieldModification", vm_field));
427:
428:                            // Load new value
429:                            instructions.insert(h, InstructionFactory
430:                                    .createLoad(field_type, local_index));
431:                        }
432:                    }
433:                }
434:            }
435:
436:            /**
437:             * Weave method redefine advice callback into method body and remove original
438:             * code.
439:             */
440:            protected void weaveRedefineAdvice() {
441:                //System.out.println("MethodWeaver.weaveRedefineAdvice(): " + target + " / " + redefineAdvice);
442:                Class advice_class = redefineAdvice.getDeclaringClass();
443:                byte[] cp_code = VM_ClassEvolution
444:                        .getConstantPoolCode(advice_class);
445:                ConstantPool advice_cp = ProseSupport.getConstantPool(cp_code);
446:                ConstantPoolGen advice_cpg = new ConstantPoolGen(advice_cp);
447:
448:                byte[] advice_code = VM_ClassEvolution
449:                        .getMethodCode(redefineAdvice);
450:                org.apache.bcel.classfile.Method bm = ProseSupport.getMethod(
451:                        advice_code, advice_cp);
452:                MethodGen advice_mg = new MethodGen(bm, advice_class.getName(),
453:                        advice_cpg);
454:                instructions = advice_mg.getInstructionList();
455:                methodGen.setInstructionList(instructions);
456:                methodGen.setMaxLocals(advice_mg.getMaxLocals());
457:
458:                for (InstructionHandle h = instructions.getStart(); h != null; h = h
459:                        .getNext()) {
460:                    Instruction instr = h.getInstruction();
461:
462:                    // Transform local variable (and parameter) access.
463:                    // Decrement each index by 1 because the first parameter was stripped.
464:                    if (instr instanceof  LocalVariableInstruction) {
465:                        LocalVariableInstruction lv_instr = (LocalVariableInstruction) instr;
466:                        if (lv_instr.getIndex() == 0)
467:                            throw new RuntimeException(
468:                                    "No (implicit) `this' usage allowed in advice method: "
469:                                            + redefineAdvice);
470:                        lv_instr.setIndex(lv_instr.getIndex() - 1);
471:                    }
472:
473:                    // Transform constant pool references to constant pool of target class.
474:                    // Add missing constant pool entries in target class.
475:                    if (instr instanceof  CPInstruction) {
476:                        CPInstruction cp_instr = (CPInstruction) instr;
477:                        Constant c = advice_cp.getConstant(cp_instr.getIndex());
478:                        int new_index = cpGen.addConstant(c, advice_cpg);
479:                        cp_instr.setIndex(new_index);
480:                    }
481:                }
482:
483:                // Curb exception handlers
484:                methodGen.removeExceptionHandlers();
485:                CodeExceptionGen[] cegs = advice_mg.getExceptionHandlers();
486:                for (int i = 0; i < cegs.length; i++) {
487:                    CodeExceptionGen ceg = cegs[i];
488:                    methodGen
489:                            .addExceptionHandler(ceg.getStartPC(), ceg
490:                                    .getEndPC(), ceg.getHandlerPC(), ceg
491:                                    .getCatchType());
492:                }
493:            }
494:
495:            /**
496:             * Weave method entry advice callback into method body.
497:             */
498:            protected void weaveMethodEntryAdvice() {
499:                //System.out.println("MethodWeaver.weaveMethodEntryAdvice(): " + target);
500:                instructions
501:                        .insert(createMethodAdviceCallback("onMethodEntry"));
502:            }
503:
504:            /**
505:             * Weave method exit advice callback into method body.
506:             */
507:            protected void weaveMethodExitAdvice() {
508:                //System.out.println("MethodWeaver.weaveMethodExitAdvice(): " + target);
509:                InstructionHandle try_start = instructions.getStart();
510:                InstructionHandle try_end = instructions.getEnd();
511:
512:                // Weave method exit advice (in a finally block)
513:                int local_index = methodGen.getMaxLocals();
514:                InstructionHandle finally_start = instructions
515:                        .append(new ASTORE(local_index));
516:                instructions.append(createMethodAdviceCallback("onMethodExit"));
517:                instructions.append(new RET(local_index++));
518:
519:                // Insert exception handler before finally block
520:                InstructionHandle catch_start = instructions.insert(
521:                        finally_start, new ASTORE(local_index));
522:                instructions.insert(finally_start, new JSR(finally_start));
523:                instructions.insert(finally_start, new ALOAD(local_index++));
524:                instructions.insert(finally_start, new ATHROW());
525:
526:                // Jump to finally block before each return
527:                JumpFinallyVisitor visitor = new JumpFinallyVisitor(
528:                        instructions, try_start, try_end, finally_start,
529:                        local_index);
530:                visitor.go();
531:                local_index += visitor.getLocalSize();
532:
533:                methodGen.setMaxLocals(local_index);
534:                methodGen.addExceptionHandler(try_start, try_end, catch_start,
535:                        null);
536:            }
537:
538:            /**
539:             * Create a method advice callback that can be woven.
540:             * 
541:             * @param callbackMethod method that will be called
542:             * @return instructions that make up the callback
543:             */
544:            protected InstructionList createMethodAdviceCallback(
545:                    String callbackMethod) {
546:                InstructionList il = new InstructionList();
547:
548:                // Push parameter: int methodId
549:                il.append(new PUSH(cpGen, targetId));
550:
551:                // Push parameter: this0
552:                if (methodGen.isStatic())
553:                    il.append(InstructionConstants.ACONST_NULL);
554:                else
555:                    il.append(InstructionFactory.createThis());
556:
557:                // Push parameter: args
558:                loadArgs(il);
559:
560:                // Call advice
561:                il.append(instructionFactory.createInvoke(JVMAI_CLASS,
562:                        callbackMethod, Type.VOID, new Type[] { Type.INT,
563:                                Type.OBJECT, new ArrayType(Type.OBJECT, 1) },
564:                        Constants.INVOKESTATIC));
565:
566:                return il;
567:            }
568:
569:            /**
570:             * Create a field advice callback that can be woven.
571:             * 
572:             * @param callbackMethod method that will be called
573:             * @param fieldId id of field
574:             * @return instructions that make up the callback
575:             */
576:            protected InstructionList createFieldAdviceCallback(
577:                    String callbackMethod, VM_Field field) {
578:                InstructionList il = new InstructionList();
579:
580:                // Push parameter: Object owner
581:                if (field.isStatic())
582:                    il.append(InstructionConstants.ACONST_NULL);
583:                else
584:                    il.append(InstructionConstants.DUP);
585:
586:                // Push parameter: int fieldId
587:                il.append(new PUSH(cpGen, field.getId()));
588:
589:                // Push parameter: int methodId
590:                il.append(new PUSH(cpGen, targetId));
591:
592:                // Push parameter: Object this0
593:                if (methodGen.isStatic())
594:                    il.append(InstructionConstants.ACONST_NULL);
595:                else
596:                    il.append(InstructionFactory.createThis());
597:
598:                // Push parameter: Object[] args
599:                loadArgs(il);
600:
601:                // Call advice
602:                il.append(instructionFactory.createInvoke(JVMAI_CLASS,
603:                        callbackMethod, Type.VOID, new Type[] { Type.OBJECT,
604:                                Type.INT, Type.INT, Type.OBJECT,
605:                                new ArrayType(Type.OBJECT, 1) },
606:                        Constants.INVOKESTATIC));
607:
608:                return il;
609:            }
610:
611:            /**
612:             * Load all arguments.
613:             * 
614:             * @param il list where instructions are appended
615:             */
616:            protected void loadArgs(InstructionList il) {
617:                Type[] arg_types = methodGen.getArgumentTypes();
618:
619:                il.append(new PUSH(cpGen, arg_types.length));
620:                il.append(instructionFactory.createNewArray(Type.OBJECT,
621:                        (short) 1));
622:
623:                int varnum = methodGen.isStatic() ? 0 : 1;
624:                for (int i = 0; i < methodGen.getArgumentTypes().length; i++) {
625:                    il.append(InstructionConstants.DUP);
626:                    il.append(new PUSH(cpGen, i));
627:                    loadArg(il, arg_types[i], varnum);
628:                    il.append(InstructionConstants.AASTORE);
629:                    varnum += arg_types[i].getSize();
630:                }
631:            }
632:
633:            /**
634:             * Load argument at `index' of type `type'. Basic types are wrapped.
635:             * 
636:             * @param il list where instructions are appended
637:             * @param type argument type
638:             * @param index argument index
639:             */
640:            protected void loadArg(InstructionList il, Type type, int index) {
641:                if (type instanceof  BasicType) {
642:                    String wrapper = Constants.CLASS_TYPE_NAMES[type.getType()];
643:                    il.append(instructionFactory.createNew(wrapper));
644:                    il.append(InstructionConstants.DUP);
645:                    il.append(InstructionFactory.createLoad(type, index));
646:                    il.append(instructionFactory.createInvoke(wrapper,
647:                            Constants.CONSTRUCTOR_NAME, Type.VOID,
648:                            new Type[] { type }, Constants.INVOKESPECIAL));
649:                } else if (type instanceof  ReferenceType) {
650:                    il.append(InstructionFactory.createLoad(type, index));
651:                } else {
652:                    throw new RuntimeException("Invalid type: " + type);
653:                }
654:            }
655:
656:            /**
657:             * Install bytecode of woven method into the VM.
658:             */
659:            protected void installBytecode() {
660:                try {
661:                    // Create new method. This will add missing constant pool entries.
662:                    methodGen.setMaxStack();
663:                    methodGen.setMaxLocals();
664:                    org.apache.bcel.classfile.Method bm = methodGen.getMethod();
665:                    instructions.dispose();
666:                    bm.getCode().setAttributes(null);
667:
668:                    // Set new constant pool of target method's declaring class.
669:                    ByteArrayOutputStream bout = new ByteArrayOutputStream();
670:                    DataOutputStream out = new DataOutputStream(bout);
671:                    ConstantPool pool = cpGen.getFinalConstantPool();
672:                    if (verifyBytecodes)
673:                        verify(pool, bm);
674:                    pool.dump(out);
675:                    //System.out.println("MethodWeaver.installBytecode(): Extending constant pool: " + targetClass.getName() + " / " + pool.getLength() + " entries");
676:                    //System.out.println(pool);
677:                    VM_ClassEvolution.extendConstantPool(targetClass, bout
678:                            .toByteArray());
679:
680:                    // Set target method's new code.
681:                    bout = new ByteArrayOutputStream();
682:                    out = new DataOutputStream(bout);
683:                    bm.dump(out);
684:                    //System.out.println("MethodWeaver.installBytecode(): Redefining method: " + target);
685:                    //System.out.println(bm);
686:                    //System.out.println(bm.getCode());
687:                    VM_ClassEvolution
688:                            .redefineMethod(target, bout.toByteArray());
689:                } catch (IOException e) {
690:                    throw new RuntimeException("Oops.", e);
691:                }
692:            }
693:
694:            /**
695:             * Verify bytecodes with the BCEL verifier.
696:             * <p>
697:             * NOTE: Can't be used since even `normal' classes are rejected with Jikes
698:             * RVM 2.3.0.1.
699:             * 
700:             * @param cp constant pool that is used for verification
701:             * @param bm method that is verified
702:             */
703:            protected void verify(ConstantPool cp,
704:                    org.apache.bcel.classfile.Method bm) {
705:                String class_name = target.getDeclaringClass().getName();
706:                //System.out.println("MethodWeaver.verify(): " + target);
707:
708:                try {
709:                    Repository.clearCache();
710:                    JavaClass jc = Repository.lookupClass(class_name);
711:                    jc.setConstantPool(cp);
712:
713:                    org.apache.bcel.classfile.Method[] methods = jc
714:                            .getMethods();
715:                    int method_index = 0;
716:                    for (method_index = 0; method_index < methods.length; method_index++)
717:                        if (methods[method_index].toString().equals(
718:                                bm.toString()))
719:                            break;
720:                    if (method_index == methods.length)
721:                        throw new RuntimeException("Method not found!");
722:                    methods[method_index] = bm;
723:
724:                    Verifier v = VerifierFactory.getVerifier(class_name);
725:                    checkVerificationResult(v.doPass1(), "1");
726:                    checkVerificationResult(v.doPass2(), "2");
727:                    checkVerificationResult(v.doPass3a(method_index), "3a");
728:                    checkVerificationResult(v.doPass3b(method_index), "3b");
729:
730:                    String[] warnings = v.getMessages();
731:                    if (warnings.length != 0)
732:                        System.err.println("Messages:");
733:                    for (int j = 0; j < warnings.length; j++)
734:                        System.err.println(warnings[j]);
735:                } catch (Exception e) {
736:                    System.out.println("Exception: " + e.toString());
737:                }
738:            }
739:
740:            /**
741:             * Check bytecode verification result.
742:             * 
743:             * @param vr verification result which must be checked
744:             * @param pass verification pass
745:             */
746:            protected void checkVerificationResult(VerificationResult vr,
747:                    String pass) {
748:                if (vr != VerificationResult.VR_OK) {
749:                    System.err.println("Verification failed in pass " + pass
750:                            + " for " + target + ".");
751:                    System.err.println(vr);
752:                }
753:            }
754:
755:        }
756:
757:        //======================================================================
758:        //
759:        // $Log$
760:        //
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.